diff --git a/org.springframework.testsuite/build.xml b/org.springframework.testsuite/build.xml
new file mode 100644
index 00000000000..d9b1bf06112
--- /dev/null
+++ b/org.springframework.testsuite/build.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/ivy.xml b/org.springframework.testsuite/ivy.xml
new file mode 100644
index 00000000000..8c468e0bbaa
--- /dev/null
+++ b/org.springframework.testsuite/ivy.xml
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/pom.xml b/org.springframework.testsuite/pom.xml
new file mode 100644
index 00000000000..b4cee14adcb
--- /dev/null
+++ b/org.springframework.testsuite/pom.xml
@@ -0,0 +1,59 @@
+
+
+ 4.0.0
+ org.springframework
+ org.springframework.core
+ jar
+ Spring Core Abstractions and Utilities
+ 3.0.0.M1
+
+
+ com.springsource.repository.bundles.external
+ SpringSource Enterprise Bundle Repository - External Bundle Releases
+ http://repository.springsource.com/maven/bundles/external
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.5
+ 1.5
+
+
+
+
+
+
+ org.apache.commons
+ com.springsource.org.apache.commons.logging
+ 1.1.1
+
+
+ org.apache.log4j
+ com.springsource.org.apache.log4j
+ 1.2.15
+ true
+
+
+ org.apache.commons
+ com.springsource.org.apache.commons.collections
+ 3.2.0
+ true
+
+
+ org.aspectj
+ com.springsource.org.aspectj.weaver
+ 1.6.2.RELEASE
+ true
+
+
+ org.objectweb.asm
+ com.springsource.org.objectweb.asm.commons
+ 2.2.3
+ true
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/SimpleBeforeAdvice.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/SimpleBeforeAdvice.java
new file mode 100644
index 00000000000..402625a27d0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/SimpleBeforeAdvice.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop;
+
+/**
+ * Simple BeforeAdvice for testing.
+ *
+ * @author Dmitriy Kopylenko
+ */
+public interface SimpleBeforeAdvice extends BeforeAdvice {
+
+ void before() throws Throwable;
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/SimpleBeforeAdviceAdapter.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/SimpleBeforeAdviceAdapter.java
new file mode 100644
index 00000000000..8273435502c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/SimpleBeforeAdviceAdapter.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop;
+
+import java.io.Serializable;
+
+import org.aopalliance.aop.Advice;
+import org.aopalliance.intercept.MethodInterceptor;
+
+import org.springframework.aop.framework.adapter.AdvisorAdapter;
+
+/**
+ * @author Dmitriy Kopylenko
+ */
+public class SimpleBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
+
+ public boolean supportsAdvice(Advice advice) {
+ return (advice instanceof SimpleBeforeAdvice);
+ }
+
+ public MethodInterceptor getInterceptor(Advisor advisor) {
+ SimpleBeforeAdvice advice = (SimpleBeforeAdvice) advisor.getAdvice();
+ return new SimpleBeforeAdviceInterceptor(advice) ;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/SimpleBeforeAdviceImpl.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/SimpleBeforeAdviceImpl.java
new file mode 100644
index 00000000000..83715314e74
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/SimpleBeforeAdviceImpl.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop;
+
+/**
+ * @author Dmitriy Kopylenko
+ */
+public class SimpleBeforeAdviceImpl implements SimpleBeforeAdvice {
+
+ private int invocationCounter;
+
+ public void before() throws Throwable {
+ ++invocationCounter;
+ }
+
+ public int getInvocationCounter() {
+ return invocationCounter;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/SimpleBeforeAdviceInterceptor.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/SimpleBeforeAdviceInterceptor.java
new file mode 100644
index 00000000000..d2056190e3e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/SimpleBeforeAdviceInterceptor.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+/**
+ * @author Dmitriy Kopylenko
+ */
+final class SimpleBeforeAdviceInterceptor implements MethodInterceptor {
+
+ private SimpleBeforeAdvice advice;
+
+ public SimpleBeforeAdviceInterceptor(SimpleBeforeAdvice advice) {
+ this.advice = advice;
+ }
+
+ public Object invoke(MethodInvocation mi) throws Throwable {
+ advice.before();
+ return mi.proceed();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AbstractAdviceBindingTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AbstractAdviceBindingTests.java
new file mode 100644
index 00000000000..443e736a520
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AbstractAdviceBindingTests.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import org.springframework.aop.framework.Advised;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
+
+/**
+ * @author Rod Johnson
+ */
+public abstract class AbstractAdviceBindingTests extends AbstractDependencyInjectionSpringContextTests {
+
+ protected ITestBean testBeanProxy;
+
+ protected TestBean testBeanTarget;
+
+ public final void setTestBean(ITestBean injectedTestBean) throws Exception {
+ assertTrue(AopUtils.isAopProxy(injectedTestBean));
+ this.testBeanProxy = injectedTestBean;
+ // we need the real target too, not just the proxy...
+ this.testBeanTarget = (TestBean) ((Advised) testBeanProxy).getTargetSource().getTarget();
+ }
+
+ // Simple test to ensure all is well with the XML file.
+ // Note that this implicitly tests that the arg-names binding is working.
+ public final void testParse() {
+ // Do nothing
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AdviceBindingTestAspect.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AdviceBindingTestAspect.java
new file mode 100644
index 00000000000..4c8476397e8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AdviceBindingTestAspect.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import org.aspectj.lang.JoinPoint;
+
+/**
+ * Aspect used as part of before advice binding tests.
+ *
+ * @author Adrian Colyer
+ */
+public class AdviceBindingTestAspect {
+
+ protected AdviceBindingCollaborator collaborator = null;
+
+ public void setCollaborator(AdviceBindingCollaborator aCollaborator) {
+ this.collaborator = aCollaborator;
+ }
+
+ // "advice" methods
+ public void oneIntArg(int age) {
+ this.collaborator.oneIntArg(age);
+ }
+
+ public void oneObjectArg(Object bean) {
+ this.collaborator.oneObjectArg(bean);
+ }
+
+ public void oneIntAndOneObject(int x, Object o) {
+ this.collaborator.oneIntAndOneObject(x,o);
+ }
+
+ public void needsJoinPoint(JoinPoint tjp) {
+ this.collaborator.needsJoinPoint(tjp.getSignature().getName());
+ }
+
+ public void needsJoinPointStaticPart(JoinPoint.StaticPart tjpsp) {
+ this.collaborator.needsJoinPointStaticPart(tjpsp.getSignature().getName());
+ }
+
+
+ /**
+ * Collaborator interface that makes it easy to test this aspect is
+ * working as expected through mocking.
+ */
+ public interface AdviceBindingCollaborator {
+
+ void oneIntArg(int x);
+ void oneObjectArg(Object o);
+ void oneIntAndOneObject(int x, Object o);
+ void needsJoinPoint(String s);
+ void needsJoinPointStaticPart(String s);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AfterAdviceBindingTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AfterAdviceBindingTests.java
new file mode 100644
index 00000000000..f248763a2dc
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AfterAdviceBindingTests.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import org.easymock.MockControl;
+
+import org.springframework.aop.aspectj.AdviceBindingTestAspect.AdviceBindingCollaborator;
+
+/**
+ * Tests for various parameter binding scenarios with before advice.
+ *
+ * @author Adrian Colyer
+ * @author Rod Johnson
+ */
+public class AfterAdviceBindingTests extends AbstractAdviceBindingTests {
+
+ private AdviceBindingTestAspect afterAdviceAspect;
+
+ private MockControl mockControl;
+
+ private AdviceBindingCollaborator mockCollaborator;
+
+
+ public void setAfterAdviceAspect(AdviceBindingTestAspect anAspect) {
+ this.afterAdviceAspect = anAspect;
+ }
+
+ protected String getConfigPath() {
+ return "after-advice-tests.xml";
+ }
+
+ protected void onSetUp() throws Exception {
+ super.onSetUp();
+ mockControl = MockControl.createNiceControl(AdviceBindingCollaborator.class);
+ mockCollaborator = (AdviceBindingCollaborator) mockControl.getMock();
+ afterAdviceAspect.setCollaborator(mockCollaborator);
+ }
+
+
+ public void testOneIntArg() {
+ mockCollaborator.oneIntArg(5);
+ mockControl.replay();
+ testBeanProxy.setAge(5);
+ mockControl.verify();
+ }
+
+ public void testOneObjectArgBindingProxyWithThis() {
+ mockCollaborator.oneObjectArg(this.testBeanProxy);
+ mockControl.replay();
+ testBeanProxy.getAge();
+ mockControl.verify();
+ }
+
+ public void testOneObjectArgBindingTarget() {
+ mockCollaborator.oneObjectArg(this.testBeanTarget);
+ mockControl.replay();
+ testBeanProxy.getDoctor();
+ mockControl.verify();
+ }
+
+ public void testOneIntAndOneObjectArgs() {
+ mockCollaborator.oneIntAndOneObject(5,this.testBeanProxy);
+ mockControl.replay();
+ testBeanProxy.setAge(5);
+ mockControl.verify();
+ }
+
+ public void testNeedsJoinPoint() {
+ mockCollaborator.needsJoinPoint("getAge");
+ mockControl.replay();
+ testBeanProxy.getAge();
+ mockControl.verify();
+ }
+
+ public void testNeedsJoinPointStaticPart() {
+ mockCollaborator.needsJoinPointStaticPart("getAge");
+ mockControl.replay();
+ testBeanProxy.getAge();
+ mockControl.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AfterReturningAdviceBindingTestAspect.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AfterReturningAdviceBindingTestAspect.java
new file mode 100644
index 00000000000..29eb3641f81
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AfterReturningAdviceBindingTestAspect.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+
+/**
+ * @author Adrian Colyer
+ * @author Juergen Hoeller
+ */
+public class AfterReturningAdviceBindingTestAspect extends AdviceBindingTestAspect {
+
+ private AfterReturningAdviceBindingCollaborator getCollaborator() {
+ return (AfterReturningAdviceBindingCollaborator) this.collaborator;
+ }
+
+ public void oneString(String name) {
+ getCollaborator().oneString(name);
+ }
+
+ public void oneTestBeanArg(TestBean bean) {
+ getCollaborator().oneTestBeanArg(bean);
+ }
+
+ public void testBeanArrayArg(ITestBean[] beans) {
+ getCollaborator().testBeanArrayArg(beans);
+ }
+
+ public void objectMatchNoArgs() {
+ getCollaborator().objectMatchNoArgs();
+ }
+
+ public void stringMatchNoArgs() {
+ getCollaborator().stringMatchNoArgs();
+ }
+
+ public void oneInt(int result) {
+ getCollaborator().oneInt(result);
+ }
+
+
+ interface AfterReturningAdviceBindingCollaborator extends AdviceBindingCollaborator {
+
+ void oneString(String s);
+ void oneTestBeanArg(TestBean b);
+ void testBeanArrayArg(ITestBean[] b);
+ void objectMatchNoArgs();
+ void stringMatchNoArgs();
+ void oneInt(int result);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AfterReturningAdviceBindingTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AfterReturningAdviceBindingTests.java
new file mode 100644
index 00000000000..ddf8f622d6c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AfterReturningAdviceBindingTests.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import org.easymock.MockControl;
+
+import org.springframework.aop.aspectj.AfterReturningAdviceBindingTestAspect.AfterReturningAdviceBindingCollaborator;
+import org.springframework.aop.framework.Advised;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
+
+/**
+ * Tests for various parameter binding scenarios with before advice.
+ *
+ * @author Adrian Colyer
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public class AfterReturningAdviceBindingTests extends AbstractDependencyInjectionSpringContextTests {
+
+ private AfterReturningAdviceBindingTestAspect afterAdviceAspect;
+
+ private ITestBean testBeanProxy;
+
+ private TestBean testBeanTarget;
+
+ private MockControl mockControl;
+
+ private AfterReturningAdviceBindingCollaborator mockCollaborator;
+
+
+ public void setAfterReturningAdviceAspect(AfterReturningAdviceBindingTestAspect anAspect) {
+ this.afterAdviceAspect = anAspect;
+ }
+
+ public void setTestBean(ITestBean aBean) throws Exception {
+ assertTrue(AopUtils.isAopProxy(aBean));
+ this.testBeanProxy = aBean;
+ // we need the real target too, not just the proxy...
+ this.testBeanTarget = (TestBean) ((Advised)aBean).getTargetSource().getTarget();
+ }
+
+ protected String getConfigPath() {
+ return "afterReturning-advice-tests.xml";
+ }
+
+ protected void onSetUp() throws Exception {
+ super.onSetUp();
+ mockControl = MockControl.createNiceControl(AfterReturningAdviceBindingCollaborator.class);
+ mockCollaborator = (AfterReturningAdviceBindingCollaborator) mockControl.getMock();
+ afterAdviceAspect.setCollaborator(mockCollaborator);
+ }
+
+
+ // simple test to ensure all is well with the xml file
+ // note that this implicitly tests that the arg-names binding is working
+ public void testParse() {
+ }
+
+ public void testOneIntArg() {
+ mockCollaborator.oneIntArg(5);
+ mockControl.replay();
+ testBeanProxy.setAge(5);
+ mockControl.verify();
+ }
+
+ public void testOneObjectArg() {
+ mockCollaborator.oneObjectArg(this.testBeanProxy);
+ mockControl.replay();
+ testBeanProxy.getAge();
+ mockControl.verify();
+ }
+
+ public void testOneIntAndOneObjectArgs() {
+ mockCollaborator.oneIntAndOneObject(5,this.testBeanProxy);
+ mockControl.replay();
+ testBeanProxy.setAge(5);
+ mockControl.verify();
+ }
+
+ public void testNeedsJoinPoint() {
+ mockCollaborator.needsJoinPoint("getAge");
+ mockControl.replay();
+ testBeanProxy.getAge();
+ mockControl.verify();
+ }
+
+ public void testNeedsJoinPointStaticPart() {
+ mockCollaborator.needsJoinPointStaticPart("getAge");
+ mockControl.replay();
+ testBeanProxy.getAge();
+ mockControl.verify();
+ }
+
+ public void testReturningString() {
+ mockCollaborator.oneString("adrian");
+ mockControl.replay();
+ testBeanProxy.setName("adrian");
+ testBeanProxy.getName();
+ mockControl.verify();
+ }
+
+ public void testReturningObject() {
+ mockCollaborator.oneObjectArg(this.testBeanTarget);
+ mockControl.replay();
+ testBeanProxy.returnsThis();
+ mockControl.verify();
+ }
+
+ public void testReturningBean() {
+ mockCollaborator.oneTestBeanArg(this.testBeanTarget);
+ mockControl.replay();
+ testBeanProxy.returnsThis();
+ mockControl.verify();
+ }
+
+ public void testReturningBeanArray() {
+ this.testBeanTarget.setSpouse(new TestBean());
+ ITestBean[] spouses = (ITestBean[]) this.testBeanTarget.getSpouses();
+ mockCollaborator.testBeanArrayArg(spouses);
+ mockControl.replay();
+ testBeanProxy.getSpouses();
+ mockControl.verify();
+ }
+
+ public void testNoInvokeWhenReturningParameterTypeDoesNotMatch() {
+ // we need a strict mock for this...
+ mockControl = MockControl.createControl(AfterReturningAdviceBindingCollaborator.class);
+ mockCollaborator = (AfterReturningAdviceBindingCollaborator) mockControl.getMock();
+ afterAdviceAspect.setCollaborator(mockCollaborator);
+
+ mockControl.replay();
+ testBeanProxy.setSpouse(this.testBeanProxy);
+ testBeanProxy.getSpouse();
+ mockControl.verify();
+ }
+
+ public void testReturningByType() {
+ mockCollaborator.objectMatchNoArgs();
+ mockControl.replay();
+ testBeanProxy.returnsThis();
+ mockControl.verify();
+ }
+
+ public void testReturningPrimitive() {
+ mockCollaborator.oneInt(20);
+ mockControl.replay();
+ testBeanProxy.setAge(20);
+ testBeanProxy.haveBirthday();
+ mockControl.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AfterThrowingAdviceBindingTestAspect.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AfterThrowingAdviceBindingTestAspect.java
new file mode 100644
index 00000000000..6f202654100
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AfterThrowingAdviceBindingTestAspect.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+/**
+ * Aspect used as part of before advice binding tests.
+ * @author Adrian Colyer
+ */
+public class AfterThrowingAdviceBindingTestAspect {
+
+ // collaborator interface that makes it easy to test this aspect is
+ // working as expected through mocking.
+ public interface AfterThrowingAdviceBindingCollaborator {
+ void noArgs();
+ void oneThrowable(Throwable t);
+ void oneRuntimeException(RuntimeException re);
+ void noArgsOnThrowableMatch();
+ void noArgsOnRuntimeExceptionMatch();
+ }
+
+ protected AfterThrowingAdviceBindingCollaborator collaborator = null;
+
+ public void setCollaborator(AfterThrowingAdviceBindingCollaborator aCollaborator) {
+ this.collaborator = aCollaborator;
+ }
+
+ public void noArgs() {
+ this.collaborator.noArgs();
+ }
+
+ public void oneThrowable(Throwable t) {
+ this.collaborator.oneThrowable(t);
+ }
+
+ public void oneRuntimeException(RuntimeException ex) {
+ this.collaborator.oneRuntimeException(ex);
+ }
+
+ public void noArgsOnThrowableMatch() {
+ this.collaborator.noArgsOnThrowableMatch();
+ }
+
+ public void noArgsOnRuntimeExceptionMatch() {
+ this.collaborator.noArgsOnRuntimeExceptionMatch();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AfterThrowingAdviceBindingTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AfterThrowingAdviceBindingTests.java
new file mode 100644
index 00000000000..a4a9b24fdac
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AfterThrowingAdviceBindingTests.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import org.easymock.MockControl;
+
+import org.springframework.aop.aspectj.AfterThrowingAdviceBindingTestAspect.AfterThrowingAdviceBindingCollaborator;
+import org.springframework.beans.ITestBean;
+import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
+
+/**
+ * Tests for various parameter binding scenarios with before advice.
+ *
+ * @author Adrian Colyer
+ */
+public class AfterThrowingAdviceBindingTests extends AbstractDependencyInjectionSpringContextTests {
+
+ private AfterThrowingAdviceBindingTestAspect afterThrowingAdviceAspect;
+
+ private ITestBean testBean;
+
+ private MockControl mockControl;
+
+ private AfterThrowingAdviceBindingCollaborator mockCollaborator;
+
+
+ public void setAfterAdviceAspect(AfterThrowingAdviceBindingTestAspect anAspect) {
+ this.afterThrowingAdviceAspect = anAspect;
+ }
+
+ public void setTestBean(ITestBean aBean) throws Exception {
+ this.testBean = aBean;
+ }
+
+ protected String getConfigPath() {
+ return "afterThrowing-advice-tests.xml";
+ }
+
+ protected void onSetUp() throws Exception {
+ mockControl = MockControl.createNiceControl(AfterThrowingAdviceBindingCollaborator.class);
+ mockCollaborator = (AfterThrowingAdviceBindingCollaborator) mockControl.getMock();
+ afterThrowingAdviceAspect.setCollaborator(mockCollaborator);
+ }
+
+
+ // Simple test to ensure all is well with the XML file.
+ // Note that this implicitly tests that the arg-names binding is working.
+ public void testParse() {
+ }
+
+ public void testSimpleAfterThrowing() {
+ mockCollaborator.noArgs();
+ mockControl.replay();
+ try {
+ this.testBean.exceptional(new Throwable());
+ fail("should throw exception");
+ } catch (Throwable t) {
+ // no-op
+ }
+ mockControl.verify();
+ }
+
+ public void testAfterThrowingWithBinding() {
+ Throwable t = new Throwable();
+ mockCollaborator.oneThrowable(t);
+ mockControl.replay();
+ try {
+ this.testBean.exceptional(t);
+ fail("should throw exception");
+ } catch (Throwable x) {
+ // no-op
+ }
+ mockControl.verify();
+ }
+
+ public void testAfterThrowingWithNamedTypeRestriction() {
+ Throwable t = new Throwable();
+ // need a strict mock for this test...
+ mockControl = MockControl.createControl(AfterThrowingAdviceBindingCollaborator.class);
+ mockCollaborator = (AfterThrowingAdviceBindingCollaborator) mockControl.getMock();
+ afterThrowingAdviceAspect.setCollaborator(mockCollaborator);
+
+ mockCollaborator.noArgs();
+ mockCollaborator.oneThrowable(t);
+ mockCollaborator.noArgsOnThrowableMatch();
+ mockControl.replay();
+ try {
+ this.testBean.exceptional(t);
+ fail("should throw exception");
+ } catch (Throwable x) {
+ // no-op
+ }
+ mockControl.verify();
+ }
+
+ public void testAfterThrowingWithRuntimeExceptionBinding() {
+ RuntimeException ex = new RuntimeException();
+ mockCollaborator.oneRuntimeException(ex);
+ mockControl.replay();
+ try {
+ this.testBean.exceptional(ex);
+ fail("should throw exception");
+ } catch (Throwable x) {
+ // no-op
+ }
+ mockControl.verify();
+ }
+
+ public void testAfterThrowingWithTypeSpecified() {
+ mockCollaborator.noArgsOnThrowableMatch();
+ mockControl.replay();
+ try {
+ this.testBean.exceptional(new Throwable());
+ fail("should throw exception");
+ } catch (Throwable t) {
+ // no-op
+ }
+ mockControl.verify();
+ }
+
+ public void testAfterThrowingWithRuntimeTypeSpecified() {
+ mockCollaborator.noArgsOnRuntimeExceptionMatch();
+ mockControl.replay();
+ try {
+ this.testBean.exceptional(new RuntimeException());
+ fail("should throw exception");
+ } catch (Throwable t) {
+ // no-op
+ }
+ mockControl.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AroundAdviceBindingTestAspect.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AroundAdviceBindingTestAspect.java
new file mode 100644
index 00000000000..58ab8855909
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AroundAdviceBindingTestAspect.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+
+/**
+ * Aspect used as part of before advice binding tests.
+ *
+ * @author Adrian Colyer
+ */
+public class AroundAdviceBindingTestAspect {
+
+ private AroundAdviceBindingCollaborator collaborator = null;
+
+ public void setCollaborator(AroundAdviceBindingCollaborator aCollaborator) {
+ this.collaborator = aCollaborator;
+ }
+
+ // "advice" methods
+ public void oneIntArg(ProceedingJoinPoint pjp, int age) throws Throwable {
+ this.collaborator.oneIntArg(age);
+ pjp.proceed();
+ }
+
+ public int oneObjectArg(ProceedingJoinPoint pjp, Object bean) throws Throwable {
+ this.collaborator.oneObjectArg(bean);
+ return ((Integer) pjp.proceed()).intValue();
+ }
+
+ public void oneIntAndOneObject(ProceedingJoinPoint pjp, int x , Object o) throws Throwable {
+ this.collaborator.oneIntAndOneObject(x,o);
+ pjp.proceed();
+ }
+
+ public int justJoinPoint(ProceedingJoinPoint pjp) throws Throwable {
+ this.collaborator.justJoinPoint(pjp.getSignature().getName());
+ return ((Integer) pjp.proceed()).intValue();
+ }
+
+
+ /**
+ * Collaborator interface that makes it easy to test this aspect
+ * is working as expected through mocking.
+ */
+ public interface AroundAdviceBindingCollaborator {
+
+ void oneIntArg(int x);
+
+ void oneObjectArg(Object o);
+
+ void oneIntAndOneObject(int x, Object o);
+
+ void justJoinPoint(String s);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AroundAdviceBindingTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AroundAdviceBindingTests.java
new file mode 100644
index 00000000000..5a4f8409912
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AroundAdviceBindingTests.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import org.easymock.MockControl;
+
+import org.springframework.aop.aspectj.AroundAdviceBindingTestAspect.AroundAdviceBindingCollaborator;
+
+/**
+ * Tests for various parameter binding scenarios with before advice.
+ *
+ * @author Adrian Colyer
+ */
+public class AroundAdviceBindingTests extends AbstractAdviceBindingTests {
+
+ private MockControl mockControl;
+
+ private AroundAdviceBindingCollaborator mockCollaborator;
+
+ private AroundAdviceBindingTestAspect aroundAdviceAspect;
+
+
+ public void setAroundAdviceAspect(AroundAdviceBindingTestAspect anAspect) {
+ this.aroundAdviceAspect = anAspect;
+ }
+
+ protected String getConfigPath() {
+ return "around-advice-tests.xml";
+ }
+
+ protected void onSetUp() throws Exception {
+ super.onSetUp();
+ mockControl = MockControl.createNiceControl(AroundAdviceBindingCollaborator.class);
+ mockCollaborator = (AroundAdviceBindingCollaborator) mockControl.getMock();
+ aroundAdviceAspect.setCollaborator(mockCollaborator);
+ }
+
+
+ public void testOneIntArg() {
+ mockCollaborator.oneIntArg(5);
+ mockControl.replay();
+ testBeanProxy.setAge(5);
+ mockControl.verify();
+ }
+
+ public void testOneObjectArgBoundToTarget() {
+ mockCollaborator.oneObjectArg(this.testBeanTarget);
+ mockControl.replay();
+ testBeanProxy.getAge();
+ mockControl.verify();
+ }
+
+ public void testOneIntAndOneObjectArgs() {
+ mockCollaborator.oneIntAndOneObject(5, this.testBeanProxy);
+ mockControl.replay();
+ testBeanProxy.setAge(5);
+ mockControl.verify();
+ }
+
+ public void testJustJoinPoint() {
+ mockCollaborator.justJoinPoint("getAge");
+ mockControl.replay();
+ testBeanProxy.getAge();
+ mockControl.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AroundAdviceCircularTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AroundAdviceCircularTests.java
new file mode 100644
index 00000000000..7294ebb1be9
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AroundAdviceCircularTests.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import org.springframework.aop.support.AopUtils;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class AroundAdviceCircularTests extends AroundAdviceBindingTests {
+
+ protected String getConfigPath() {
+ return "around-advice-circular-tests.xml";
+ }
+
+ public void testBothBeansAreProxies() {
+ Object tb = getApplicationContext().getBean("testBean");
+ assertTrue(AopUtils.isAopProxy(tb));
+ Object tb2 = getApplicationContext().getBean("testBean2");
+ assertTrue(AopUtils.isAopProxy(tb2));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AspectAndAdvicePrecedenceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AspectAndAdvicePrecedenceTests.java
new file mode 100644
index 00000000000..f670edfbc52
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AspectAndAdvicePrecedenceTests.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import org.springframework.beans.ITestBean;
+import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
+
+/**
+ * @author Adrian Colyer
+ */
+public class AspectAndAdvicePrecedenceTests extends AbstractDependencyInjectionSpringContextTests {
+
+ private PrecedenceTestAspect highPrecedenceAspect;
+ private PrecedenceTestAspect lowPrecedenceAspect;
+ private SimpleSpringBeforeAdvice lowPrecedenceSpringAdvice;
+ private SimpleSpringBeforeAdvice highPrecedenceSpringAdvice;
+ private ITestBean testBean;
+
+
+ public AspectAndAdvicePrecedenceTests() {
+ setAutowireMode(AUTOWIRE_BY_NAME);
+ }
+
+ public void setHighPrecedenceAspect(PrecedenceTestAspect highPrecedenceAspect) {
+ this.highPrecedenceAspect = highPrecedenceAspect;
+ }
+
+ public void setLowPrecedenceAspect(PrecedenceTestAspect lowPrecedenceAspect) {
+ this.lowPrecedenceAspect = lowPrecedenceAspect;
+ }
+
+ public void setLowPrecedenceSpringAdvice(SimpleSpringBeforeAdvice lowPrecedenceSpringAdvice) {
+ this.lowPrecedenceSpringAdvice = lowPrecedenceSpringAdvice;
+ }
+
+ public void setHighPrecedenceSpringAdvice(SimpleSpringBeforeAdvice highPrecedenceSpringAdvice) {
+ this.highPrecedenceSpringAdvice = highPrecedenceSpringAdvice;
+ }
+
+ public void setTestBean(ITestBean testBean) {
+ this.testBean = testBean;
+ }
+
+ protected String getConfigPath() {
+ return "advice-precedence-tests.xml";
+ }
+
+
+ // ========== end of test case set up, start of tests proper ===================
+
+ public void testAdviceOrder() {
+ PrecedenceTestAspect.Collaborator collaborator = new PrecedenceVerifyingCollaborator();
+ this.highPrecedenceAspect.setCollaborator(collaborator);
+ this.lowPrecedenceAspect.setCollaborator(collaborator);
+ this.highPrecedenceSpringAdvice.setCollaborator(collaborator);
+ this.lowPrecedenceSpringAdvice.setCollaborator(collaborator);
+ this.testBean.getAge();
+ }
+
+
+ private static class PrecedenceVerifyingCollaborator implements PrecedenceTestAspect.Collaborator {
+
+ private static final String[] EXPECTED = {
+ // this order confirmed by running the same aspects (minus the Spring AOP advisors)
+ // through AspectJ...
+ "beforeAdviceOne(highPrecedenceAspect)", // 1
+ "beforeAdviceTwo(highPrecedenceAspect)", // 2
+ "aroundAdviceOne(highPrecedenceAspect)", // 3, before proceed
+ "aroundAdviceTwo(highPrecedenceAspect)", // 4, before proceed
+ "beforeAdviceOne(highPrecedenceSpringAdvice)", // 5
+ "beforeAdviceOne(lowPrecedenceSpringAdvice)", // 6
+ "beforeAdviceOne(lowPrecedenceAspect)", // 7
+ "beforeAdviceTwo(lowPrecedenceAspect)", // 8
+ "aroundAdviceOne(lowPrecedenceAspect)", // 9, before proceed
+ "aroundAdviceTwo(lowPrecedenceAspect)", // 10, before proceed
+ "aroundAdviceTwo(lowPrecedenceAspect)", // 11, after proceed
+ "aroundAdviceOne(lowPrecedenceAspect)", // 12, after proceed
+ "afterAdviceOne(lowPrecedenceAspect)", // 13
+ "afterAdviceTwo(lowPrecedenceAspect)", // 14
+ "aroundAdviceTwo(highPrecedenceAspect)", // 15, after proceed
+ "aroundAdviceOne(highPrecedenceAspect)", // 16, after proceed
+ "afterAdviceOne(highPrecedenceAspect)", // 17
+ "afterAdviceTwo(highPrecedenceAspect)" // 18
+ };
+
+ private int adviceInvocationNumber = 0;
+
+ private void checkAdvice(String whatJustHappened) {
+ //System.out.println("[" + adviceInvocationNumber + "] " + whatJustHappened + " ==> " + EXPECTED[adviceInvocationNumber]);
+ if (adviceInvocationNumber > (EXPECTED.length - 1)) {
+ fail("Too many advice invocations, expecting " + EXPECTED.length
+ + " but had " + adviceInvocationNumber);
+ }
+ String expecting = EXPECTED[adviceInvocationNumber++];
+ if (!whatJustHappened.equals(expecting)) {
+ fail("Expecting '" + expecting + "' on advice invocation " + adviceInvocationNumber +
+ " but got '" + whatJustHappened + "'");
+ }
+ }
+
+ public void beforeAdviceOne(String beanName) {
+ checkAdvice("beforeAdviceOne(" + beanName + ")");
+ }
+
+ public void beforeAdviceTwo(String beanName) {
+ checkAdvice("beforeAdviceTwo(" + beanName + ")");
+ }
+
+ public void aroundAdviceOne(String beanName) {
+ checkAdvice("aroundAdviceOne(" + beanName + ")");
+ }
+
+ public void aroundAdviceTwo(String beanName) {
+ checkAdvice("aroundAdviceTwo(" + beanName + ")");
+ }
+
+ public void afterAdviceOne(String beanName) {
+ checkAdvice("afterAdviceOne(" + beanName + ")");
+ }
+
+ public void afterAdviceTwo(String beanName) {
+ checkAdvice("afterAdviceTwo(" + beanName + ")");
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscovererTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscovererTests.java
new file mode 100644
index 00000000000..b061363a1e2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscovererTests.java
@@ -0,0 +1,298 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import junit.framework.TestCase;
+import org.aspectj.lang.JoinPoint;
+import org.springframework.aop.aspectj.AspectJAdviceParameterNameDiscoverer.AmbiguousBindingException;
+
+import java.lang.reflect.Method;
+
+/**
+ * Unit tests for the {@link AspectJAdviceParameterNameDiscoverer} class.
+ *
+ *
See also TigerAspectJAdviceParameterNameDiscovererTests in
+ * the 'tiger' tree for tests relating to annotations.
+ *
+ * @author Adrian Colyer
+ */
+public class AspectJAdviceParameterNameDiscovererTests extends TestCase {
+
+ // methods to discover parameter names for
+ public void noArgs() {
+ }
+
+ public void tjp(JoinPoint jp) {
+ }
+
+ public void tjpsp(JoinPoint.StaticPart tjpsp) {
+ }
+
+ public void twoJoinPoints(JoinPoint jp1, JoinPoint jp2) {
+ }
+
+ public void oneThrowable(Exception ex) {
+ }
+
+ public void jpAndOneThrowable(JoinPoint jp, Exception ex) {
+ }
+
+ public void jpAndTwoThrowables(JoinPoint jp, Exception ex, Error err) {
+ }
+
+ public void oneObject(Object x) {
+ }
+
+ public void twoObjects(Object x, Object y) {
+ }
+
+ public void onePrimitive(int x) {
+ }
+
+ public void oneObjectOnePrimitive(Object x, int y) {
+ }
+
+ public void oneThrowableOnePrimitive(Throwable x, int y) {
+ }
+
+ public void theBigOne(JoinPoint jp, Throwable x, int y, Object foo) {
+ }
+
+
+ public void testNoArgs() {
+ assertParameterNames(getMethod("noArgs"), "execution(* *(..))", new String[0]);
+ }
+
+ public void testJoinPointOnly() {
+ assertParameterNames(getMethod("tjp"), "execution(* *(..))", new String[]{"thisJoinPoint"});
+ }
+
+ public void testJoinPointStaticPartOnly() {
+ assertParameterNames(getMethod("tjpsp"), "execution(* *(..))", new String[]{"thisJoinPointStaticPart"});
+ }
+
+ public void testTwoJoinPoints() {
+ assertException(getMethod("twoJoinPoints"), "foo()", IllegalStateException.class, "Failed to bind all argument names: 1 argument(s) could not be bound");
+ }
+
+ public void testOneThrowable() {
+ assertParameterNames(getMethod("oneThrowable"), "foo()", null, "ex", new String[]{"ex"});
+ }
+
+ public void testOneJPAndOneThrowable() {
+ assertParameterNames(getMethod("jpAndOneThrowable"), "foo()", null, "ex", new String[]{"thisJoinPoint", "ex"});
+ }
+
+ public void testOneJPAndTwoThrowables() {
+ assertException(getMethod("jpAndTwoThrowables"), "foo()", null, "ex", AmbiguousBindingException.class,
+ "Binding of throwing parameter 'ex' is ambiguous: could be bound to argument 1 or argument 2");
+ }
+
+ public void testThrowableNoCandidates() {
+ assertException(getMethod("noArgs"), "foo()", null, "ex", IllegalStateException.class,
+ "Not enough arguments in method to satisfy binding of returning and throwing variables");
+ }
+
+ public void testReturning() {
+ assertParameterNames(getMethod("oneObject"), "foo()", "obj", null, new String[]{"obj"});
+ }
+
+ public void testAmbiguousReturning() {
+ assertException(getMethod("twoObjects"), "foo()", "obj", null, AmbiguousBindingException.class,
+ "Binding of returning parameter 'obj' is ambiguous, there are 2 candidates.");
+ }
+
+ public void testReturningNoCandidates() {
+ assertException(getMethod("noArgs"), "foo()", "obj", null, IllegalStateException.class,
+ "Not enough arguments in method to satisfy binding of returning and throwing variables");
+ }
+
+ public void testThisBindingOneCandidate() {
+ assertParameterNames(getMethod("oneObject"), "this(x)", new String[]{"x"});
+ }
+
+ public void testThisBindingWithAlternateTokenizations() {
+ assertParameterNames(getMethod("oneObject"), "this( x )", new String[]{"x"});
+ assertParameterNames(getMethod("oneObject"), "this( x)", new String[]{"x"});
+ assertParameterNames(getMethod("oneObject"), "this (x )", new String[]{"x"});
+ assertParameterNames(getMethod("oneObject"), "this(x )", new String[]{"x"});
+ assertParameterNames(getMethod("oneObject"), "foo() && this(x)", new String[]{"x"});
+ }
+
+ public void testThisBindingTwoCandidates() {
+ assertException(getMethod("oneObject"), "this(x) || this(y)", AmbiguousBindingException.class,
+ "Found 2 candidate this(), target() or args() variables but only one unbound argument slot");
+ }
+
+ public void testThisBindingWithBadPointcutExpressions() {
+ assertException(getMethod("oneObject"), "this(", IllegalStateException.class,
+ "Failed to bind all argument names: 1 argument(s) could not be bound");
+ assertException(getMethod("oneObject"), "this(x && foo()", IllegalStateException.class,
+ "Failed to bind all argument names: 1 argument(s) could not be bound");
+ }
+
+ public void testTargetBindingOneCandidate() {
+ assertParameterNames(getMethod("oneObject"), "target(x)", new String[]{"x"});
+ }
+
+ public void testTargetBindingWithAlternateTokenizations() {
+ assertParameterNames(getMethod("oneObject"), "target( x )", new String[]{"x"});
+ assertParameterNames(getMethod("oneObject"), "target( x)", new String[]{"x"});
+ assertParameterNames(getMethod("oneObject"), "target (x )", new String[]{"x"});
+ assertParameterNames(getMethod("oneObject"), "target(x )", new String[]{"x"});
+ assertParameterNames(getMethod("oneObject"), "foo() && target(x)", new String[]{"x"});
+ }
+
+ public void testTargetBindingTwoCandidates() {
+ assertException(getMethod("oneObject"), "target(x) || target(y)", AmbiguousBindingException.class,
+ "Found 2 candidate this(), target() or args() variables but only one unbound argument slot");
+ }
+
+ public void testTargetBindingWithBadPointcutExpressions() {
+ assertException(getMethod("oneObject"), "target(", IllegalStateException.class,
+ "Failed to bind all argument names: 1 argument(s) could not be bound");
+ assertException(getMethod("oneObject"), "target(x && foo()", IllegalStateException.class,
+ "Failed to bind all argument names: 1 argument(s) could not be bound");
+ }
+
+ public void testArgsBindingOneObject() {
+ assertParameterNames(getMethod("oneObject"), "args(x)", new String[]{"x"});
+ }
+
+ public void testArgsBindingOneObjectTwoCandidates() {
+ assertException(getMethod("oneObject"), "args(x,y)", AmbiguousBindingException.class,
+ "Found 2 candidate this(), target() or args() variables but only one unbound argument slot");
+ }
+
+ public void testAmbiguousArgsBinding() {
+ assertException(getMethod("twoObjects"), "args(x,y)", AmbiguousBindingException.class,
+ "Still 2 unbound args at this(),target(),args() binding stage, with no way to determine between them");
+ }
+
+ public void testArgsOnePrimitive() {
+ assertParameterNames(getMethod("onePrimitive"), "args(count)", new String[]{"count"});
+ }
+
+ public void testArgsOnePrimitiveOneObject() {
+ assertException(getMethod("oneObjectOnePrimitive"), "args(count,obj)", AmbiguousBindingException.class,
+ "Found 2 candidate variable names but only one candidate binding slot when matching primitive args");
+ }
+
+ public void testThisAndPrimitive() {
+ assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && this(obj)", new String[]{"obj", "count"});
+ }
+
+ public void testTargetAndPrimitive() {
+ assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && target(obj)", new String[]{"obj", "count"});
+ }
+
+ public void testThrowingAndPrimitive() {
+ assertParameterNames(getMethod("oneThrowableOnePrimitive"), "args(count)", null, "ex", new String[]{"ex", "count"});
+ }
+
+ public void testAllTogetherNow() {
+ assertParameterNames(getMethod("theBigOne"), "this(foo) && args(x)", null, "ex", new String[]{"thisJoinPoint", "ex", "x", "foo"});
+ }
+
+ public void testReferenceBinding() {
+ assertParameterNames(getMethod("onePrimitive"),"somepc(foo)",new String[] {"foo"});
+ }
+
+ public void testReferenceBindingWithAlternateTokenizations() {
+ assertParameterNames(getMethod("onePrimitive"),"call(bar *) && somepc(foo)",new String[] {"foo"});
+ assertParameterNames(getMethod("onePrimitive"),"somepc ( foo )",new String[] {"foo"});
+ assertParameterNames(getMethod("onePrimitive"),"somepc( foo)",new String[] {"foo"});
+ }
+
+
+ protected Method getMethod(String name) {
+ // assumes no overloading of test methods...
+ Method[] candidates = this.getClass().getMethods();
+ for (int i = 0; i < candidates.length; i++) {
+ if (candidates[i].getName().equals(name)) {
+ return candidates[i];
+ }
+ }
+ fail("Bad test specification, no method '" + name + "' found in test class");
+ return null;
+ }
+
+ protected void assertParameterNames(Method m, String pointcut, String[] parameterNames) {
+ assertParameterNames(m, pointcut, null, null, parameterNames);
+ }
+
+ protected void assertParameterNames(Method m, String pointcut, String returning, String throwing, String[] parameterNames) {
+ assertEquals("bad test specification, must have same number of parameter names as method arguments",
+ m.getParameterTypes().length, parameterNames.length);
+
+ AspectJAdviceParameterNameDiscoverer discoverer = new AspectJAdviceParameterNameDiscoverer(pointcut);
+ discoverer.setRaiseExceptions(true);
+ discoverer.setReturningName(returning);
+ discoverer.setThrowingName(throwing);
+ String[] discoveredNames = discoverer.getParameterNames(m);
+
+ String formattedExpectedNames = format(parameterNames);
+ String formattedActualNames = format(discoveredNames);
+
+ assertEquals("Expecting " + parameterNames.length + " parameter names in return set '" +
+ formattedExpectedNames + "', but found " + discoveredNames.length +
+ " '" + formattedActualNames + "'",
+ parameterNames.length, discoveredNames.length);
+
+ for (int i = 0; i < discoveredNames.length; i++) {
+ assertNotNull("Parameter names must never be null", discoveredNames[i]);
+ assertEquals("Expecting parameter " + i + " to be named '" +
+ parameterNames[i] + "' but was '" + discoveredNames[i] + "'",
+ parameterNames[i], discoveredNames[i]);
+ }
+ }
+
+ protected void assertException(Method m, String pointcut, Class exceptionType, String message) {
+ assertException(m, pointcut, null, null, exceptionType, message);
+ }
+
+ protected void assertException(Method m, String pointcut, String returning, String throwing, Class exceptionType, String message) {
+ AspectJAdviceParameterNameDiscoverer discoverer = new AspectJAdviceParameterNameDiscoverer(pointcut);
+ discoverer.setRaiseExceptions(true);
+ discoverer.setReturningName(returning);
+ discoverer.setThrowingName(throwing);
+
+ try {
+ discoverer.getParameterNames(m);
+ fail("Expecting " + exceptionType.getName() + " with message '" + message + "'");
+ } catch (RuntimeException expected) {
+ assertEquals("Expecting exception of type " + exceptionType.getName(),
+ exceptionType, expected.getClass());
+ assertEquals("Exception message does not match expected", message, expected.getMessage());
+ }
+ }
+
+
+ private static String format(String[] names) {
+ StringBuffer sb = new StringBuffer();
+ sb.append("(");
+ for (int i = 0; i < names.length; i++) {
+ sb.append(names[i]);
+ if ((i + 1) < names.length) {
+ sb.append(",");
+ }
+ }
+ sb.append(")");
+ return sb.toString();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AspectJExpressionPointcutAdvisorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AspectJExpressionPointcutAdvisorTests.java
new file mode 100644
index 00000000000..cdfcf2684c2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AspectJExpressionPointcutAdvisorTests.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import org.springframework.beans.ITestBean;
+import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class AspectJExpressionPointcutAdvisorTests extends AbstractDependencyInjectionSpringContextTests {
+
+ private ITestBean testBean;
+
+ private CallCountingInterceptor interceptor;
+
+
+ public void setTestBean(ITestBean testBean) {
+ this.testBean = testBean;
+ }
+
+ public void setInterceptor(CallCountingInterceptor interceptor) {
+ this.interceptor = interceptor;
+ }
+
+ protected String getConfigPath() {
+ return "aspectj.xml";
+ }
+
+ protected void onSetUp() throws Exception {
+ interceptor.reset();
+ }
+
+
+ public void testPointcutting() throws Exception {
+ assertEquals("Count should be 0", 0, interceptor.getCount());
+ testBean.getSpouses();
+ assertEquals("Count should be 1", 1, interceptor.getCount());
+ testBean.getSpouse();
+ assertEquals("Count should be 1", 1, interceptor.getCount());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AspectJExpressionPointcutTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AspectJExpressionPointcutTests.java
new file mode 100644
index 00000000000..a050e5bf342
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AspectJExpressionPointcutTests.java
@@ -0,0 +1,332 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.aspectj.weaver.tools.PointcutExpression;
+import org.aspectj.weaver.tools.PointcutPrimitive;
+import org.aspectj.weaver.tools.UnsupportedPointcutPrimitiveException;
+import org.springframework.aop.ClassFilter;
+import org.springframework.aop.MethodMatcher;
+import org.springframework.aop.Pointcut;
+import org.springframework.aop.aspectj.AspectJExpressionPointcut;
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.aop.support.DefaultPointcutAdvisor;
+import org.springframework.beans.IOther;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+
+/**
+ * @author Rob Harrop
+ * @author Rod Johnson
+ */
+public class AspectJExpressionPointcutTests extends TestCase {
+
+ public static final String MATCH_ALL_METHODS = "execution(* *(..))";
+
+ private Method getAge;
+
+ private Method setAge;
+
+ private Method setSomeNumber;
+
+ private Method isPostProcessed;
+
+ public void testMatchExplicit() {
+ String expression = "execution(int org.springframework.beans.TestBean.getAge())";
+
+ Pointcut pointcut = getPointcut(expression);
+ ClassFilter classFilter = pointcut.getClassFilter();
+ MethodMatcher methodMatcher = pointcut.getMethodMatcher();
+
+ assertMatchesTestBeanClass(classFilter);
+
+ // not currently testable in a reliable fashion
+ //assertDoesNotMatchStringClass(classFilter);
+
+ assertFalse("Should not be a runtime match", methodMatcher.isRuntime());
+ assertMatchesGetAge(methodMatcher);
+ assertFalse("Expression should match setAge() method", methodMatcher.matches(setAge, TestBean.class));
+ }
+
+
+ public void setUp() throws NoSuchMethodException {
+ getAge = TestBean.class.getMethod("getAge", null);
+ setAge = TestBean.class.getMethod("setAge", new Class[]{int.class});
+ setSomeNumber = TestBean.class.getMethod("setSomeNumber", new Class[]{Number.class});
+ isPostProcessed = TestBean.class.getMethod("isPostProcessed", (Class[]) null);
+ }
+
+
+
+ public void testMatchWithTypePattern() throws Exception {
+ String expression = "execution(* *..TestBean.*Age(..))";
+
+ Pointcut pointcut = getPointcut(expression);
+ ClassFilter classFilter = pointcut.getClassFilter();
+ MethodMatcher methodMatcher = pointcut.getMethodMatcher();
+
+ assertMatchesTestBeanClass(classFilter);
+
+ // not currently testable in a reliable fashion
+ //assertDoesNotMatchStringClass(classFilter);
+
+ assertFalse("Should not be a runtime match", methodMatcher.isRuntime());
+ assertMatchesGetAge(methodMatcher);
+ assertTrue("Expression should match setAge(int) method", methodMatcher.matches(setAge, TestBean.class));
+ }
+
+
+ public void testThis() throws SecurityException, NoSuchMethodException{
+ testThisOrTarget("this");
+ }
+
+ public void testTarget() throws SecurityException, NoSuchMethodException {
+ testThisOrTarget("target");
+ }
+
+ public static class OtherIOther implements IOther {
+
+ public void absquatulate() {
+ // Empty
+ }
+
+ }
+
+ /**
+ * This and target are equivalent. Really instanceof pointcuts.
+ * @throws Exception
+ * @param which this or target
+ * @throws NoSuchMethodException
+ * @throws SecurityException
+ */
+ private void testThisOrTarget(String which) throws SecurityException, NoSuchMethodException {
+ String matchesTestBean = which + "(org.springframework.beans.TestBean)";
+ String matchesIOther = which + "(org.springframework.beans.IOther)";
+ AspectJExpressionPointcut testBeanPc = new AspectJExpressionPointcut();
+ testBeanPc.setExpression(matchesTestBean);
+
+ AspectJExpressionPointcut iOtherPc = new AspectJExpressionPointcut();
+ iOtherPc.setExpression(matchesIOther);
+
+ assertTrue(testBeanPc.matches(TestBean.class));
+ assertTrue(testBeanPc.matches(getAge, TestBean.class));
+ assertTrue(iOtherPc.matches(OtherIOther.class.getMethod("absquatulate", null),
+ OtherIOther.class));
+
+ assertFalse(testBeanPc.matches(OtherIOther.class.getMethod("absquatulate", null),
+ OtherIOther.class));
+ }
+
+ public void testWithinRootPackage() throws SecurityException, NoSuchMethodException {
+ testWithinPackage(false);
+ }
+
+ public void testWithinRootAndSubpackages() throws SecurityException, NoSuchMethodException {
+ testWithinPackage(true);
+ }
+
+ private void testWithinPackage(boolean matchSubpackages) throws SecurityException, NoSuchMethodException {
+ String withinBeansPackage = "within(org.springframework.beans.";
+ // Subpackages are matched by **
+ if (matchSubpackages) {
+ withinBeansPackage += ".";
+ }
+ withinBeansPackage = withinBeansPackage + "*)";
+ AspectJExpressionPointcut withinBeansPc = new AspectJExpressionPointcut();
+ withinBeansPc.setExpression(withinBeansPackage);
+
+ assertTrue(withinBeansPc.matches(TestBean.class));
+ assertTrue(withinBeansPc.matches(getAge, TestBean.class));
+ assertEquals(matchSubpackages, withinBeansPc.matches(BeanFactory.class));
+ assertEquals(matchSubpackages, withinBeansPc.matches(
+ DefaultListableBeanFactory.class.getMethod("getBeanDefinitionCount", null),
+ DefaultListableBeanFactory.class));
+ assertFalse(withinBeansPc.matches(String.class));
+ assertFalse(withinBeansPc.matches(OtherIOther.class.getMethod("absquatulate", null),
+ OtherIOther.class));
+ }
+
+ public void testFriendlyErrorOnNoLocationClassMatching() {
+ AspectJExpressionPointcut pc = new AspectJExpressionPointcut();
+ try {
+ pc.matches(ITestBean.class);
+ fail();
+ }
+ catch (IllegalStateException ex) {
+ assertTrue(ex.getMessage().indexOf("expression") != -1);
+ }
+ }
+
+ public void testFriendlyErrorOnNoLocation2ArgMatching() {
+ AspectJExpressionPointcut pc = new AspectJExpressionPointcut();
+ try {
+ pc.matches(getAge, ITestBean.class);
+ fail();
+ }
+ catch (IllegalStateException ex) {
+ assertTrue(ex.getMessage().indexOf("expression") != -1);
+ }
+ }
+
+ public void testFriendlyErrorOnNoLocation3ArgMatching() {
+ AspectJExpressionPointcut pc = new AspectJExpressionPointcut();
+ try {
+ pc.matches(getAge, ITestBean.class, (Object[]) null);
+ fail();
+ }
+ catch (IllegalStateException ex) {
+ assertTrue(ex.getMessage().indexOf("expression") != -1);
+ }
+ }
+
+
+ public void testMatchWithArgs() throws Exception {
+ String expression = "execution(void org.springframework.beans.TestBean.setSomeNumber(Number)) && args(Double)";
+
+ Pointcut pointcut = getPointcut(expression);
+ ClassFilter classFilter = pointcut.getClassFilter();
+ MethodMatcher methodMatcher = pointcut.getMethodMatcher();
+
+ assertMatchesTestBeanClass(classFilter);
+
+ // not currently testable in a reliable fashion
+ //assertDoesNotMatchStringClass(classFilter);
+
+ assertTrue("Should match with setSomeNumber with Double input",
+ methodMatcher.matches(setSomeNumber, TestBean.class, new Object[]{new Double(12)}));
+ assertFalse("Should not match setSomeNumber with Integer input",
+ methodMatcher.matches(setSomeNumber, TestBean.class, new Object[]{new Integer(11)}));
+ assertFalse("Should not match getAge", methodMatcher.matches(getAge, TestBean.class, null));
+ assertTrue("Should be a runtime match", methodMatcher.isRuntime());
+ }
+
+ public void testSimpleAdvice() {
+ String expression = "execution(int org.springframework.beans.TestBean.getAge())";
+
+ CallCountingInterceptor interceptor = new CallCountingInterceptor();
+
+ TestBean testBean = getAdvisedProxy(expression, interceptor);
+
+ assertEquals("Calls should be 0", 0, interceptor.getCount());
+
+ testBean.getAge();
+
+ assertEquals("Calls should be 1", 1, interceptor.getCount());
+
+ testBean.setAge(90);
+
+ assertEquals("Calls should still be 1", 1, interceptor.getCount());
+ }
+
+ public void testDynamicMatchingProxy() {
+ String expression = "execution(void org.springframework.beans.TestBean.setSomeNumber(Number)) && args(Double)";
+
+ CallCountingInterceptor interceptor = new CallCountingInterceptor();
+
+ TestBean testBean = getAdvisedProxy(expression, interceptor);
+
+ assertEquals("Calls should be 0", 0, interceptor.getCount());
+
+ testBean.setSomeNumber(new Double(30));
+
+ assertEquals("Calls should be 1", 1, interceptor.getCount());
+
+ testBean.setSomeNumber(new Integer(90));
+
+ assertEquals("Calls should be 1", 1, interceptor.getCount());
+ }
+
+ public void testInvalidExpression() {
+ String expression = "execution(void org.springframework.beans.TestBean.setSomeNumber(Number) && args(Double)";
+
+ try {
+ getPointcut(expression).getClassFilter(); // call to getClassFilter forces resolution
+ fail("Invalid expression should throw IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ assertTrue(true);
+ System.out.println(ex.getMessage());
+ }
+ }
+
+ private TestBean getAdvisedProxy(String pointcutExpression, CallCountingInterceptor interceptor) {
+ TestBean target = new TestBean();
+
+ Pointcut pointcut = getPointcut(pointcutExpression);
+
+ DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
+ advisor.setAdvice(interceptor);
+ advisor.setPointcut(pointcut);
+
+ ProxyFactory pf = new ProxyFactory();
+ pf.setTarget(target);
+ pf.addAdvisor(advisor);
+
+ return (TestBean) pf.getProxy();
+ }
+
+ private void assertMatchesGetAge(MethodMatcher methodMatcher) {
+ assertTrue("Expression should match getAge() method", methodMatcher.matches(getAge, TestBean.class));
+ }
+
+ private void assertMatchesTestBeanClass(ClassFilter classFilter) {
+ assertTrue("Expression should match TestBean class", classFilter.matches(TestBean.class));
+ }
+
+ private void assertDoesNotMatchStringClass(ClassFilter classFilter) {
+ assertFalse("Expression should not match String class", classFilter.matches(String.class));
+ }
+
+ public void testWithUnsupportedPointcutPrimitive() throws Exception {
+ String expression = "call(int org.springframework.beans.TestBean.getAge())";
+
+ try {
+ getPointcut(expression).getClassFilter(); // call to getClassFilter forces resolution...
+ fail("Should not support call pointcuts");
+ }
+ catch (UnsupportedPointcutPrimitiveException ex) {
+ assertEquals("Should not support call pointcut", PointcutPrimitive.CALL, ex.getUnsupportedPrimitive());
+ }
+
+ }
+
+ public void testAndSubstitution() {
+ Pointcut pc = getPointcut("execution(* *(..)) and args(String)");
+ PointcutExpression expr =
+ ((AspectJExpressionPointcut) pc).getPointcutExpression();
+ assertEquals("execution(* *(..)) && args(String)",expr.getPointcutExpression());
+ }
+
+ public void testMultipleAndSubstitutions() {
+ Pointcut pc = getPointcut("execution(* *(..)) and args(String) and this(Object)");
+ PointcutExpression expr =
+ ((AspectJExpressionPointcut) pc).getPointcutExpression();
+ assertEquals("execution(* *(..)) && args(String) && this(Object)",expr.getPointcutExpression());
+ }
+
+ private Pointcut getPointcut(String expression) {
+ AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
+ pointcut.setExpression(expression);
+ return pointcut;
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AuthenticationLogger.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AuthenticationLogger.java
new file mode 100644
index 00000000000..d3d46b30c9a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/AuthenticationLogger.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.
+ *
+ * Created on 13-Feb-2006 by Adrian Colyer
+ */
+package org.springframework.aop.aspectj;
+
+/**
+ * Used by before-advice-tests.xml
+ * @author Adrian Colyer
+ * @since 2.0
+ */
+public class AuthenticationLogger {
+
+ public void logAuthenticationAttempt(String username) {
+ System.out.println("User [" + username + "] attempting to authenticate");
+ }
+
+}
+
+class SecurityManager {
+ public boolean authenticate(String username, String password) {
+ return false;
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/BeanNameAwareMixin.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/BeanNameAwareMixin.java
new file mode 100644
index 00000000000..1bc6e9c22dd
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/BeanNameAwareMixin.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.
+ *
+ * Created on 15 Nov 2006 by Adrian Colyer
+ */
+package org.springframework.aop.aspectj;
+
+import org.springframework.beans.factory.BeanNameAware;
+
+/**
+ * @author Adrian Colyer
+ * @since 2.0
+ */
+public class BeanNameAwareMixin implements BeanNameAware {
+
+ private String beanName;
+
+ /* (non-Javadoc)
+ * @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String)
+ */
+ public void setBeanName(String name) {
+ this.beanName = name;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/BeanNamePointcutMatchingTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/BeanNamePointcutMatchingTests.java
new file mode 100644
index 00000000000..df40ef37bdc
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/BeanNamePointcutMatchingTests.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+
+/**
+ * Tests for matching of bean() pointcut designator.
+ *
+ * @author Ramnivas Laddad
+ */
+public class BeanNamePointcutMatchingTests extends TestCase {
+
+ public void testMatchingPointcuts() {
+ assertMatch("someName", "bean(someName)");
+
+ // Spring bean names are less restrictive compared to AspectJ names (methods, types etc.)
+ // MVC Controller-kind
+ assertMatch("someName/someOtherName", "bean(someName/someOtherName)");
+ assertMatch("someName/foo/someOtherName", "bean(someName/*/someOtherName)");
+ assertMatch("someName/foo/bar/someOtherName", "bean(someName/*/someOtherName)");
+ assertMatch("someName/*/**", "bean(someName/*)");
+ // JMX-kind
+ assertMatch("service:name=traceService", "bean(service:name=traceService)");
+ assertMatch("service:name=traceService", "bean(service:name=*)");
+ assertMatch("service:name=traceService", "bean(*:name=traceService)");
+
+ // Wildcards
+ assertMatch("someName", "bean(*someName)");
+ assertMatch("someName", "bean(*Name)");
+ assertMatch("someName", "bean(*)");
+ assertMatch("someName", "bean(someName*)");
+ assertMatch("someName", "bean(some*)");
+ assertMatch("someName", "bean(some*Name)");
+ assertMatch("someName", "bean(*some*Name*)");
+ assertMatch("someName", "bean(*s*N*)");
+
+ // Or, and, not expressions
+ assertMatch("someName", "bean(someName) || bean(someOtherName)");
+ assertMatch("someOtherName", "bean(someName) || bean(someOtherName)");
+
+ assertMatch("someName", "!bean(someOtherName)");
+
+ assertMatch("someName", "bean(someName) || !bean(someOtherName)");
+ assertMatch("someName", "bean(someName) && !bean(someOtherName)");
+ }
+
+ public void testNonMatchingPointcuts() {
+ assertMisMatch("someName", "bean(someNamex)");
+ assertMisMatch("someName", "bean(someX*Name)");
+
+ // And, not expressions
+ assertMisMatch("someName", "bean(someName) && bean(someOtherName)");
+ assertMisMatch("someName", "!bean(someName)");
+ assertMisMatch("someName", "!bean(someName) && bean(someOtherName)");
+ assertMisMatch("someName", "!bean(someName) || bean(someOtherName)");
+ }
+
+ private void assertMatch(String beanName, String pcExpression) {
+ assertTrue("Unexpected mismatch for bean \"" + beanName + "\" for pcExpression \"" + pcExpression + "\"",
+ matches(beanName, pcExpression));
+ }
+
+ private void assertMisMatch(String beanName, String pcExpression) {
+ assertFalse("Unexpected match for bean \"" + beanName + "\" for pcExpression \"" + pcExpression + "\"",
+ matches(beanName, pcExpression));
+ }
+
+ private static boolean matches(final String beanName, String pcExpression) {
+ AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut() {
+ protected String getCurrentProxiedBeanName() {
+ return beanName;
+ }
+ };
+ pointcut.setExpression(pcExpression);
+ return pointcut.matches(TestBean.class);
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/BeanNamePointcutTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/BeanNamePointcutTests.java
new file mode 100644
index 00000000000..7935a1777b9
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/BeanNamePointcutTests.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+
+import org.springframework.aop.MethodBeforeAdvice;
+import org.springframework.aop.framework.Advised;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
+
+/**
+ * Test for correct application of the bean() PCD for XML-based AspectJ aspects.
+ *
+ * @author Ramnivas Laddad
+ * @author Juergen Hoeller
+ */
+public class BeanNamePointcutTests extends AbstractDependencyInjectionSpringContextTests {
+
+ protected ITestBean testBean1;
+ protected ITestBean testBean2;
+ protected ITestBean testBeanContainingNestedBean;
+ protected Map testFactoryBean1;
+ protected Map testFactoryBean2;
+ protected Counter counterAspect;
+
+ protected ITestBean interceptThis;
+ protected ITestBean dontInterceptThis;
+ protected TestInterceptor testInterceptor;
+
+
+ public BeanNamePointcutTests() {
+ setPopulateProtectedVariables(true);
+ }
+
+ protected String getConfigPath() {
+ return "bean-name-pointcut-tests.xml";
+ }
+
+ protected void onSetUp() throws Exception {
+ this.counterAspect.reset();
+ super.onSetUp();
+ }
+
+
+ // We don't need to test all combination of pointcuts due to BeanNamePointcutMatchingTests
+
+ public void testMatchingBeanName() {
+ assertTrue("Matching bean must be advised (proxied)", this.testBean1 instanceof Advised);
+ // Call two methods to test for SPR-3953-like condition
+ this.testBean1.setAge(20);
+ this.testBean1.setName("");
+ assertEquals("Advice not executed: must have been", 2, this.counterAspect.getCount());
+ }
+
+ public void testNonMatchingBeanName() {
+ assertFalse("Non-matching bean must *not* be advised (proxied)", this.testBean2 instanceof Advised);
+ this.testBean2.setAge(20);
+ assertEquals("Advice must *not* have been executed", 0, this.counterAspect.getCount());
+ }
+
+ public void testNonMatchingNestedBeanName() {
+ assertFalse("Non-matching bean must *not* be advised (proxied)", this.testBeanContainingNestedBean.getDoctor() instanceof Advised);
+ }
+
+ public void testMatchingFactoryBeanObject() {
+ assertTrue("Matching bean must be advised (proxied)", this.testFactoryBean1 instanceof Advised);
+ assertEquals("myValue", this.testFactoryBean1.get("myKey"));
+ assertEquals("myValue", this.testFactoryBean1.get("myKey"));
+ assertEquals("Advice not executed: must have been", 2, this.counterAspect.getCount());
+ FactoryBean fb = (FactoryBean) getApplicationContext().getBean("&testFactoryBean1");
+ assertTrue("FactoryBean itself must *not* be advised", !(fb instanceof Advised));
+ }
+
+ public void testMatchingFactoryBeanItself() {
+ assertTrue("Matching bean must *not* be advised (proxied)", !(this.testFactoryBean2 instanceof Advised));
+ FactoryBean fb = (FactoryBean) getApplicationContext().getBean("&testFactoryBean2");
+ assertTrue("FactoryBean itself must be advised", fb instanceof Advised);
+ assertTrue(Map.class.isAssignableFrom(fb.getObjectType()));
+ assertTrue(Map.class.isAssignableFrom(fb.getObjectType()));
+ assertEquals("Advice not executed: must have been", 2, this.counterAspect.getCount());
+ }
+
+ public void testPointcutAdvisorCombination() {
+ assertTrue("Matching bean must be advised (proxied)", this.interceptThis instanceof Advised);
+ assertFalse("Non-matching bean must *not* be advised (proxied)", this.dontInterceptThis instanceof Advised);
+ interceptThis.setAge(20);
+ assertEquals(1, testInterceptor.interceptionCount);
+ dontInterceptThis.setAge(20);
+ assertEquals(1, testInterceptor.interceptionCount);
+ }
+
+
+ public static class TestInterceptor implements MethodBeforeAdvice {
+
+ private int interceptionCount;
+
+ public void before(Method method, Object[] args, Object target) throws Throwable {
+ interceptionCount++;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/BeforeAdviceBindingTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/BeforeAdviceBindingTests.java
new file mode 100644
index 00000000000..52792be6222
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/BeforeAdviceBindingTests.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import org.easymock.MockControl;
+
+import org.springframework.aop.aspectj.AdviceBindingTestAspect.AdviceBindingCollaborator;
+
+/**
+ * Tests for various parameter binding scenarios with before advice.
+ *
+ * @author Adrian Colyer
+ * @author Rod Johnson
+ */
+public class BeforeAdviceBindingTests extends AbstractAdviceBindingTests {
+
+ private AdviceBindingTestAspect beforeAdviceAspect;
+
+ private MockControl mockControl;
+
+ private AdviceBindingCollaborator mockCollaborator;
+
+
+ public void setBeforeAdviceAspect(AdviceBindingTestAspect anAspect) {
+ this.beforeAdviceAspect = anAspect;
+ }
+
+ protected String getConfigPath() {
+ return "before-advice-tests.xml";
+ }
+
+ protected void onSetUp() throws Exception {
+ super.onSetUp();
+ mockControl = MockControl.createNiceControl(AdviceBindingCollaborator.class);
+ mockCollaborator = (AdviceBindingCollaborator) mockControl.getMock();
+ beforeAdviceAspect.setCollaborator(mockCollaborator);
+ }
+
+
+ public void testOneIntArg() {
+ mockCollaborator.oneIntArg(5);
+ mockControl.replay();
+ testBeanProxy.setAge(5);
+ mockControl.verify();
+ }
+
+ public void testOneObjectArgBoundToProxyUsingThis() {
+ mockCollaborator.oneObjectArg(this.testBeanProxy);
+ mockControl.replay();
+ testBeanProxy.getAge();
+ mockControl.verify();
+ }
+
+ public void testOneIntAndOneObjectArgs() {
+ mockCollaborator.oneIntAndOneObject(5,this.testBeanTarget);
+ mockControl.replay();
+ testBeanProxy.setAge(5);
+ mockControl.verify();
+ }
+
+ public void testNeedsJoinPoint() {
+ mockCollaborator.needsJoinPoint("getAge");
+ mockControl.replay();
+ testBeanProxy.getAge();
+ mockControl.verify();
+ }
+
+ public void testNeedsJoinPointStaticPart() {
+ mockCollaborator.needsJoinPointStaticPart("getAge");
+ mockControl.replay();
+ testBeanProxy.getAge();
+ mockControl.verify();
+ }
+
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/CallCountingInterceptor.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/CallCountingInterceptor.java
new file mode 100644
index 00000000000..aa5eb61eddc
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/CallCountingInterceptor.java
@@ -0,0 +1,26 @@
+
+package org.springframework.aop.aspectj;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+/**
+ * @author robh
+ */
+class CallCountingInterceptor implements MethodInterceptor {
+
+ private int count;
+
+ public Object invoke(MethodInvocation methodInvocation) throws Throwable {
+ count++;
+ return methodInvocation.proceed();
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public void reset() {
+ this.count = 0;
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/Counter.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/Counter.java
new file mode 100644
index 00000000000..c8ae64ce444
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/Counter.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+/**
+ * A simple counter for use in simple tests (for example, how many times an advice was executed)
+ *
+ * @author Ramnivas Laddad
+ */
+public class Counter implements ICounter {
+
+ private int count;
+
+ public Counter() {
+ }
+
+ public void increment() {
+ count++;
+ }
+
+ public void decrement() {
+ count--;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public void setCount(int counter) {
+ this.count = counter;
+ }
+
+ public void reset() {
+ this.count = 0;
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/DeclarationOrderIndependenceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/DeclarationOrderIndependenceTests.java
new file mode 100644
index 00000000000..a962b3d04bf
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/DeclarationOrderIndependenceTests.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import java.io.Serializable;
+
+import org.springframework.beans.factory.BeanNameAware;
+import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
+
+/**
+ * @author Adrian Colyer
+ */
+public class DeclarationOrderIndependenceTests extends AbstractDependencyInjectionSpringContextTests {
+
+ private TopsyTurvyAspect aspect;
+
+ private TopsyTurvyTarget target;
+
+
+ public DeclarationOrderIndependenceTests() {
+ setAutowireMode(AUTOWIRE_BY_NAME);
+ }
+
+ public void setTopsyTurvyAspect(TopsyTurvyAspect aspect) {
+ this.aspect = aspect;
+ }
+
+ public void setTopsyTurvyTarget(TopsyTurvyTarget target) {
+ this.target = target;
+ }
+
+ protected String getConfigPath() {
+ return "topsy-turvy-aspect.xml";
+ }
+
+
+ public void testTargetIsSerializable() {
+ assertTrue("target bean is serializable",this.target instanceof Serializable);
+ }
+
+ public void testTargetIsBeanNameAware() {
+ assertTrue("target bean is bean name aware",this.target instanceof BeanNameAware);
+ }
+
+ public void testBeforeAdviceFiringOk() {
+ AspectCollaborator collab = new AspectCollaborator();
+ this.aspect.setCollaborator(collab);
+ this.target.doSomething();
+ assertTrue("before advice fired",collab.beforeFired);
+ }
+
+ public void testAroundAdviceFiringOk() {
+ AspectCollaborator collab = new AspectCollaborator();
+ this.aspect.setCollaborator(collab);
+ this.target.getX();
+ assertTrue("around advice fired",collab.aroundFired);
+ }
+
+ public void testAfterReturningFiringOk() {
+ AspectCollaborator collab = new AspectCollaborator();
+ this.aspect.setCollaborator(collab);
+ this.target.getX();
+ assertTrue("after returning advice fired",collab.afterReturningFired);
+ }
+
+ private static class AspectCollaborator implements TopsyTurvyAspect.Collaborator {
+
+ public boolean afterReturningFired = false;
+ public boolean aroundFired = false;
+ public boolean beforeFired = false;
+
+ /* (non-Javadoc)
+ * @see org.springframework.aop.aspectj.TopsyTurvyAspect.Collaborator#afterReturningAdviceFired()
+ */
+ public void afterReturningAdviceFired() {
+ this.afterReturningFired = true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.aop.aspectj.TopsyTurvyAspect.Collaborator#aroundAdviceFired()
+ */
+ public void aroundAdviceFired() {
+ this.aroundFired = true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.aop.aspectj.TopsyTurvyAspect.Collaborator#beforeAdviceFired()
+ */
+ public void beforeAdviceFired() {
+ this.beforeFired = true;
+ }
+
+ }
+}
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/DeclareParentsDelegateRefTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/DeclareParentsDelegateRefTests.java
new file mode 100644
index 00000000000..8da46feed6b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/DeclareParentsDelegateRefTests.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
+
+/**
+ * @author Ramnivas Laddad
+ */
+public class DeclareParentsDelegateRefTests extends AbstractDependencyInjectionSpringContextTests {
+
+ protected NoMethodsBean noMethodsBean;
+
+ protected CounterImpl counter;
+
+
+ public DeclareParentsDelegateRefTests() {
+ setPopulateProtectedVariables(true);
+ }
+
+ protected void onSetUp() throws Exception {
+ counter.reset();
+ }
+
+ protected String getConfigPath() {
+ return "declare-parents-delegate-ref-tests.xml";
+ }
+
+
+ public void testIntroductionWasMade() {
+ assertTrue("Introduction must have been made", noMethodsBean instanceof Counter);
+ }
+
+ public void testIntroductionDelegation() {
+ ((Counter)noMethodsBean).increment();
+ assertEquals("Delegate's counter should be updated", 1, counter.count);
+ }
+
+ public static interface NoMethodsBean {
+ }
+
+ public static class NoMethodsBeanImpl implements NoMethodsBean {
+ }
+
+ public static interface Counter {
+ public void increment();
+ }
+
+
+ public static class CounterImpl implements Counter {
+
+ int count;
+
+ public void increment() {
+ count++;
+ }
+
+ public void reset() {
+ count = 0;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/DeclareParentsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/DeclareParentsTests.java
new file mode 100644
index 00000000000..0eb09b31ec6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/DeclareParentsTests.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import org.springframework.aop.framework.Lockable;
+import org.springframework.aop.support.AopUtils;
+
+/**
+ * @author Rod Johnson
+ */
+public class DeclareParentsTests extends AbstractAdviceBindingTests {
+
+ protected String getConfigPath() {
+ return "declare-parents-tests.xml";
+ }
+
+ public void testIntroductionWasMade() {
+ assertTrue("Introduction must have been made", testBeanProxy instanceof Lockable);
+ }
+
+ // TODO if you change type pattern from org.springframework.beans..*
+ // to org.springframework..* it also matches introduction.
+ // Perhaps generated advisor bean definition could be made to depend
+ // on the introduction, in which case this would not be a problem.
+ public void testLockingWorks() {
+ Object introductionObject = applicationContext.getBean("introduction");
+ assertFalse("Introduction should not be proxied", AopUtils.isAopProxy(introductionObject));
+
+ Lockable lockable = (Lockable) testBeanProxy;
+ assertFalse(lockable.locked());
+
+ // Invoke a non-advised method
+ testBeanProxy.getAge();
+
+ testBeanProxy.setName("");
+ lockable.lock();
+ try {
+ testBeanProxy.setName(" ");
+ fail("Should be locked");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/ICounter.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/ICounter.java
new file mode 100644
index 00000000000..4c35daf9d80
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/ICounter.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+/**
+ * @author Ramnivas Laddad
+ */
+public interface ICounter {
+
+ void increment();
+
+ void decrement();
+
+ int getCount();
+
+ void setCount(int counter);
+
+ void reset();
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/ImplicitJPArgumentMatchingTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/ImplicitJPArgumentMatchingTests.java
new file mode 100644
index 00000000000..20662199d3d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/ImplicitJPArgumentMatchingTests.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.springframework.beans.TestBean;
+import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
+
+/**
+ * Tests to check if the first implicit join point argument is correctly processed.
+ * See SPR-3723 for more details.
+ *
+ * @author Ramnivas Laddad
+ */
+public class ImplicitJPArgumentMatchingTests extends AbstractDependencyInjectionSpringContextTests {
+ protected TestBean testBean;
+
+ public ImplicitJPArgumentMatchingTests() {
+ setPopulateProtectedVariables(true);
+ }
+
+ protected String getConfigPath() {
+ return "implicit-jp-argument-matching-tests.xml";
+ }
+
+ public void testAspect() {
+ // nothing to really test; it is enough if we don't get error while creating app context
+ testBean.setCountry("US");
+ }
+
+ public static class CounterAspect {
+ public void increment(ProceedingJoinPoint pjp, Object bean, Object argument) throws Throwable {
+ pjp.proceed();
+ }
+ }
+}
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/MethodInvocationProceedingJoinPointTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/MethodInvocationProceedingJoinPointTests.java
new file mode 100644
index 00000000000..0238e8caeb4
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/MethodInvocationProceedingJoinPointTests.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.JoinPoint.StaticPart;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.aspectj.lang.reflect.SourceLocation;
+
+import org.springframework.aop.MethodBeforeAdvice;
+import org.springframework.aop.framework.AopContext;
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+
+/**
+ * @author Rod Johnson
+ * @since 2.0
+ */
+public class MethodInvocationProceedingJoinPointTests extends TestCase {
+
+ public void testingBindingWithJoinPoint() {
+ try {
+ AbstractAspectJAdvice.currentJoinPoint();
+ fail("Needs to be bound by interceptor action");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ public void testingBindingWithProceedingJoinPoint() {
+ try {
+ AbstractAspectJAdvice.currentJoinPoint();
+ fail("Needs to be bound by interceptor action");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ public void testCanGetMethodSignatureFromJoinPoint() {
+ final Object raw = new TestBean();
+ // Will be set by advice during a method call
+ final int newAge = 23;
+
+ ProxyFactory pf = new ProxyFactory(raw);
+ pf.setExposeProxy(true);
+ pf.addAdvisor(ExposeInvocationInterceptor.ADVISOR);
+ pf.addAdvice(new MethodBeforeAdvice() {
+ private int depth;
+
+ public void before(Method method, Object[] args, Object target) throws Throwable {
+ JoinPoint jp = AbstractAspectJAdvice.currentJoinPoint();
+ assertTrue("Method named in toString", jp.toString().indexOf(method.getName()) != -1);
+ // Ensure that these don't cause problems
+ jp.toShortString();
+ jp.toLongString();
+
+ assertSame(target, AbstractAspectJAdvice.currentJoinPoint().getTarget());
+ assertFalse(AopUtils.isAopProxy(AbstractAspectJAdvice.currentJoinPoint().getTarget()));
+
+ ITestBean thisProxy = (ITestBean) AbstractAspectJAdvice.currentJoinPoint().getThis();
+ assertTrue(AopUtils.isAopProxy(AbstractAspectJAdvice.currentJoinPoint().getThis()));
+
+ assertNotSame(target, thisProxy);
+
+ // Check getting again doesn't cause a problem
+ assertSame(thisProxy, AbstractAspectJAdvice.currentJoinPoint().getThis());
+
+ // Try reentrant call--will go through this advice.
+ // Be sure to increment depth to avoid infinite recursion
+ if (depth++ == 0) {
+ // Check that toString doesn't cause a problem
+ thisProxy.toString();
+ // Change age, so this will be returned by invocation
+ thisProxy.setAge(newAge);
+ assertEquals(newAge, thisProxy.getAge());
+ }
+
+ assertSame(AopContext.currentProxy(), thisProxy);
+ assertSame(target, raw);
+
+ assertSame(method.getName(), AbstractAspectJAdvice.currentJoinPoint().getSignature().getName());
+ assertEquals(method.getModifiers(), AbstractAspectJAdvice.currentJoinPoint().getSignature().getModifiers());
+
+ MethodSignature msig = (MethodSignature) AbstractAspectJAdvice.currentJoinPoint().getSignature();
+ assertSame("Return same MethodSignature repeatedly", msig, AbstractAspectJAdvice.currentJoinPoint().getSignature());
+ assertSame("Return same JoinPoint repeatedly", AbstractAspectJAdvice.currentJoinPoint(), AbstractAspectJAdvice.currentJoinPoint());
+ assertEquals(method.getDeclaringClass(), msig.getDeclaringType());
+ assertTrue(Arrays.equals(method.getParameterTypes(), msig.getParameterTypes()));
+ assertEquals(method.getReturnType(), msig.getReturnType());
+ assertTrue(Arrays.equals(method.getExceptionTypes(), msig.getExceptionTypes()));
+ try {
+ msig.getParameterNames();
+ fail("Can't determine parameter names");
+ }
+ catch (UnsupportedOperationException ex) {
+ // Expected
+ }
+ msig.toLongString();
+ msig.toShortString();
+ }
+ });
+ ITestBean itb = (ITestBean) pf.getProxy();
+ // Any call will do
+ assertEquals("Advice reentrantly set age", newAge, itb.getAge());
+ }
+
+ public void testCanGetSourceLocationFromJoinPoint() {
+ final Object raw = new TestBean();
+ ProxyFactory pf = new ProxyFactory(raw);
+ pf.addAdvisor(ExposeInvocationInterceptor.ADVISOR);
+ pf.addAdvice(new MethodBeforeAdvice() {
+ public void before(Method method, Object[] args, Object target) throws Throwable {
+ SourceLocation sloc = AbstractAspectJAdvice.currentJoinPoint().getSourceLocation();
+ assertEquals("Same source location must be returned on subsequent requests", sloc, AbstractAspectJAdvice.currentJoinPoint().getSourceLocation());
+ assertEquals(TestBean.class, sloc.getWithinType());
+ try {
+ sloc.getLine();
+ fail("Can't get line number");
+ }
+ catch (UnsupportedOperationException ex) {
+ // Expected
+ }
+
+ try {
+ sloc.getFileName();
+ fail("Can't get file name");
+ }
+ catch (UnsupportedOperationException ex) {
+ // Expected
+ }
+ }
+ });
+ ITestBean itb = (ITestBean) pf.getProxy();
+ // Any call will do
+ itb.getAge();
+ }
+
+ public void testCanGetStaticPartFromJoinPoint() {
+ final Object raw = new TestBean();
+ ProxyFactory pf = new ProxyFactory(raw);
+ pf.addAdvisor(ExposeInvocationInterceptor.ADVISOR);
+ pf.addAdvice(new MethodBeforeAdvice() {
+ public void before(Method method, Object[] args, Object target) throws Throwable {
+ StaticPart staticPart = AbstractAspectJAdvice.currentJoinPoint().getStaticPart();
+ assertEquals("Same static part must be returned on subsequent requests", staticPart, AbstractAspectJAdvice.currentJoinPoint().getStaticPart());
+ assertEquals(ProceedingJoinPoint.METHOD_EXECUTION, staticPart.getKind());
+ assertSame(AbstractAspectJAdvice.currentJoinPoint().getSignature(), staticPart.getSignature());
+ assertEquals(AbstractAspectJAdvice.currentJoinPoint().getSourceLocation(), staticPart.getSourceLocation());
+ }
+ });
+ ITestBean itb = (ITestBean) pf.getProxy();
+ // Any call will do
+ itb.getAge();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/NonAnnotatedMakeLockable.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/NonAnnotatedMakeLockable.java
new file mode 100644
index 00000000000..e608d4e8d21
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/NonAnnotatedMakeLockable.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import org.springframework.aop.framework.Lockable;
+
+/**
+ * @author Rod Johnson
+ */
+public class NonAnnotatedMakeLockable {
+
+ public void checkNotLocked(Lockable mixin) {
+ if (mixin.locked()) {
+ throw new IllegalStateException("locked");
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/OverloadedAdviceTestAspect.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/OverloadedAdviceTestAspect.java
new file mode 100644
index 00000000000..196a6bc3ae2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/OverloadedAdviceTestAspect.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+
+/**
+ * Aspect used as part of overloaded advice tests.
+ * @author Adrian Colyer
+ */
+public class OverloadedAdviceTestAspect {
+
+ public void myBeforeAdvice(String name) {
+ // no-op
+ }
+
+ public void myBeforeAdvice(int age) {
+ // no-op
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/OverloadedAdviceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/OverloadedAdviceTests.java
new file mode 100644
index 00000000000..42d60c89cf6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/OverloadedAdviceTests.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * Tests for overloaded advice.
+ *
+ * @author Adrian Colyer
+ */
+public class OverloadedAdviceTests extends TestCase {
+
+ public void testExceptionOnConfigParsingWithMismatchedAdviceMethod() {
+ try {
+ new ClassPathXmlApplicationContext("org/springframework/aop/aspectj/overloaded-advice-tests.xml");
+ }
+ catch (BeanCreationException ex) {
+ Throwable cause = ex.getRootCause();
+ assertTrue("Should be IllegalArgumentException", cause instanceof IllegalArgumentException);
+ assertTrue("invalidAbsoluteTypeName should be detected by AJ",
+ cause.getMessage().indexOf("invalidAbsoluteTypeName") != -1);
+ }
+ }
+
+ public void testExceptionOnConfigParsingWithAmbiguousAdviceMethod() {
+ try {
+ new ClassPathXmlApplicationContext("org/springframework/aop/aspectj/ambiguous-advice-tests.xml");
+ }
+ catch (BeanCreationException ex) {
+ Throwable cause = ex.getRootCause();
+ assertTrue("Should be IllegalArgumentException", cause instanceof IllegalArgumentException);
+ assertTrue("Cannot resolve method 'myBeforeAdvice' to a unique method",
+ cause.getMessage().indexOf("Cannot resolve method 'myBeforeAdvice' to a unique method") != -1);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/PrecedenceTestAspect.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/PrecedenceTestAspect.java
new file mode 100644
index 00000000000..bf0b092bc62
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/PrecedenceTestAspect.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+
+import org.springframework.beans.factory.BeanNameAware;
+import org.springframework.core.Ordered;
+
+/**
+ * Used in advice precedence tests (surprise!)
+ *
+ * @author Adrian Colyer
+ */
+public class PrecedenceTestAspect implements BeanNameAware, Ordered {
+
+ private String name;
+
+ private int order = Ordered.LOWEST_PRECEDENCE;
+
+ private Collaborator collaborator;
+
+
+ public void setBeanName(String name) {
+ this.name = name;
+ }
+
+ public void setOrder(int order) {
+ this.order = order;
+ }
+
+ public int getOrder() {
+ return order;
+ }
+
+ public void setCollaborator(Collaborator collaborator) {
+ this.collaborator = collaborator;
+ }
+
+ public void beforeAdviceOne() {
+ this.collaborator.beforeAdviceOne(this.name);
+ }
+
+ public void beforeAdviceTwo() {
+ this.collaborator.beforeAdviceTwo(this.name);
+ }
+
+ public int aroundAdviceOne(ProceedingJoinPoint pjp) {
+ int ret = -1;
+ this.collaborator.aroundAdviceOne(this.name);
+ try {
+ ret = ((Integer)pjp.proceed()).intValue();
+ }
+ catch(Throwable t) { throw new RuntimeException(t); }
+ this.collaborator.aroundAdviceOne(this.name);
+ return ret;
+ }
+
+ public int aroundAdviceTwo(ProceedingJoinPoint pjp) {
+ int ret = -1;
+ this.collaborator.aroundAdviceTwo(this.name);
+ try {
+ ret = ((Integer)pjp.proceed()).intValue();
+ }
+ catch(Throwable t) {throw new RuntimeException(t);}
+ this.collaborator.aroundAdviceTwo(this.name);
+ return ret;
+ }
+
+ public void afterAdviceOne() {
+ this.collaborator.afterAdviceOne(this.name);
+ }
+
+ public void afterAdviceTwo() {
+ this.collaborator.afterAdviceTwo(this.name);
+ }
+
+
+ public interface Collaborator {
+
+ void beforeAdviceOne(String beanName);
+ void beforeAdviceTwo(String beanName);
+ void aroundAdviceOne(String beanName);
+ void aroundAdviceTwo(String beanName);
+ void afterAdviceOne(String beanName);
+ void afterAdviceTwo(String beanName);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/ProceedTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/ProceedTests.java
new file mode 100644
index 00000000000..b882dcc83fb
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/ProceedTests.java
@@ -0,0 +1,214 @@
+/**
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.ProceedingJoinPoint;
+
+import org.springframework.core.JdkVersion;
+import org.springframework.core.Ordered;
+import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
+
+/**
+ * Test for SPR-3522. Arguments changed on a call to proceed should be
+ * visible to advice further down the invocation chain.
+ *
+ * @author Adrian Colyer
+ */
+public class ProceedTests extends AbstractDependencyInjectionSpringContextTests {
+
+ private SimpleBean testBean;
+
+ private ProceedTestingAspect testAspect;
+
+ private ProceedTestingAspect secondTestAspect;
+
+
+ public ProceedTests() {
+ setAutowireMode(AUTOWIRE_BY_NAME);
+ }
+
+ protected String[] getConfigLocations() {
+ return new String[] {"org/springframework/aop/aspectj/proceedTests.xml"};
+ }
+
+ public void setFirstTestAspect(ProceedTestingAspect anAspect) {
+ this.testAspect = anAspect;
+ }
+
+ public void setSecondTestAspect(ProceedTestingAspect anAspect) {
+ this.secondTestAspect = anAspect;
+ }
+
+ public void setTestBean(SimpleBean aBean) {
+ this.testBean = aBean;
+ }
+
+
+ public void testSimpleProceedWithChangedArgs() {
+ this.testBean.setName("abc");
+ assertEquals("Name changed in around advice", "ABC", this.testBean.getName());
+ }
+
+ public void testGetArgsIsDefensive() {
+ this.testBean.setAge(5);
+ assertEquals("getArgs is defensive", 5, this.testBean.getAge());
+ }
+
+ public void testProceedWithArgsInSameAspect() {
+ if (!JdkVersion.isAtLeastJava15()) {
+ // Doesn't work on JDK 1.4 for some reason...
+ return;
+ }
+
+ this.testBean.setMyFloat(1.0F);
+ assertTrue("value changed in around advice", this.testBean.getMyFloat() > 1.9F);
+ assertTrue("changed value visible to next advice in chain", this.testAspect.getLastBeforeFloatValue() > 1.9F);
+ }
+
+ public void testProceedWithArgsAcrossAspects() {
+ this.testBean.setSex("male");
+ assertEquals("value changed in around advice","MALE", this.testBean.getSex());
+ assertEquals("changed value visible to next before advice in chain","MALE", this.secondTestAspect.getLastBeforeStringValue());
+ assertEquals("changed value visible to next around advice in chain","MALE", this.secondTestAspect.getLastAroundStringValue());
+ }
+
+
+ public interface SimpleBean {
+
+ public void setName(String name);
+ public String getName();
+ public void setAge(int age);
+ public int getAge();
+ public void setMyFloat(float f);
+ public float getMyFloat();
+ public void setSex(String sex);
+ public String getSex();
+ }
+
+
+ public static class SimpleBeanImpl implements SimpleBean {
+
+ private int age;
+ private float aFloat;
+ private String name;
+ private String sex;
+
+ public int getAge() {
+ return age;
+ }
+
+ public float getMyFloat() {
+ return aFloat;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getSex() {
+ return sex;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ public void setMyFloat(float f) {
+ this.aFloat = f;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setSex(String sex) {
+ this.sex = sex;
+ }
+ }
+
+
+ public static class ProceedTestingAspect implements Ordered {
+
+ private String lastBeforeStringValue;
+ private String lastAroundStringValue;
+ private float lastBeforeFloatValue;
+ private int order;
+
+ public void setOrder(int order) { this.order = order; }
+ public int getOrder() { return this.order; }
+
+ public Object capitalize(ProceedingJoinPoint pjp, String value) throws Throwable {
+ return pjp.proceed(new Object[] {value.toUpperCase()});
+ }
+
+ public Object doubleOrQuits(ProceedingJoinPoint pjp) throws Throwable {
+ int value = ((Integer) pjp.getArgs()[0]).intValue();
+ pjp.getArgs()[0] = new Integer(value * 2);
+ return pjp.proceed();
+ }
+
+ public Object addOne(ProceedingJoinPoint pjp, Float value) throws Throwable {
+ float fv = value.floatValue();
+ return pjp.proceed(new Object[] {new Float(fv + 1.0F)});
+ }
+
+ public void captureStringArgument(JoinPoint tjp, String arg) {
+ if (!tjp.getArgs()[0].equals(arg)) {
+ throw new IllegalStateException(
+ "argument is '" + arg + "', " +
+ "but args array has '" + tjp.getArgs()[0] + "'"
+ );
+ }
+ this.lastBeforeStringValue = arg;
+ }
+
+ public Object captureStringArgumentInAround(ProceedingJoinPoint pjp, String arg) throws Throwable {
+ if (!pjp.getArgs()[0].equals(arg)) {
+ throw new IllegalStateException(
+ "argument is '" + arg + "', " +
+ "but args array has '" + pjp.getArgs()[0] + "'");
+ }
+ this.lastAroundStringValue = arg;
+ return pjp.proceed();
+ }
+
+ public void captureFloatArgument(JoinPoint tjp, float arg) {
+ float tjpArg = ((Float) tjp.getArgs()[0]).floatValue();
+ if (Math.abs(tjpArg - arg) > 0.000001) {
+ throw new IllegalStateException(
+ "argument is '" + arg + "', " +
+ "but args array has '" + tjpArg + "'"
+ );
+ }
+ this.lastBeforeFloatValue = arg;
+ }
+
+ public String getLastBeforeStringValue() {
+ return this.lastBeforeStringValue;
+ }
+
+ public String getLastAroundStringValue() {
+ return this.lastAroundStringValue;
+ }
+
+ public float getLastBeforeFloatValue() {
+ return this.lastBeforeFloatValue;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/SerializableMixin.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/SerializableMixin.java
new file mode 100644
index 00000000000..2046942aa42
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/SerializableMixin.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.
+ *
+ * Created on 15 Nov 2006 by Adrian Colyer
+ */
+package org.springframework.aop.aspectj;
+
+import java.io.Serializable;
+
+/**
+ * @author Adrian Colyer
+ * @since 2.0
+ */
+public class SerializableMixin implements Serializable {
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/SharedPointcutWithArgsMismatch.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/SharedPointcutWithArgsMismatch.java
new file mode 100644
index 00000000000..9083ebe1df5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/SharedPointcutWithArgsMismatch.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
+
+/**
+ * See SPR-1682.
+ *
+ * @author Adrian Colyer
+ */
+public class SharedPointcutWithArgsMismatch extends AbstractDependencyInjectionSpringContextTests {
+
+ private ToBeAdvised toBeAdvised;
+
+
+ public void setToBeAdvised(ToBeAdvised tba) {
+ this.toBeAdvised = tba;
+ }
+
+ protected String getConfigPath() {
+ return "args-mismatch.xml";
+ }
+
+
+ public void testMismatchedArgBinding() {
+ this.toBeAdvised.foo("Hello");
+ }
+
+
+ public static class ToBeAdvised {
+
+ public void foo(String s) {
+ System.out.println(s);
+ }
+ }
+
+
+ public static class MyAspect {
+
+ public void doBefore(int x) {
+ System.out.println(x);
+ }
+
+ public void doBefore(String x) {
+ System.out.println(x);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/SimpleSpringBeforeAdvice.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/SimpleSpringBeforeAdvice.java
new file mode 100644
index 00000000000..77a3ca45ef9
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/SimpleSpringBeforeAdvice.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.
+ *
+ * Created on 14-Feb-2006 by Adrian Colyer
+ */
+package org.springframework.aop.aspectj;
+
+import java.lang.reflect.Method;
+
+import org.springframework.aop.MethodBeforeAdvice;
+import org.springframework.beans.factory.BeanNameAware;
+
+/**
+ * Used as part of aspect precedence tests
+ *
+ * @author Adrian Colyer
+ * @since 2.0
+ */
+public class SimpleSpringBeforeAdvice implements MethodBeforeAdvice, BeanNameAware {
+
+ private PrecedenceTestAspect.Collaborator collaborator;
+ private String name;
+
+ /* (non-Javadoc)
+ * @see org.springframework.aop.MethodBeforeAdvice#before(java.lang.reflect.Method, java.lang.Object[], java.lang.Object)
+ */
+ public void before(Method method, Object[] args, Object target)
+ throws Throwable {
+ this.collaborator.beforeAdviceOne(this.name);
+ }
+
+ public void setCollaborator(PrecedenceTestAspect.Collaborator collaborator) {
+ this.collaborator = collaborator;
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String)
+ */
+ public void setBeanName(String name) {
+ this.name = name;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/SubtypeMatchingTestClasses.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/SubtypeMatchingTestClasses.java
new file mode 100644
index 00000000000..ce5a77189fc
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/SubtypeMatchingTestClasses.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import java.io.Serializable;
+
+
+// strange looking interfaces are just to set up certain test conditions...
+interface NonSerializableFoo { void foo(); }
+interface SerializableFoo extends Serializable { void foo(); }
+
+class SubtypeMatchingTestClassA implements NonSerializableFoo {
+
+ public void foo() {}
+
+}
+
+class SubtypeMatchingTestClassB implements SerializableFoo {
+
+ public void foo() {}
+
+}
+
+interface Bar { void bar(Object o); }
+
+class SubtypeMatchingTestClassC implements Bar {
+
+ public void bar(Object o) {}
+
+}
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/SubtypeSensitiveMatchingTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/SubtypeSensitiveMatchingTests.java
new file mode 100644
index 00000000000..13dff54d618
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/SubtypeSensitiveMatchingTests.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import org.springframework.aop.framework.Advised;
+import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
+
+/**
+ * @author Adrian Colyer
+ */
+public class SubtypeSensitiveMatchingTests extends AbstractDependencyInjectionSpringContextTests {
+
+ private NonSerializableFoo nonSerializableBean;
+
+ private SerializableFoo serializableBean;
+
+ private Bar bar;
+
+
+ public void setNonSerializableFoo(NonSerializableFoo aBean) {
+ this.nonSerializableBean = aBean;
+ }
+
+ public void setSerializableFoo(SerializableFoo aBean) {
+ this.serializableBean = aBean;
+ }
+
+ public void setBar(Bar aBean) {
+ this.bar = aBean;
+ }
+
+ protected String getConfigPath() {
+ return "subtype-sensitive-matching.xml";
+ }
+
+
+ public void testBeansAreProxiedOnStaticMatch() {
+ assertTrue("bean with serializable type should be proxied",
+ this.serializableBean instanceof Advised);
+ }
+
+ public void testBeansThatDoNotMatchBasedSolelyOnRuntimeTypeAreNotProxied() {
+ assertFalse("bean with non-serializable type should not be proxied",
+ this.nonSerializableBean instanceof Advised);
+ }
+
+ public void testBeansThatDoNotMatchBasedOnOtherTestAreProxied() {
+ assertTrue("bean with args check should be proxied",
+ this.bar instanceof Advised);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/TargetPointcutSelectionTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/TargetPointcutSelectionTests.java
new file mode 100644
index 00000000000..1146b777f61
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/TargetPointcutSelectionTests.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
+
+/**
+ * Tests for target selection matching (see SPR-3783).
+ * Thanks to Tomasz Blachowicz for the bug report!
+ *
+ * @author Ramnivas Laddad
+ */
+public class TargetPointcutSelectionTests extends AbstractDependencyInjectionSpringContextTests {
+
+ protected TestInterface testImpl1;
+ protected TestInterface testImpl2;
+ protected TestAspect testAspectForTestImpl1;
+ protected TestAspect testAspectForAbstractTestImpl;
+ protected TestInterceptor testInterceptor;
+
+
+ public TargetPointcutSelectionTests() {
+ setPopulateProtectedVariables(true);
+ }
+
+ protected String getConfigPath() {
+ return "targetPointcutSelectionTests.xml";
+ }
+
+ protected void onSetUp() throws Exception {
+ testAspectForTestImpl1.count = 0;
+ testAspectForAbstractTestImpl.count = 0;
+ testInterceptor.count = 0;
+ super.onSetUp();
+ }
+
+
+ public void testTargetSelectionForMatchedType() {
+ testImpl1.interfaceMethod();
+ assertEquals("Should have been advised by POJO advice for impl", 1, testAspectForTestImpl1.count);
+ assertEquals("Should have been advised by POJO advice for base type", 1, testAspectForAbstractTestImpl.count);
+ assertEquals("Should have been advised by advisor", 1, testInterceptor.count);
+ }
+
+ public void testTargetNonSelectionForMismatchedType() {
+ testImpl2.interfaceMethod();
+ assertEquals("Shouldn't have been advised by POJO advice for impl", 0, testAspectForTestImpl1.count);
+ assertEquals("Should have been advised by POJO advice for base type", 1, testAspectForAbstractTestImpl.count);
+ assertEquals("Shouldn't have been advised by advisor", 0, testInterceptor.count);
+ }
+
+
+ public static interface TestInterface {
+
+ public void interfaceMethod();
+ }
+
+
+ // Reproducing bug requires that the class specified in target() pointcut doesn't
+ // include the advised method's implementation (instead a base class should include it)
+ public static abstract class AbstractTestImpl implements TestInterface {
+
+ public void interfaceMethod() {
+ }
+ }
+
+
+ public static class TestImpl1 extends AbstractTestImpl {
+ }
+
+
+ public static class TestImpl2 extends AbstractTestImpl {
+ }
+
+
+ public static class TestAspect {
+
+ public int count;
+
+ public void increment() {
+ count++;
+ }
+ }
+
+
+ public static class TestInterceptor extends TestAspect implements MethodInterceptor {
+
+ public Object invoke(MethodInvocation mi) throws Throwable {
+ increment();
+ return mi.proceed();
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/ThisAndTargetSelectionOnlyPointcutsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/ThisAndTargetSelectionOnlyPointcutsTests.java
new file mode 100644
index 00000000000..f2b470e738e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/ThisAndTargetSelectionOnlyPointcutsTests.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
+
+/**
+ * @author Ramnivas Laddad
+ */
+public class ThisAndTargetSelectionOnlyPointcutsTests extends AbstractDependencyInjectionSpringContextTests {
+ protected TestInterface testBean;
+
+ protected Counter thisAsClassCounter;
+ protected Counter thisAsInterfaceCounter;
+ protected Counter targetAsClassCounter;
+ protected Counter targetAsInterfaceCounter;
+ protected Counter thisAsClassAndTargetAsClassCounter;
+ protected Counter thisAsInterfaceAndTargetAsInterfaceCounter;
+ protected Counter thisAsInterfaceAndTargetAsClassCounter;
+
+ public ThisAndTargetSelectionOnlyPointcutsTests() {
+ setPopulateProtectedVariables(true);
+ }
+
+ protected void onSetUp() throws Exception {
+ super.onSetUp();
+ thisAsClassCounter.reset();
+ thisAsInterfaceCounter.reset();
+ targetAsClassCounter.reset();
+ targetAsInterfaceCounter.reset();
+
+ thisAsClassAndTargetAsClassCounter.reset();
+ thisAsInterfaceAndTargetAsInterfaceCounter.reset();
+ thisAsInterfaceAndTargetAsClassCounter.reset();
+ }
+
+ protected String getConfigPath() {
+ return "this-and-target-selectionOnly-pointcuts-tests.xml";
+ }
+
+ public void testThisAsClassDoesNotMatch() {
+ testBean.doIt();
+ assertEquals(0, thisAsClassCounter.getCount());
+ }
+
+ public void testThisAsInterfaceMatch() {
+ testBean.doIt();
+ assertEquals(1, thisAsInterfaceCounter.getCount());
+ }
+
+ public void testTargetAsClassDoesMatch() {
+ testBean.doIt();
+ assertEquals(1, targetAsClassCounter.getCount());
+ }
+
+ public void testTargetAsInterfaceMatch() {
+ testBean.doIt();
+ assertEquals(1, targetAsInterfaceCounter.getCount());
+ }
+
+ public void testThisAsClassAndTargetAsClassCounterNotMatch() {
+ testBean.doIt();
+ assertEquals(0, thisAsClassAndTargetAsClassCounter.getCount());
+ }
+
+ public void testThisAsInterfaceAndTargetAsInterfaceCounterMatch() {
+ testBean.doIt();
+ assertEquals(1, thisAsInterfaceAndTargetAsInterfaceCounter.getCount());
+ }
+
+ public void testThisAsInterfaceAndTargetAsClassCounterMatch() {
+ testBean.doIt();
+ assertEquals(1, thisAsInterfaceAndTargetAsInterfaceCounter.getCount());
+ }
+
+ public static interface TestInterface {
+ public void doIt();
+ }
+
+ public static class TestImpl implements TestInterface {
+ public void doIt() {
+ }
+ }
+}
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/TopsyTurvyAspect.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/TopsyTurvyAspect.java
new file mode 100644
index 00000000000..489f7621323
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/TopsyTurvyAspect.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.
+ *
+ * Created on 15 Nov 2006 by Adrian Colyer
+ */
+package org.springframework.aop.aspectj;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+
+/**
+ * @author Adrian Colyer
+ * @since 2.0
+ */
+public class TopsyTurvyAspect {
+
+ interface Collaborator {
+ void beforeAdviceFired();
+ void afterReturningAdviceFired();
+ void aroundAdviceFired();
+ }
+
+ private Collaborator collaborator;
+
+ public void setCollaborator(Collaborator collaborator) {
+ this.collaborator = collaborator;
+ }
+
+ public void before() {
+ this.collaborator.beforeAdviceFired();
+ }
+
+ public void afterReturning() {
+ this.collaborator.afterReturningAdviceFired();
+ }
+
+ public Object around(ProceedingJoinPoint pjp) throws Throwable {
+ Object ret = pjp.proceed();
+ this.collaborator.aroundAdviceFired();
+ return ret;
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/TopsyTurvyTarget.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/TopsyTurvyTarget.java
new file mode 100644
index 00000000000..3cb679c0de7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/TopsyTurvyTarget.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.
+ *
+ * Created on 15 Nov 2006 by Adrian Colyer
+ */
+package org.springframework.aop.aspectj;
+
+/**
+ * @author Adrian Colyer
+ * @since 2.0
+ */
+public interface TopsyTurvyTarget {
+
+ public abstract void doSomething();
+
+ public abstract int getX();
+
+}
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/TopsyTurvyTargetImpl.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/TopsyTurvyTargetImpl.java
new file mode 100644
index 00000000000..bfebb397bb6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/TopsyTurvyTargetImpl.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.
+ *
+ * Created on 15 Nov 2006 by Adrian Colyer
+ */
+package org.springframework.aop.aspectj;
+
+/**
+ * @author Adrian Colyer
+ * @since 2.0
+ */
+public class TopsyTurvyTargetImpl implements TopsyTurvyTarget {
+
+ private int x = 5;
+
+ /* (non-Javadoc)
+ * @see org.springframework.aop.aspectj.TopsyTurvyTarget#doSomething()
+ */
+ public void doSomething() {
+ this.x = 10;
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.aop.aspectj.TopsyTurvyTarget#getX()
+ */
+ public int getX() {
+ return x;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/TypePatternClassFilterTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/TypePatternClassFilterTests.java
new file mode 100644
index 00000000000..d6deb96c0ab
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/TypePatternClassFilterTests.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj;
+
+import junit.framework.TestCase;
+import org.springframework.aop.framework.autoproxy.CountingTestBean;
+import org.springframework.beans.IOther;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.test.AssertThrows;
+
+/**
+ * Unit tests for the {@link TypePatternClassFilter} class.
+ *
+ * @author Rod Johnson
+ * @author Rick Evans
+ */
+public final class TypePatternClassFilterTests extends TestCase {
+
+ public void testInvalidPattern() {
+ try {
+ new TypePatternClassFilter("-");
+ fail("Pattern must be recognized as invalid.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testValidPatternMatching() {
+ TypePatternClassFilter tpcf = new TypePatternClassFilter("org.springframework.beans.*");
+ assertTrue("Must match: in package", tpcf.matches(TestBean.class));
+ assertTrue("Must match: in package", tpcf.matches(ITestBean.class));
+ assertTrue("Must match: in package", tpcf.matches(IOther.class));
+ assertFalse("Must be excluded: in wrong package", tpcf.matches(CountingTestBean.class));
+ assertFalse("Must be excluded: in wrong package", tpcf.matches(BeanFactory.class));
+ assertFalse("Must be excluded: in wrong package", tpcf.matches(DefaultListableBeanFactory.class));
+ }
+
+ public void testSubclassMatching() {
+ TypePatternClassFilter tpcf = new TypePatternClassFilter("org.springframework.beans.ITestBean+");
+ assertTrue("Must match: in package", tpcf.matches(TestBean.class));
+ assertTrue("Must match: in package", tpcf.matches(ITestBean.class));
+ assertTrue("Must match: in package", tpcf.matches(CountingTestBean.class));
+ assertFalse("Must be excluded: not subclass", tpcf.matches(IOther.class));
+ assertFalse("Must be excluded: not subclass", tpcf.matches(DefaultListableBeanFactory.class));
+ }
+
+ public void testAndOrNotReplacement() {
+ TypePatternClassFilter tpcf = new TypePatternClassFilter("java.lang.Object or java.lang.String");
+ assertFalse("matches Number",tpcf.matches(Number.class));
+ assertTrue("matches Object",tpcf.matches(Object.class));
+ assertTrue("matchesString",tpcf.matches(String.class));
+ tpcf = new TypePatternClassFilter("java.lang.Number+ and java.lang.Float");
+ assertTrue("matches Float",tpcf.matches(Float.class));
+ assertFalse("matches Double",tpcf.matches(Double.class));
+ tpcf = new TypePatternClassFilter("java.lang.Number+ and not java.lang.Float");
+ assertFalse("matches Float",tpcf.matches(Float.class));
+ assertTrue("matches Double",tpcf.matches(Double.class));
+ }
+
+ public void testSetTypePatternWithNullArgument() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new TypePatternClassFilter(null);
+ }
+ }.runTest();
+ }
+
+ public void testInvocationOfMatchesMethodBlowsUpWhenNoTypePatternHasBeenSet() throws Exception {
+ new AssertThrows(IllegalStateException.class) {
+ public void test() throws Exception {
+ new TypePatternClassFilter().matches(String.class);
+ }
+ }.runTest();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/advice-precedence-tests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/advice-precedence-tests.xml
new file mode 100644
index 00000000000..6dae894ae62
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/advice-precedence-tests.xml
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/after-advice-tests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/after-advice-tests.xml
new file mode 100644
index 00000000000..9a55cc823e3
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/after-advice-tests.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/afterReturning-advice-tests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/afterReturning-advice-tests.xml
new file mode 100644
index 00000000000..197afbf0695
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/afterReturning-advice-tests.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/afterThrowing-advice-tests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/afterThrowing-advice-tests.xml
new file mode 100644
index 00000000000..9152fe1853e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/afterThrowing-advice-tests.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/ambiguous-advice-tests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/ambiguous-advice-tests.xml
new file mode 100644
index 00000000000..3268b8ccecc
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/ambiguous-advice-tests.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/args-mismatch.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/args-mismatch.xml
new file mode 100644
index 00000000000..d82ac51900c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/args-mismatch.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/around-advice-circular-tests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/around-advice-circular-tests.xml
new file mode 100644
index 00000000000..7f947101837
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/around-advice-circular-tests.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/around-advice-tests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/around-advice-tests.xml
new file mode 100644
index 00000000000..91ca7c6540c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/around-advice-tests.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/aspectj.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/aspectj.xml
new file mode 100644
index 00000000000..8a23b5ad4d5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/aspectj.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/autoproxy/AspectImplementingInterfaceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/autoproxy/AspectImplementingInterfaceTests.java
new file mode 100644
index 00000000000..3ef06b4001b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/autoproxy/AspectImplementingInterfaceTests.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj.autoproxy;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.springframework.aop.framework.Advised;
+import org.springframework.beans.ITestBean;
+import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
+
+/**
+ * Test for ensuring the aspects aren't advised. See SPR-3893 for more details.
+ *
+ * @author Ramnivas Laddad
+ */
+public class AspectImplementingInterfaceTests extends AbstractDependencyInjectionSpringContextTests {
+ protected ITestBean testBean;
+ protected AnInterface interfaceExtendingAspect;
+
+ public AspectImplementingInterfaceTests() {
+ setPopulateProtectedVariables(true);
+ }
+
+ protected String getConfigPath() {
+ return "aspect-implementing-interface-tests.xml";
+ }
+
+ protected void onSetUp() throws Exception {
+ super.onSetUp();
+ }
+
+ public void testProxyCreation() {
+ assertTrue(testBean instanceof Advised);
+ assertFalse(interfaceExtendingAspect instanceof Advised);
+ }
+
+ public static interface AnInterface {
+ public void interfaceMethod();
+ }
+
+ public static class InterfaceExtendingAspect implements AnInterface {
+ public void increment(ProceedingJoinPoint pjp) throws Throwable {
+ pjp.proceed();
+ }
+
+ public void interfaceMethod() {
+ }
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/autoproxy/AspectJPrecedenceComparatorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/autoproxy/AspectJPrecedenceComparatorTests.java
new file mode 100644
index 00000000000..7e8374f4b3a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/autoproxy/AspectJPrecedenceComparatorTests.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.aspectj.autoproxy;
+
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.Advisor;
+import org.springframework.aop.AfterReturningAdvice;
+import org.springframework.aop.BeforeAdvice;
+import org.springframework.aop.aspectj.AbstractAspectJAdvice;
+import org.springframework.aop.aspectj.AspectJAfterAdvice;
+import org.springframework.aop.aspectj.AspectJAfterReturningAdvice;
+import org.springframework.aop.aspectj.AspectJAfterThrowingAdvice;
+import org.springframework.aop.aspectj.AspectJAroundAdvice;
+import org.springframework.aop.aspectj.AspectJExpressionPointcut;
+import org.springframework.aop.aspectj.AspectJMethodBeforeAdvice;
+import org.springframework.aop.aspectj.AspectJPointcutAdvisor;
+import org.springframework.aop.support.DefaultPointcutAdvisor;
+
+/**
+ * @author Adrian Colyer
+ */
+public class AspectJPrecedenceComparatorTests extends TestCase {
+
+ /*
+ * Specification for the comparator (as defined in the
+ * AspectJPrecedenceComparator class)
+ *
+ *
+ * Orders AspectJ advice/advisors by invocation order.
+ *
+ *
+ * Given two pieces of advice, a and b:
+ *
+ *
+ *
if a and b are defined in different
+ * aspects, then the advice in the aspect with the lowest order
+ * value has the highest precedence
+ *
if a and b are defined in the same
+ * aspect, then if one of a or b is a form of
+ * after advice, then the advice declared last in the aspect has the
+ * highest precedence. If neither a nor b is a
+ * form of after advice, then the advice declared first in the aspect has
+ * the highest precedence.
+ *
+ */
+
+ private static final int HIGH_PRECEDENCE_ADVISOR_ORDER = 100;
+ private static final int LOW_PRECEDENCE_ADVISOR_ORDER = 200;
+ private static final int EARLY_ADVICE_DECLARATION_ORDER = 5;
+ private static final int LATE_ADVICE_DECLARATION_ORDER = 10;
+
+
+ private AspectJPrecedenceComparator comparator;
+
+ private Method anyOldMethod;
+
+ private AspectJExpressionPointcut anyOldPointcut;
+
+
+ protected void setUp() throws Exception {
+ this.comparator = new AspectJPrecedenceComparator();
+ this.anyOldMethod = getClass().getMethods()[0];
+ this.anyOldPointcut = new AspectJExpressionPointcut();
+ this.anyOldPointcut.setExpression("execution(* *(..))");
+ }
+
+
+ public void testSameAspectNoAfterAdvice() {
+ Advisor advisor1 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
+ Advisor advisor2 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
+ assertEquals("advisor1 sorted before advisor2", -1, this.comparator.compare(advisor1, advisor2));
+
+ advisor1 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
+ advisor2 = createAspectJAroundAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
+ assertEquals("advisor2 sorted before advisor1", 1, this.comparator.compare(advisor1, advisor2));
+ }
+
+ public void testSameAspectAfterAdvice() {
+ Advisor advisor1 = createAspectJAfterAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
+ Advisor advisor2 = createAspectJAroundAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
+ assertEquals("advisor2 sorted before advisor1", 1, this.comparator.compare(advisor1, advisor2));
+
+ advisor1 = createAspectJAfterReturningAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
+ advisor2 = createAspectJAfterThrowingAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
+ assertEquals("advisor1 sorted before advisor2", -1, this.comparator.compare(advisor1, advisor2));
+ }
+
+ public void testSameAspectOneOfEach() {
+ Advisor advisor1 = createAspectJAfterAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
+ Advisor advisor2 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
+ assertEquals("advisor1 and advisor2 not comparable", 0, this.comparator.compare(advisor1, advisor2));
+ }
+
+ public void testSameAdvisorPrecedenceDifferentAspectNoAfterAdvice() {
+ Advisor advisor1 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
+ Advisor advisor2 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someOtherAspect");
+ assertEquals("nothing to say about order here", 0, this.comparator.compare(advisor1, advisor2));
+
+ advisor1 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
+ advisor2 = createAspectJAroundAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someOtherAspect");
+ assertEquals("nothing to say about order here", 0, this.comparator.compare(advisor1, advisor2));
+ }
+
+ public void testSameAdvisorPrecedenceDifferentAspectAfterAdvice() {
+ Advisor advisor1 = createAspectJAfterAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
+ Advisor advisor2 = createAspectJAroundAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someOtherAspect");
+ assertEquals("nothing to say about order here", 0, this.comparator.compare(advisor1, advisor2));
+
+ advisor1 = createAspectJAfterReturningAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
+ advisor2 = createAspectJAfterThrowingAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someOtherAspect");
+ assertEquals("nothing to say about order here", 0, this.comparator.compare(advisor1, advisor2));
+ }
+
+ public void testHigherAdvisorPrecedenceNoAfterAdvice() {
+ Advisor advisor1 = createSpringAOPBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER);
+ Advisor advisor2 = createAspectJBeforeAdvice(LOW_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someOtherAspect");
+ assertEquals("advisor1 sorted before advisor2", -1, this.comparator.compare(advisor1, advisor2));
+
+ advisor1 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
+ advisor2 = createAspectJAroundAdvice(LOW_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someOtherAspect");
+ assertEquals("advisor1 sorted before advisor2", -1, this.comparator.compare(advisor1, advisor2));
+ }
+
+ public void testHigherAdvisorPrecedenceAfterAdvice() {
+ Advisor advisor1 = createAspectJAfterAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
+ Advisor advisor2 = createAspectJAroundAdvice(LOW_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someOtherAspect");
+ assertEquals("advisor1 sorted before advisor2", -1, this.comparator.compare(advisor1, advisor2));
+
+ advisor1 = createAspectJAfterReturningAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
+ advisor2 = createAspectJAfterThrowingAdvice(LOW_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someOtherAspect");
+ assertEquals("advisor2 sorted after advisor1", -1, this.comparator.compare(advisor1, advisor2));
+ }
+
+ public void testLowerAdvisorPrecedenceNoAfterAdvice() {
+ Advisor advisor1 = createAspectJBeforeAdvice(LOW_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
+ Advisor advisor2 = createAspectJBeforeAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someOtherAspect");
+ assertEquals("advisor1 sorted after advisor2", 1, this.comparator.compare(advisor1, advisor2));
+
+ advisor1 = createAspectJBeforeAdvice(LOW_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someAspect");
+ advisor2 = createAspectJAroundAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someOtherAspect");
+ assertEquals("advisor1 sorted after advisor2", 1, this.comparator.compare(advisor1, advisor2));
+ }
+
+ public void testLowerAdvisorPrecedenceAfterAdvice() {
+ Advisor advisor1 = createAspectJAfterAdvice(LOW_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someAspect");
+ Advisor advisor2 = createAspectJAroundAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, LATE_ADVICE_DECLARATION_ORDER, "someOtherAspect");
+ assertEquals("advisor1 sorted after advisor2", 1, this.comparator.compare(advisor1, advisor2));
+
+ advisor1 = createSpringAOPAfterAdvice(LOW_PRECEDENCE_ADVISOR_ORDER);
+ advisor2 = createAspectJAfterThrowingAdvice(HIGH_PRECEDENCE_ADVISOR_ORDER, EARLY_ADVICE_DECLARATION_ORDER, "someOtherAspect");
+ assertEquals("advisor1 sorted after advisor2", 1, this.comparator.compare(advisor1, advisor2));
+ }
+
+
+ private Advisor createAspectJBeforeAdvice(int advisorOrder, int adviceDeclarationOrder, String aspectName) {
+ AspectJMethodBeforeAdvice advice = new AspectJMethodBeforeAdvice(this.anyOldMethod, this.anyOldPointcut, null);
+ return createAspectJAdvice(advisorOrder, adviceDeclarationOrder, aspectName, advice);
+ }
+
+ private Advisor createAspectJAroundAdvice(int advisorOrder, int adviceDeclarationOrder, String aspectName) {
+ AspectJAroundAdvice advice = new AspectJAroundAdvice(this.anyOldMethod, this.anyOldPointcut, null);
+ return createAspectJAdvice(advisorOrder, adviceDeclarationOrder, aspectName, advice);
+ }
+
+ private Advisor createAspectJAfterAdvice(int advisorOrder, int adviceDeclarationOrder, String aspectName) {
+ AspectJAfterAdvice advice = new AspectJAfterAdvice(this.anyOldMethod, this.anyOldPointcut, null);
+ return createAspectJAdvice(advisorOrder, adviceDeclarationOrder, aspectName, advice);
+ }
+
+ private Advisor createAspectJAfterReturningAdvice(int advisorOrder, int adviceDeclarationOrder, String aspectName) {
+ AspectJAfterReturningAdvice advice = new AspectJAfterReturningAdvice(this.anyOldMethod, this.anyOldPointcut, null);
+ return createAspectJAdvice(advisorOrder, adviceDeclarationOrder, aspectName, advice);
+ }
+
+ private Advisor createAspectJAfterThrowingAdvice(int advisorOrder, int adviceDeclarationOrder, String aspectName) {
+ AspectJAfterThrowingAdvice advice = new AspectJAfterThrowingAdvice(this.anyOldMethod, this.anyOldPointcut, null);
+ return createAspectJAdvice(advisorOrder, adviceDeclarationOrder, aspectName, advice);
+ }
+
+ private Advisor createAspectJAdvice(int advisorOrder, int adviceDeclarationOrder, String aspectName, AbstractAspectJAdvice advice) {
+ advice.setDeclarationOrder(adviceDeclarationOrder);
+ advice.setAspectName(aspectName);
+ AspectJPointcutAdvisor advisor = new AspectJPointcutAdvisor(advice);
+ advisor.setOrder(advisorOrder);
+ return advisor;
+ }
+
+ private Advisor createSpringAOPAfterAdvice(int order) {
+ AfterReturningAdvice advice = new AfterReturningAdvice() {
+ public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
+ }
+ };
+ DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(this.anyOldPointcut, advice);
+ advisor.setOrder(order);
+ return advisor;
+ }
+
+ private Advisor createSpringAOPBeforeAdvice(int order) {
+ BeforeAdvice advice = new BeforeAdvice() {
+ };
+ DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(this.anyOldPointcut, advice);
+ advisor.setOrder(order);
+ return advisor;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/autoproxy/aspect-implementing-interface-tests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/autoproxy/aspect-implementing-interface-tests.xml
new file mode 100644
index 00000000000..dffe959a329
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/autoproxy/aspect-implementing-interface-tests.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/bean-name-pointcut-tests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/bean-name-pointcut-tests.xml
new file mode 100644
index 00000000000..66ccb584951
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/bean-name-pointcut-tests.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/before-advice-tests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/before-advice-tests.xml
new file mode 100644
index 00000000000..d12031f34eb
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/before-advice-tests.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/declare-parents-delegate-ref-tests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/declare-parents-delegate-ref-tests.xml
new file mode 100644
index 00000000000..0c6ee0117b9
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/declare-parents-delegate-ref-tests.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/declare-parents-tests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/declare-parents-tests.xml
new file mode 100644
index 00000000000..f8b682c84f7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/declare-parents-tests.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/implicit-jp-argument-matching-tests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/implicit-jp-argument-matching-tests.xml
new file mode 100644
index 00000000000..1c10ec952fe
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/implicit-jp-argument-matching-tests.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/overloaded-advice-tests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/overloaded-advice-tests.xml
new file mode 100644
index 00000000000..57f3f9dd4d7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/overloaded-advice-tests.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/proceedTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/proceedTests.xml
new file mode 100644
index 00000000000..2b4ca898e2f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/proceedTests.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/subtype-sensitive-matching.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/subtype-sensitive-matching.xml
new file mode 100644
index 00000000000..6fb76c1b525
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/subtype-sensitive-matching.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/targetPointcutSelectionTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/targetPointcutSelectionTests.xml
new file mode 100644
index 00000000000..1e57557518f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/targetPointcutSelectionTests.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/this-and-target-selectionOnly-pointcuts-tests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/this-and-target-selectionOnly-pointcuts-tests.xml
new file mode 100644
index 00000000000..acf51f5ccd8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/this-and-target-selectionOnly-pointcuts-tests.xml
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/topsy-turvy-aspect.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/topsy-turvy-aspect.xml
new file mode 100644
index 00000000000..f0d90523d9e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/aspectj/topsy-turvy-aspect.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceAdviceTypeTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceAdviceTypeTests.java
new file mode 100644
index 00000000000..a62a6dec0e4
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceAdviceTypeTests.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.config;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.BeanDefinitionStoreException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.xml.sax.SAXParseException;
+
+/**
+ * @author Adrian Colyer
+ */
+public class AopNamespaceAdviceTypeTests extends TestCase {
+
+ private ApplicationContext context;
+
+ protected String getOKConfigLocation() {
+ return "org/springframework/aop/config/aopNamespaceHandlerAdviceTypeOKTests.xml";
+ }
+
+ protected String getErrorConfigLocation() {
+ return "org/springframework/aop/config/aopNamespaceHandlerAdviceTypeErrorTests.xml";
+ }
+
+ public void testParsingOfAdviceTypes() {
+ this.context = new ClassPathXmlApplicationContext(getOKConfigLocation());
+ }
+
+ public void testParsingOfAdviceTypesWithError() {
+ try {
+ this.context = new ClassPathXmlApplicationContext(getErrorConfigLocation());
+ fail("Expected BeanDefinitionStoreException");
+ }
+ catch (BeanDefinitionStoreException ex) {
+ assertTrue(ex.contains(SAXParseException.class));
+ }
+ }
+
+ protected ITestBean getTestBean() {
+ return (ITestBean) this.context.getBean("testBean");
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerArgNamesTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerArgNamesTests.java
new file mode 100644
index 00000000000..6f58ae39319
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerArgNamesTests.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.config;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * @author Adrian Colyer
+ */
+public class AopNamespaceHandlerArgNamesTests extends TestCase {
+
+ private ApplicationContext context;
+
+ protected String getOKConfigLocation() {
+ return "org/springframework/aop/config/aopNamespaceHandlerArgNamesOKTests.xml";
+ }
+
+ protected String getErrorConfigLocation() {
+ return "org/springframework/aop/config/aopNamespaceHandlerArgNamesErrorTests.xml";
+ }
+
+ public void testArgNamesOK() {
+ this.context = new ClassPathXmlApplicationContext(getOKConfigLocation());
+ }
+
+ public void testArgNamesError() {
+ try {
+ this.context = new ClassPathXmlApplicationContext(getErrorConfigLocation());
+ fail("Expected BeanCreationException");
+ }
+ catch (BeanCreationException ex) {
+ assertTrue(ex.contains(IllegalArgumentException.class));
+ }
+ }
+
+ protected ITestBean getTestBean() {
+ return (ITestBean) this.context.getBean("testBean");
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerEventTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerEventTests.java
new file mode 100644
index 00000000000..7e49b8e845f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerEventTests.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.config;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.BeanReference;
+import org.springframework.beans.factory.parsing.BeanComponentDefinition;
+import org.springframework.beans.factory.parsing.CollectingReaderEventListener;
+import org.springframework.beans.factory.parsing.ComponentDefinition;
+import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class AopNamespaceHandlerEventTests extends TestCase {
+
+ private CollectingReaderEventListener eventListener = new CollectingReaderEventListener();
+
+ private XmlBeanDefinitionReader reader;
+
+ private DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
+
+
+ protected void setUp() throws Exception {
+ this.reader = new XmlBeanDefinitionReader(this.beanFactory);
+ this.reader.setEventListener(this.eventListener);
+ }
+
+ public void testPointcutEvents() throws Exception {
+ loadBeansFrom("aopNamespaceHandlerPointcutEventTests.xml");
+ ComponentDefinition[] componentDefinitions = this.eventListener.getComponentDefinitions();
+ assertEquals("Incorrect number of events fired", 1, componentDefinitions.length);
+ assertTrue("No holder with nested components", componentDefinitions[0] instanceof CompositeComponentDefinition);
+
+ CompositeComponentDefinition compositeDef = (CompositeComponentDefinition) componentDefinitions[0];
+ assertEquals("aop:config", compositeDef.getName());
+
+ ComponentDefinition[] nestedComponentDefs = compositeDef.getNestedComponents();
+ assertEquals("Incorrect number of inner components", 2, nestedComponentDefs.length);
+ PointcutComponentDefinition pcd = null;
+ for (int i = 0; i < nestedComponentDefs.length; i++) {
+ ComponentDefinition componentDefinition = nestedComponentDefs[i];
+ if (componentDefinition instanceof PointcutComponentDefinition) {
+ pcd = (PointcutComponentDefinition) componentDefinition;
+ break;
+ }
+ }
+ assertNotNull("PointcutComponentDefinition not found", pcd);
+ assertEquals("Incorrect number of BeanDefinitions", 1, pcd.getBeanDefinitions().length);
+ }
+
+ public void testAdvisorEventsWithPointcutRef() throws Exception {
+ loadBeansFrom("aopNamespaceHandlerAdvisorWithPointcutRefEventTests.xml");
+ ComponentDefinition[] componentDefinitions = this.eventListener.getComponentDefinitions();
+ assertEquals("Incorrect number of events fired", 2, componentDefinitions.length);
+
+ assertTrue("No holder with nested components", componentDefinitions[0] instanceof CompositeComponentDefinition);
+ CompositeComponentDefinition compositeDef = (CompositeComponentDefinition) componentDefinitions[0];
+ assertEquals("aop:config", compositeDef.getName());
+
+ ComponentDefinition[] nestedComponentDefs = compositeDef.getNestedComponents();
+ assertEquals("Incorrect number of inner components", 3, nestedComponentDefs.length);
+ AdvisorComponentDefinition acd = null;
+ for (int i = 0; i < nestedComponentDefs.length; i++) {
+ ComponentDefinition componentDefinition = nestedComponentDefs[i];
+ if (componentDefinition instanceof AdvisorComponentDefinition) {
+ acd = (AdvisorComponentDefinition) componentDefinition;
+ break;
+ }
+ }
+ assertNotNull("AdvisorComponentDefinition not found", acd);
+ assertEquals(1, acd.getBeanDefinitions().length);
+ assertEquals(2, acd.getBeanReferences().length);
+
+ assertTrue("No advice bean found", componentDefinitions[1] instanceof BeanComponentDefinition);
+ BeanComponentDefinition adviceDef = (BeanComponentDefinition) componentDefinitions[1];
+ assertEquals("countingAdvice", adviceDef.getBeanName());
+ }
+
+ public void testAdvisorEventsWithDirectPointcut() throws Exception {
+ loadBeansFrom("aopNamespaceHandlerAdvisorWithDirectPointcutEventTests.xml");
+ ComponentDefinition[] componentDefinitions = this.eventListener.getComponentDefinitions();
+ assertEquals("Incorrect number of events fired", 2, componentDefinitions.length);
+
+ assertTrue("No holder with nested components", componentDefinitions[0] instanceof CompositeComponentDefinition);
+ CompositeComponentDefinition compositeDef = (CompositeComponentDefinition) componentDefinitions[0];
+ assertEquals("aop:config", compositeDef.getName());
+
+ ComponentDefinition[] nestedComponentDefs = compositeDef.getNestedComponents();
+ assertEquals("Incorrect number of inner components", 2, nestedComponentDefs.length);
+ AdvisorComponentDefinition acd = null;
+ for (int i = 0; i < nestedComponentDefs.length; i++) {
+ ComponentDefinition componentDefinition = nestedComponentDefs[i];
+ if (componentDefinition instanceof AdvisorComponentDefinition) {
+ acd = (AdvisorComponentDefinition) componentDefinition;
+ break;
+ }
+ }
+ assertNotNull("AdvisorComponentDefinition not found", acd);
+ assertEquals(2, acd.getBeanDefinitions().length);
+ assertEquals(1, acd.getBeanReferences().length);
+
+ assertTrue("No advice bean found", componentDefinitions[1] instanceof BeanComponentDefinition);
+ BeanComponentDefinition adviceDef = (BeanComponentDefinition) componentDefinitions[1];
+ assertEquals("countingAdvice", adviceDef.getBeanName());
+ }
+
+ public void testAspectEvent() throws Exception {
+ loadBeansFrom("aopNamespaceHandlerAspectEventTests.xml");
+ ComponentDefinition[] componentDefinitions = this.eventListener.getComponentDefinitions();
+ assertEquals("Incorrect number of events fired", 5, componentDefinitions.length);
+
+ assertTrue("No holder with nested components", componentDefinitions[0] instanceof CompositeComponentDefinition);
+ CompositeComponentDefinition compositeDef = (CompositeComponentDefinition) componentDefinitions[0];
+ assertEquals("aop:config", compositeDef.getName());
+
+ ComponentDefinition[] nestedComponentDefs = compositeDef.getNestedComponents();
+ assertEquals("Incorrect number of inner components", 2, nestedComponentDefs.length);
+ AspectComponentDefinition acd = null;
+ for (int i = 0; i < nestedComponentDefs.length; i++) {
+ ComponentDefinition componentDefinition = nestedComponentDefs[i];
+ if (componentDefinition instanceof AspectComponentDefinition) {
+ acd = (AspectComponentDefinition) componentDefinition;
+ break;
+ }
+ }
+
+ assertNotNull("AspectComponentDefinition not found", acd);
+ BeanDefinition[] beanDefinitions = acd.getBeanDefinitions();
+ assertEquals(5, beanDefinitions.length);
+ BeanReference[] beanReferences = acd.getBeanReferences();
+ assertEquals(6, beanReferences.length);
+
+ Set expectedReferences = new HashSet();
+ expectedReferences.add("pc");
+ expectedReferences.add("countingAdvice");
+ for (int i = 0; i < beanReferences.length; i++) {
+ BeanReference beanReference = beanReferences[i];
+ expectedReferences.remove(beanReference.getBeanName());
+ }
+ assertEquals("Incorrect references found", 0, expectedReferences.size());
+
+ for (int i = 1; i < componentDefinitions.length; i++) {
+ assertTrue(componentDefinitions[i] instanceof BeanComponentDefinition);
+ }
+
+ ComponentDefinition[] nestedComponentDefs2 = acd.getNestedComponents();
+ assertEquals("Inner PointcutComponentDefinition not found", 1, nestedComponentDefs2.length);
+ assertTrue(nestedComponentDefs2[0] instanceof PointcutComponentDefinition);
+ PointcutComponentDefinition pcd = (PointcutComponentDefinition) nestedComponentDefs2[0];
+ assertEquals("Incorrect number of BeanDefinitions", 1, pcd.getBeanDefinitions().length);
+ }
+
+ private void loadBeansFrom(String path) {
+ this.reader.loadBeanDefinitions(new ClassPathResource(path, getClass()));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerPointcutErrorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerPointcutErrorTests.java
new file mode 100644
index 00000000000..c5dfcab6b07
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerPointcutErrorTests.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.config;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.factory.BeanDefinitionStoreException;
+import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Mark Fisher
+ */
+public class AopNamespaceHandlerPointcutErrorTests extends TestCase {
+
+ public void testDuplicatePointcutConfig() {
+ try {
+ new XmlBeanFactory(new ClassPathResource(
+ "org/springframework/aop/config/aopNamespaceHandlerPointcutDuplicationTests.xml"));
+ fail("parsing should have caused a BeanDefinitionStoreException");
+ }
+ catch (BeanDefinitionStoreException ex) {
+ assertTrue(ex.contains(BeanDefinitionParsingException.class));
+ }
+ }
+
+ public void testMissingPointcutConfig() {
+ try {
+ new XmlBeanFactory(new ClassPathResource(
+ "org/springframework/aop/config/aopNamespaceHandlerPointcutMissingTests.xml"));
+ fail("parsing should have caused a BeanDefinitionStoreException");
+ }
+ catch (BeanDefinitionStoreException ex) {
+ assertTrue(ex.contains(BeanDefinitionParsingException.class));
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerProxyTargetClassTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerProxyTargetClassTests.java
new file mode 100644
index 00000000000..73e9f377be5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerProxyTargetClassTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.config;
+
+import org.springframework.aop.support.AopUtils;
+import org.springframework.beans.ITestBean;
+
+/**
+ * @author Rob Harrop
+ */
+public class AopNamespaceHandlerProxyTargetClassTests extends AopNamespaceHandlerTests {
+
+ public void testIsClassProxy() {
+ ITestBean bean = getTestBean();
+ assertTrue("Should be a CGLIB proxy", AopUtils.isCglibProxy(bean));
+ }
+
+ protected String getConfigLocation() {
+ return "org/springframework/aop/config/aopNamespaceHandlerProxyTargetClassTests.xml";
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerReturningTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerReturningTests.java
new file mode 100644
index 00000000000..9852cdfef4e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerReturningTests.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.config;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.factory.BeanDefinitionStoreException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.xml.sax.SAXParseException;
+
+/**
+ * @author Adrian Colyer
+ */
+public class AopNamespaceHandlerReturningTests extends TestCase {
+
+ private ApplicationContext context;
+
+ protected String getOKConfigLocation() {
+ return "org/springframework/aop/config/aopNamespaceHandlerReturningOKTests.xml";
+ }
+
+ protected String getErrorConfigLocation() {
+ return "org/springframework/aop/config/aopNamespaceHandlerReturningErrorTests.xml";
+ }
+
+ public void testReturningOnReturningAdvice() {
+ this.context = new ClassPathXmlApplicationContext(getOKConfigLocation());
+ }
+
+ public void testParseReturningOnOtherAdviceType() {
+ try {
+ this.context = new ClassPathXmlApplicationContext(getErrorConfigLocation());
+ fail("Expected BeanDefinitionStoreException");
+ }
+ catch (BeanDefinitionStoreException ex) {
+ assertTrue(ex.contains(SAXParseException.class));
+ }
+ }
+
+ protected ITestBean getTestBean() {
+ return (ITestBean) this.context.getBean("testBean");
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerScopeTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerScopeTests.java
new file mode 100644
index 00000000000..e8bce909650
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerScopeTests.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.config;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.framework.Advised;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpSession;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import org.springframework.web.context.support.XmlWebApplicationContext;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class AopNamespaceHandlerScopeTests extends TestCase {
+
+ private ApplicationContext context;
+
+ public void setUp() {
+ XmlWebApplicationContext wac = new XmlWebApplicationContext();
+ wac.setConfigLocations(new String[] {"classpath:org/springframework/aop/config/aopNamespaceHandlerScopeTests.xml"});
+ wac.refresh();
+ this.context = wac;
+ }
+
+ public void testRequestScoping() throws Exception {
+ MockHttpServletRequest oldRequest = new MockHttpServletRequest();
+ MockHttpServletRequest newRequest = new MockHttpServletRequest();
+
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(oldRequest));
+
+ ITestBean scoped = (ITestBean) this.context.getBean("requestScoped");
+ assertTrue("Should be AOP proxy", AopUtils.isAopProxy(scoped));
+ assertTrue("Should be target class proxy", scoped instanceof TestBean);
+
+ ITestBean testBean = (ITestBean) this.context.getBean("testBean");
+ assertTrue("Should be AOP proxy", AopUtils.isAopProxy(testBean));
+ assertFalse("Regular bean should be JDK proxy", testBean instanceof TestBean);
+
+ String rob = "Rob Harrop";
+ String bram = "Bram Smeets";
+
+ assertEquals(rob, scoped.getName());
+ scoped.setName(bram);
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(newRequest));
+ assertEquals(rob, scoped.getName());
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(oldRequest));
+ assertEquals(bram, scoped.getName());
+
+ assertTrue("Should have advisors", ((Advised) scoped).getAdvisors().length > 0);
+ }
+
+ public void testSessionScoping() throws Exception {
+ MockHttpSession oldSession = new MockHttpSession();
+ MockHttpSession newSession = new MockHttpSession();
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setSession(oldSession);
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
+
+ ITestBean scoped = (ITestBean) this.context.getBean("sessionScoped");
+ assertTrue("Should be AOP proxy", AopUtils.isAopProxy(scoped));
+ assertFalse("Should not be target class proxy", scoped instanceof TestBean);
+
+ ITestBean scopedAlias = (ITestBean) this.context.getBean("sessionScopedAlias");
+ assertSame(scoped, scopedAlias);
+
+ ITestBean testBean = (ITestBean) this.context.getBean("testBean");
+ assertTrue("Should be AOP proxy", AopUtils.isAopProxy(testBean));
+ assertFalse("Regular bean should be JDK proxy", testBean instanceof TestBean);
+
+ String rob = "Rob Harrop";
+ String bram = "Bram Smeets";
+
+ assertEquals(rob, scoped.getName());
+ scoped.setName(bram);
+ request.setSession(newSession);
+ assertEquals(rob, scoped.getName());
+ request.setSession(oldSession);
+ assertEquals(bram, scoped.getName());
+
+ assertTrue("Should have advisors", ((Advised) scoped).getAdvisors().length > 0);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerTests.java
new file mode 100644
index 00000000000..70e57beed78
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerTests.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.config;
+
+import junit.framework.TestCase;
+import org.springframework.aop.Advisor;
+import org.springframework.aop.framework.Advised;
+import org.springframework.aop.framework.CountingBeforeAdvice;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.beans.ITestBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * @author Rob Harrop
+ */
+public class AopNamespaceHandlerTests extends TestCase {
+
+ private ApplicationContext context;
+
+ public void setUp() {
+ this.context = new ClassPathXmlApplicationContext(getConfigLocation());
+ }
+
+ protected String getConfigLocation() {
+ return "org/springframework/aop/config/aopNamespaceHandlerTests.xml";
+ }
+
+ public void testIsProxy() throws Exception {
+ ITestBean bean = getTestBean();
+
+ assertTrue("Bean is not a proxy", AopUtils.isAopProxy(bean));
+
+ // check the advice details
+ Advised advised = (Advised) bean;
+ Advisor[] advisors = advised.getAdvisors();
+
+ assertTrue("Advisors should not be empty", advisors.length > 0);
+ }
+
+ public void testAdviceInvokedCorrectly() throws Exception {
+ CountingBeforeAdvice getAgeCounter = (CountingBeforeAdvice) this.context.getBean("getAgeCounter");
+ CountingBeforeAdvice getNameCounter = (CountingBeforeAdvice) this.context.getBean("getNameCounter");
+
+ ITestBean bean = getTestBean();
+
+ assertEquals("Incorrect initial getAge count", 0, getAgeCounter.getCalls("getAge"));
+ assertEquals("Incorrect initial getName count", 0, getNameCounter.getCalls("getName"));
+
+ bean.getAge();
+
+ assertEquals("Incorrect getAge count on getAge counter", 1, getAgeCounter.getCalls("getAge"));
+ assertEquals("Incorrect getAge count on getName counter", 0, getNameCounter.getCalls("getAge"));
+
+ bean.getName();
+
+ assertEquals("Incorrect getName count on getName counter", 1, getNameCounter.getCalls("getName"));
+ assertEquals("Incorrect getName count on getAge counter", 0, getAgeCounter.getCalls("getName"));
+ }
+
+ public void testAspectApplied() throws Exception {
+ ITestBean testBean = getTestBean();
+
+ CountingAspectJAdvice advice = (CountingAspectJAdvice) this.context.getBean("countingAdvice");
+
+ assertEquals("Incorrect before count", 0, advice.getBeforeCount());
+ assertEquals("Incorrect after count", 0, advice.getAfterCount());
+
+ testBean.setName("Sally");
+
+ assertEquals("Incorrect before count", 1, advice.getBeforeCount());
+ assertEquals("Incorrect after count", 1, advice.getAfterCount());
+
+ testBean.getName();
+
+ assertEquals("Incorrect before count", 1, advice.getBeforeCount());
+ assertEquals("Incorrect after count", 1, advice.getAfterCount());
+ }
+
+ protected ITestBean getTestBean() {
+ return (ITestBean) this.context.getBean("testBean");
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerThrowingTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerThrowingTests.java
new file mode 100644
index 00000000000..597e069ee90
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/AopNamespaceHandlerThrowingTests.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.config;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.factory.BeanDefinitionStoreException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.xml.sax.SAXParseException;
+
+/**
+ * @author Adrian Colyer
+ */
+public class AopNamespaceHandlerThrowingTests extends TestCase {
+
+ private ApplicationContext context;
+
+ protected String getOKConfigLocation() {
+ return "org/springframework/aop/config/aopNamespaceHandlerThrowingOKTests.xml";
+ }
+
+ protected String getErrorConfigLocation() {
+ return "org/springframework/aop/config/aopNamespaceHandlerThrowingErrorTests.xml";
+ }
+
+ public void testThrowingOnThrowingAdvice() {
+ this.context = new ClassPathXmlApplicationContext(getOKConfigLocation());
+ }
+
+ public void testParseThrowingOnOtherAdviceType() {
+ try {
+ this.context = new ClassPathXmlApplicationContext(getErrorConfigLocation());
+ fail("Expected BeanDefinitionStoreException");
+ }
+ catch (BeanDefinitionStoreException ex) {
+ assertTrue(ex.contains(SAXParseException.class));
+ }
+ }
+
+ protected ITestBean getTestBean() {
+ return (ITestBean) this.context.getBean("testBean");
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/CountingAspectJAdvice.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/CountingAspectJAdvice.java
new file mode 100644
index 00000000000..6251cf40948
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/CountingAspectJAdvice.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.config;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.springframework.beans.ITestBean;
+
+/**
+ * @author Rob Harrop
+ */
+public class CountingAspectJAdvice {
+
+ private int beforeCount;
+
+ private int afterCount;
+
+ private int aroundCount;
+
+ public void myBeforeAdvice() throws Throwable {
+ this.beforeCount++;
+ }
+
+ public void myAfterAdvice() throws Throwable {
+ this.afterCount++;
+ }
+
+ public void myAroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
+ this.aroundCount++;
+ pjp.proceed();
+ }
+
+ public void myAfterReturningAdvice(int age) {
+ this.afterCount++;
+ }
+
+ public void myAfterThrowingAdvice(RuntimeException ex) {
+ this.afterCount++;
+ }
+
+ public void mySetAgeAdvice(int newAge, ITestBean bean) {
+ // no-op
+ }
+
+ public int getBeforeCount() {
+ return this.beforeCount;
+ }
+
+ public int getAfterCount() {
+ return this.afterCount;
+ }
+
+ public int getAroundCount() {
+ return this.aroundCount;
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/MethodLocatingFactoryBeanTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/MethodLocatingFactoryBeanTests.java
new file mode 100644
index 00000000000..55699b56fae
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/MethodLocatingFactoryBeanTests.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.config;
+
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.mock.easymock.AbstractScalarMockTemplate;
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Rick Evans
+ */
+public final class MethodLocatingFactoryBeanTests extends TestCase {
+
+ private static final String BEAN_NAME = "string";
+
+
+ public void testIsSingleton() throws Exception {
+ MethodLocatingFactoryBean factory = new MethodLocatingFactoryBean();
+ assertTrue(factory.isSingleton());
+ }
+
+ public void testGetObjectType() throws Exception {
+ MethodLocatingFactoryBean factory = new MethodLocatingFactoryBean();
+ assertEquals(Method.class, factory.getObjectType());
+ }
+
+ public void testWithNullTargetBeanName() throws Exception {
+ new BeanFactoryScalarMockTemplate() {
+ public void doTestInternal(final BeanFactory beanFactory) throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ MethodLocatingFactoryBean factory = new MethodLocatingFactoryBean();
+ factory.setMethodName("toString()");
+ factory.setBeanFactory(beanFactory);
+ }
+ }.runTest();
+ }
+ }.test();
+ }
+
+ public void testWithEmptyTargetBeanName() throws Exception {
+ new BeanFactoryScalarMockTemplate() {
+ public void doTestInternal(final BeanFactory beanFactory) throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ MethodLocatingFactoryBean factory = new MethodLocatingFactoryBean();
+ factory.setTargetBeanName("");
+ factory.setMethodName("toString()");
+ factory.setBeanFactory(beanFactory);
+ }
+ }.runTest();
+ }
+ }.test();
+ }
+
+ public void testWithNullTargetMethodName() throws Exception {
+ new BeanFactoryScalarMockTemplate() {
+ public void doTestInternal(final BeanFactory beanFactory) throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ MethodLocatingFactoryBean factory = new MethodLocatingFactoryBean();
+ factory.setTargetBeanName(BEAN_NAME);
+ factory.setBeanFactory(beanFactory);
+ }
+ }.runTest();
+ }
+ }.test();
+ }
+
+ public void testWithEmptyTargetMethodName() throws Exception {
+ new BeanFactoryScalarMockTemplate() {
+ public void doTestInternal(final BeanFactory beanFactory) throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ MethodLocatingFactoryBean factory = new MethodLocatingFactoryBean();
+ factory.setTargetBeanName(BEAN_NAME);
+ factory.setMethodName("");
+ factory.setBeanFactory(beanFactory);
+ }
+ }.runTest();
+ }
+ }.test();
+ }
+
+ public void testWhenTargetBeanClassCannotBeResolved() throws Exception {
+ new BeanFactoryScalarMockTemplate() {
+ protected void setupBeanFactoryExpectations(MockControl mockControl, BeanFactory beanFactory) throws Exception {
+ beanFactory.getType(BEAN_NAME);
+ mockControl.setReturnValue(null);
+ }
+ protected void doTestInternal(final BeanFactory beanFactory) throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ MethodLocatingFactoryBean factory = new MethodLocatingFactoryBean();
+ factory.setTargetBeanName(BEAN_NAME);
+ factory.setMethodName("toString()");
+ factory.setBeanFactory(beanFactory);
+ }
+ }.runTest();
+ }
+ }.test();
+ }
+
+ public void testSunnyDayPath() throws Exception {
+ new BeanFactoryScalarMockTemplate() {
+ protected void setupBeanFactoryExpectations(MockControl mockControl, BeanFactory beanFactory) throws Exception {
+ beanFactory.getType(BEAN_NAME);
+ mockControl.setReturnValue(String.class);
+ }
+ protected void doTestInternal(final BeanFactory beanFactory) throws Exception {
+ MethodLocatingFactoryBean factory = new MethodLocatingFactoryBean();
+ factory.setTargetBeanName(BEAN_NAME);
+ factory.setMethodName("toString()");
+ factory.setBeanFactory(beanFactory);
+ Object result = factory.getObject();
+ assertNotNull(result);
+ assertTrue(result instanceof Method);
+ Method method = (Method) result;
+ assertEquals("Bingo", method.invoke("Bingo", new Object[]{}));
+ }
+ }.test();
+ }
+
+ public void testWhereMethodCannotBeResolved() throws Exception {
+ new BeanFactoryScalarMockTemplate() {
+ protected void setupBeanFactoryExpectations(MockControl mockControl, BeanFactory beanFactory) throws Exception {
+ beanFactory.getType(BEAN_NAME);
+ mockControl.setReturnValue(String.class);
+ }
+ protected void doTestInternal(final BeanFactory beanFactory) throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ MethodLocatingFactoryBean factory = new MethodLocatingFactoryBean();
+ factory.setTargetBeanName(BEAN_NAME);
+ factory.setMethodName("loadOfOld()");
+ factory.setBeanFactory(beanFactory);
+ }
+ }.runTest();
+ }
+ }.test();
+ }
+
+
+ private static abstract class BeanFactoryScalarMockTemplate extends AbstractScalarMockTemplate {
+
+ public BeanFactoryScalarMockTemplate() {
+ super(BeanFactory.class);
+ }
+
+ public void setupExpectations(MockControl mockControl, Object mockObject) throws Exception {
+ setupBeanFactoryExpectations(mockControl, (BeanFactory) mockObject);
+ }
+
+ public void doTest(Object mockObject) throws Exception {
+ doTestInternal((BeanFactory) mockObject);
+ }
+
+ protected void setupBeanFactoryExpectations(MockControl mockControl, BeanFactory beanFactory) throws Exception {
+ }
+
+ protected abstract void doTestInternal(final BeanFactory beanFactory) throws Exception;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/PrototypeProxyTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/PrototypeProxyTests.java
new file mode 100644
index 00000000000..1c64d884c7c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/PrototypeProxyTests.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.config;
+
+import junit.framework.TestCase;
+
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class PrototypeProxyTests extends TestCase {
+
+ public void testInjectionBeforeWrappingCheckDoesNotKickInForPrototypeProxy() {
+ new ClassPathXmlApplicationContext("prototypeProxy.xml", getClass());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/TopLevelAopTagTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/TopLevelAopTagTests.java
new file mode 100644
index 00000000000..f9d6f66e565
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/TopLevelAopTagTests.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.config;
+
+import junit.framework.TestCase;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * Tests that the <aop:config/> element can be used as a top level element.
+ *
+ * @author Rob Harrop
+ */
+public final class TopLevelAopTagTests extends TestCase {
+
+ public void testParse() throws Exception {
+ DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
+ reader.loadBeanDefinitions(new ClassPathResource("topLevelAop.xml", getClass()));
+
+ assertTrue(beanFactory.containsBeanDefinition("testPointcut"));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerAdviceTypeErrorTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerAdviceTypeErrorTests.xml
new file mode 100644
index 00000000000..efdd2acb7c2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerAdviceTypeErrorTests.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerAdviceTypeOKTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerAdviceTypeOKTests.xml
new file mode 100644
index 00000000000..157ffe66781
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerAdviceTypeOKTests.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerAdvisorWithDirectPointcutEventTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerAdvisorWithDirectPointcutEventTests.xml
new file mode 100644
index 00000000000..42291802335
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerAdvisorWithDirectPointcutEventTests.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerAdvisorWithPointcutRefEventTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerAdvisorWithPointcutRefEventTests.xml
new file mode 100644
index 00000000000..23e4a88b3fc
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerAdvisorWithPointcutRefEventTests.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerArgNamesErrorTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerArgNamesErrorTests.xml
new file mode 100644
index 00000000000..c156060d093
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerArgNamesErrorTests.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerArgNamesOKTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerArgNamesOKTests.xml
new file mode 100644
index 00000000000..1cafd6663a1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerArgNamesOKTests.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerAspectEventTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerAspectEventTests.xml
new file mode 100644
index 00000000000..157ffe66781
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerAspectEventTests.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerPointcutDuplicationTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerPointcutDuplicationTests.xml
new file mode 100644
index 00000000000..e5c02022290
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerPointcutDuplicationTests.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerPointcutEventTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerPointcutEventTests.xml
new file mode 100644
index 00000000000..8350030c171
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerPointcutEventTests.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerPointcutMissingTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerPointcutMissingTests.xml
new file mode 100644
index 00000000000..712c5c783ba
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerPointcutMissingTests.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerProxyTargetClassTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerProxyTargetClassTests.xml
new file mode 100644
index 00000000000..4d0f93b4e70
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerProxyTargetClassTests.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerReturningErrorTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerReturningErrorTests.xml
new file mode 100644
index 00000000000..26da583dd3d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerReturningErrorTests.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerReturningOKTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerReturningOKTests.xml
new file mode 100644
index 00000000000..17f64373dcc
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerReturningOKTests.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerScopeTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerScopeTests.xml
new file mode 100644
index 00000000000..d57f82193cb
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerScopeTests.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerTests.xml
new file mode 100644
index 00000000000..1ac7a3c38be
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerTests.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerThrowingErrorTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerThrowingErrorTests.xml
new file mode 100644
index 00000000000..1334e21719b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerThrowingErrorTests.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerThrowingOKTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerThrowingOKTests.xml
new file mode 100644
index 00000000000..86d7624c0a6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/aopNamespaceHandlerThrowingOKTests.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/prototypeProxy.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/prototypeProxy.xml
new file mode 100644
index 00000000000..a46f0bec3b2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/prototypeProxy.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/config/topLevelAop.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/topLevelAop.xml
new file mode 100644
index 00000000000..6c9e44b560f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/config/topLevelAop.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/AbstractAopProxyTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/AbstractAopProxyTests.java
new file mode 100644
index 00000000000..9ce0ed576b1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/AbstractAopProxyTests.java
@@ -0,0 +1,1838 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+import javax.transaction.TransactionRequiredException;
+
+import junit.framework.TestCase;
+import org.aopalliance.aop.Advice;
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+import org.springframework.aop.Advisor;
+import org.springframework.aop.AfterReturningAdvice;
+import org.springframework.aop.DynamicIntroductionAdvice;
+import org.springframework.aop.MethodBeforeAdvice;
+import org.springframework.aop.TargetSource;
+import org.springframework.aop.framework.adapter.ThrowsAdviceInterceptorTests;
+import org.springframework.aop.interceptor.DebugInterceptor;
+import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
+import org.springframework.aop.interceptor.NopInterceptor;
+import org.springframework.aop.interceptor.SerializableNopInterceptor;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.aop.support.DefaultIntroductionAdvisor;
+import org.springframework.aop.support.DefaultPointcutAdvisor;
+import org.springframework.aop.support.DelegatingIntroductionInterceptor;
+import org.springframework.aop.support.DynamicMethodMatcherPointcut;
+import org.springframework.aop.support.NameMatchMethodPointcut;
+import org.springframework.aop.support.Pointcuts;
+import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
+import org.springframework.aop.target.HotSwappableTargetSource;
+import org.springframework.aop.target.SingletonTargetSource;
+import org.springframework.beans.IOther;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.Person;
+import org.springframework.beans.SerializablePerson;
+import org.springframework.beans.TestBean;
+import org.springframework.jdbc.CannotGetJdbcConnectionException;
+import org.springframework.util.SerializationTestUtils;
+import org.springframework.util.StopWatch;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @since 13.03.2003
+ */
+public abstract class AbstractAopProxyTests extends TestCase {
+
+ protected final MockTargetSource mockTargetSource = new MockTargetSource();
+
+
+ /**
+ * Make a clean target source available if code wants to use it.
+ * The target must be set. Verification will be automatic in tearDown
+ * to ensure that it was used appropriately by code.
+ */
+ protected void setUp() {
+ mockTargetSource.reset();
+ }
+
+ protected void tearDown() {
+ mockTargetSource.verify();
+ }
+
+
+ /**
+ * Set in CGLIB or JDK mode.
+ */
+ protected abstract Object createProxy(ProxyCreatorSupport as);
+
+ protected abstract AopProxy createAopProxy(AdvisedSupport as);
+
+ /**
+ * Is a target always required?
+ */
+ protected boolean requiresTarget() {
+ return false;
+ }
+
+
+ public void testNoInterceptorsAndNoTarget() {
+ AdvisedSupport pc = new AdvisedSupport(new Class[] {ITestBean.class});
+ // Add no interceptors
+ try {
+ AopProxy aop = createAopProxy(pc);
+ aop.getProxy();
+ fail("Shouldn't allow no interceptors");
+ }
+ catch (AopConfigException ex) {
+ // Ok
+ }
+ }
+
+ /**
+ * Simple test that if we set values we can get them out again.
+ */
+ public void testValuesStick() {
+ int age1 = 33;
+ int age2 = 37;
+ String name = "tony";
+
+ TestBean target1 = new TestBean();
+ target1.setAge(age1);
+ ProxyFactory pf1 = new ProxyFactory(target1);
+ pf1.addAdvisor(new DefaultPointcutAdvisor(new NopInterceptor()));
+ pf1.addAdvisor(new DefaultPointcutAdvisor(new TimestampIntroductionInterceptor()));
+ ITestBean tb = (ITestBean) pf1.getProxy();
+
+ assertEquals(age1, tb.getAge());
+ tb.setAge(age2);
+ assertEquals(age2, tb.getAge());
+ assertNull(tb.getName());
+ tb.setName(name);
+ assertEquals(name, tb.getName());
+ }
+
+ /**
+ * This is primarily a test for the efficiency of our
+ * usage of CGLIB. If we create too many classes with
+ * CGLIB this will be slow or will run out of memory.
+ */
+ public void testManyProxies() {
+ int howMany = 10000;
+ StopWatch sw = new StopWatch();
+ sw.start("Create " + howMany + " proxies");
+ testManyProxies(howMany);
+ sw.stop();
+ System.out.println(sw.getTotalTimeMillis());
+ assertTrue("Proxy creation was too slow", sw.getTotalTimeMillis() < 5000);
+ }
+
+ private void testManyProxies(int howMany) {
+ int age1 = 33;
+ TestBean target1 = new TestBean();
+ target1.setAge(age1);
+ ProxyFactory pf1 = new ProxyFactory(target1);
+ pf1.addAdvice(new NopInterceptor());
+ pf1.addAdvice(new NopInterceptor());
+ ITestBean proxies[] = new ITestBean[howMany];
+ for (int i = 0; i < howMany; i++) {
+ proxies[i] = (ITestBean) createAopProxy(pf1).getProxy();
+ assertEquals(age1, proxies[i].getAge());
+ }
+ }
+
+ public void testSerializationAdviceAndTargetNotSerializable() throws Exception {
+ TestBean tb = new TestBean();
+ assertFalse(SerializationTestUtils.isSerializable(tb));
+
+ ProxyFactory pf = new ProxyFactory(tb);
+
+ pf.addAdvice(new NopInterceptor());
+ ITestBean proxy = (ITestBean) createAopProxy(pf).getProxy();
+
+ assertFalse(SerializationTestUtils.isSerializable(proxy));
+ }
+
+ public void testSerializationAdviceNotSerializable() throws Exception {
+ SerializablePerson sp = new SerializablePerson();
+ assertTrue(SerializationTestUtils.isSerializable(sp));
+
+ ProxyFactory pf = new ProxyFactory(sp);
+
+ // This isn't serializable
+ Advice i = new NopInterceptor();
+ pf.addAdvice(i);
+ assertFalse(SerializationTestUtils.isSerializable(i));
+ Object proxy = createAopProxy(pf).getProxy();
+
+ assertFalse(SerializationTestUtils.isSerializable(proxy));
+ }
+
+ public void testSerializationSerializableTargetAndAdvice() throws Throwable {
+ SerializablePerson personTarget = new SerializablePerson();
+ personTarget.setName("jim");
+ personTarget.setAge(26);
+
+ assertTrue(SerializationTestUtils.isSerializable(personTarget));
+
+ ProxyFactory pf = new ProxyFactory(personTarget);
+
+ CountingThrowsAdvice cta = new CountingThrowsAdvice();
+
+ pf.addAdvice(new SerializableNopInterceptor());
+ // Try various advice types
+ pf.addAdvice(new CountingBeforeAdvice());
+ pf.addAdvice(new CountingAfterReturningAdvice());
+ pf.addAdvice(cta);
+ Person p = (Person) createAopProxy(pf).getProxy();
+
+ p.echo(null);
+ assertEquals(0, cta.getCalls());
+ try {
+ p.echo(new ServletException());
+ }
+ catch (ServletException ex) {
+
+ }
+ assertEquals(1, cta.getCalls());
+
+ // Will throw exception if it fails
+ Person p2 = (Person) SerializationTestUtils.serializeAndDeserialize(p);
+ assertNotSame(p, p2);
+ assertEquals(p.getName(), p2.getName());
+ assertEquals(p.getAge(), p2.getAge());
+ assertTrue("Deserialized object is an AOP proxy", AopUtils.isAopProxy(p2));
+
+ Advised a1 = (Advised) p;
+ Advised a2 = (Advised) p2;
+ // Check we can manipulate state of p2
+ assertEquals(a1.getAdvisors().length, a2.getAdvisors().length);
+
+ // This should work as SerializablePerson is equal
+ assertEquals("Proxies should be equal, even after one was serialized", p, p2);
+ assertEquals("Proxies should be equal, even after one was serialized", p2, p);
+
+ // Check we can add a new advisor to the target
+ NopInterceptor ni = new NopInterceptor();
+ p2.getAge();
+ assertEquals(0, ni.getCount());
+ a2.addAdvice(ni);
+ p2.getAge();
+ assertEquals(1, ni.getCount());
+
+ cta = (CountingThrowsAdvice) a2.getAdvisors()[3].getAdvice();
+ p2.echo(null);
+ assertEquals(1, cta.getCalls());
+ try {
+ p2.echo(new ServletException());
+ }
+ catch (ServletException ex) {
+
+ }
+ assertEquals(2, cta.getCalls());
+
+ }
+
+ /**
+ * Check that the two MethodInvocations necessary are independent and
+ * don't conflict.
+ * Check also proxy exposure.
+ */
+ public void testOneAdvisedObjectCallsAnother() {
+ int age1 = 33;
+ int age2 = 37;
+
+ TestBean target1 = new TestBean();
+ ProxyFactory pf1 = new ProxyFactory(target1);
+ // Permit proxy and invocation checkers to get context from AopContext
+ pf1.setExposeProxy(true);
+ NopInterceptor di1 = new NopInterceptor();
+ pf1.addAdvice(0, di1);
+ pf1.addAdvice(1, new ProxyMatcherInterceptor());
+ pf1.addAdvice(2, new CheckMethodInvocationIsSameInAndOutInterceptor());
+ pf1.addAdvice(1, new CheckMethodInvocationViaThreadLocalIsSameInAndOutInterceptor());
+ // Must be first
+ pf1.addAdvice(0, ExposeInvocationInterceptor.INSTANCE);
+ ITestBean advised1 = (ITestBean) pf1.getProxy();
+ advised1.setAge(age1); // = 1 invocation
+
+ TestBean target2 = new TestBean();
+ ProxyFactory pf2 = new ProxyFactory(target2);
+ pf2.setExposeProxy(true);
+ NopInterceptor di2 = new NopInterceptor();
+ pf2.addAdvice(0, di2);
+ pf2.addAdvice(1, new ProxyMatcherInterceptor());
+ pf2.addAdvice(2, new CheckMethodInvocationIsSameInAndOutInterceptor());
+ pf2.addAdvice(1, new CheckMethodInvocationViaThreadLocalIsSameInAndOutInterceptor());
+ pf2.addAdvice(0, ExposeInvocationInterceptor.INSTANCE);
+ //System.err.println(pf2.toProxyConfigString());
+ ITestBean advised2 = (ITestBean) createProxy(pf2);
+ advised2.setAge(age2);
+ advised1.setSpouse(advised2); // = 2 invocations
+
+ assertEquals("Advised one has correct age", age1, advised1.getAge()); // = 3 invocations
+ assertEquals("Advised two has correct age", age2, advised2.getAge());
+ // Means extra call on advised 2
+ assertEquals("Advised one spouse has correct age", age2, advised1.getSpouse().getAge()); // = 4 invocations on 1 and another one on 2
+
+ assertEquals("one was invoked correct number of times", 4, di1.getCount());
+ // Got hit by call to advised1.getSpouse().getAge()
+ assertEquals("one was invoked correct number of times", 3, di2.getCount());
+ }
+
+
+ public void testReentrance() {
+ int age1 = 33;
+
+ TestBean target1 = new TestBean();
+ ProxyFactory pf1 = new ProxyFactory(target1);
+ NopInterceptor di1 = new NopInterceptor();
+ pf1.addAdvice(0, di1);
+ ITestBean advised1 = (ITestBean) createProxy(pf1);
+ advised1.setAge(age1); // = 1 invocation
+ advised1.setSpouse(advised1); // = 2 invocations
+
+ assertEquals("one was invoked correct number of times", 2, di1.getCount());
+
+ assertEquals("Advised one has correct age", age1, advised1.getAge()); // = 3 invocations
+ assertEquals("one was invoked correct number of times", 3, di1.getCount());
+
+ // = 5 invocations, as reentrant call to spouse is advised also
+ assertEquals("Advised spouse has correct age", age1, advised1.getSpouse().getAge());
+
+ assertEquals("one was invoked correct number of times", 5, di1.getCount());
+ }
+
+ public void testTargetCanGetProxy() {
+ NopInterceptor di = new NopInterceptor();
+ INeedsToSeeProxy target = new TargetChecker();
+ ProxyFactory proxyFactory = new ProxyFactory(target);
+ proxyFactory.setExposeProxy(true);
+ assertTrue(proxyFactory.isExposeProxy());
+
+ proxyFactory.addAdvice(0, di);
+ INeedsToSeeProxy proxied = (INeedsToSeeProxy) createProxy(proxyFactory);
+ assertEquals(0, di.getCount());
+ assertEquals(0, target.getCount());
+ proxied.incrementViaThis();
+ assertEquals("Increment happened", 1, target.getCount());
+
+ assertEquals("Only one invocation via AOP as use of this wasn't proxied", 1, di.getCount());
+ // 1 invocation
+ assertEquals("Increment happened", 1, proxied.getCount());
+ proxied.incrementViaProxy(); // 2 invoocations
+ assertEquals("Increment happened", 2, target.getCount());
+ assertEquals("3 more invocations via AOP as the first call was reentrant through the proxy", 4, di.getCount());
+ }
+
+
+ public void testTargetCantGetProxyByDefault() {
+ NeedsToSeeProxy et = new NeedsToSeeProxy();
+ ProxyFactory pf1 = new ProxyFactory(et);
+ assertFalse(pf1.isExposeProxy());
+ INeedsToSeeProxy proxied = (INeedsToSeeProxy) createProxy(pf1);
+ try {
+ proxied.incrementViaProxy();
+ fail("Should have failed to get proxy as exposeProxy wasn't set to true");
+ }
+ catch (IllegalStateException ex) {
+ // Ok
+ }
+ }
+
+ public void testContext() throws Throwable {
+ testContext(true);
+ }
+
+ public void testNoContext() throws Throwable {
+ testContext(false);
+ }
+
+ /**
+ * @param context if true, want context
+ */
+ private void testContext(final boolean context) throws Throwable {
+ final String s = "foo";
+ // Test return value
+ MethodInterceptor mi = new MethodInterceptor() {
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ if (!context) {
+ assertNoInvocationContext();
+ } else {
+ assertTrue("have context", ExposeInvocationInterceptor.currentInvocation() != null);
+ }
+ return s;
+ }
+ };
+ AdvisedSupport pc = new AdvisedSupport(new Class[] {ITestBean.class});
+ if (context) {
+ pc.addAdvice(ExposeInvocationInterceptor.INSTANCE);
+ }
+ pc.addAdvice(mi);
+ // Keep CGLIB happy
+ if (requiresTarget()) {
+ pc.setTarget(new TestBean());
+ }
+ AopProxy aop = createAopProxy(pc);
+
+ assertNoInvocationContext();
+ ITestBean tb = (ITestBean) aop.getProxy();
+ assertNoInvocationContext();
+ assertTrue("correct return value", tb.getName() == s);
+ }
+
+ /**
+ * Test that the proxy returns itself when the
+ * target returns this
+ */
+ public void testTargetReturnsThis() throws Throwable {
+ // Test return value
+ TestBean raw = new OwnSpouse();
+
+ ProxyCreatorSupport pc = new ProxyCreatorSupport();
+ pc.setInterfaces(new Class[] {ITestBean.class});
+ pc.setTarget(raw);
+
+ ITestBean tb = (ITestBean) createProxy(pc);
+ assertTrue("this return is wrapped in proxy", tb.getSpouse() == tb);
+ }
+
+ public void testDeclaredException() throws Throwable {
+ final Exception expectedException = new Exception();
+ // Test return value
+ MethodInterceptor mi = new MethodInterceptor() {
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ throw expectedException;
+ }
+ };
+ AdvisedSupport pc = new AdvisedSupport(new Class[] {ITestBean.class});
+ pc.addAdvice(ExposeInvocationInterceptor.INSTANCE);
+ pc.addAdvice(mi);
+
+ // We don't care about the object
+ mockTargetSource.setTarget(new Object());
+ pc.setTargetSource(mockTargetSource);
+ AopProxy aop = createAopProxy(pc);
+
+ try {
+ ITestBean tb = (ITestBean) aop.getProxy();
+ // Note: exception param below isn't used
+ tb.exceptional(expectedException);
+ fail("Should have thrown exception raised by interceptor");
+ }
+ catch (Exception thrown) {
+ assertEquals("exception matches", expectedException, thrown);
+ }
+ }
+
+ /**
+ * An interceptor throws a checked exception not on the method signature.
+ * For efficiency, we don't bother unifying java.lang.reflect and
+ * net.sf.cglib UndeclaredThrowableException
+ */
+ public void testUndeclaredCheckedException() throws Throwable {
+ final Exception unexpectedException = new Exception();
+ // Test return value
+ MethodInterceptor mi = new MethodInterceptor() {
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ throw unexpectedException;
+ }
+ };
+ AdvisedSupport pc = new AdvisedSupport(new Class[] {ITestBean.class});
+ pc.addAdvice(ExposeInvocationInterceptor.INSTANCE);
+ pc.addAdvice(mi);
+
+ // We don't care about the object
+ pc.setTarget(new TestBean());
+ AopProxy aop = createAopProxy(pc);
+ ITestBean tb = (ITestBean) aop.getProxy();
+
+ try {
+ // Note: exception param below isn't used
+ tb.getAge();
+ fail("Should have wrapped exception raised by interceptor");
+ }
+ catch (UndeclaredThrowableException thrown) {
+ assertEquals("exception matches", unexpectedException, thrown.getUndeclaredThrowable());
+ }
+ //catch (net.sf.cglib.proxy.UndeclaredThrowableException thrown) {
+ // assertEquals("exception matches", unexpectedException, thrown.getUndeclaredThrowable());
+ //}
+ catch (Exception ex) {
+ ex.printStackTrace();
+ fail("Didn't expect exception: " + ex);
+ }
+ }
+
+ public void testUndeclaredUnheckedException() throws Throwable {
+ final RuntimeException unexpectedException = new RuntimeException();
+ // Test return value
+ MethodInterceptor mi = new MethodInterceptor() {
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ throw unexpectedException;
+ }
+ };
+ AdvisedSupport pc = new AdvisedSupport(new Class[] {ITestBean.class});
+ pc.addAdvice(ExposeInvocationInterceptor.INSTANCE);
+ pc.addAdvice(mi);
+
+ // We don't care about the object
+ pc.setTarget(new TestBean());
+ AopProxy aop = createAopProxy(pc);
+ ITestBean tb = (ITestBean) aop.getProxy();
+
+ try {
+ // Note: exception param below isn't used
+ tb.getAge();
+ fail("Should have wrapped exception raised by interceptor");
+ }
+ catch (RuntimeException thrown) {
+ assertEquals("exception matches", unexpectedException, thrown);
+ }
+ //catch (net.sf.cglib.proxy.UndeclaredThrowableException thrown) {
+ // assertEquals("exception matches", unexpectedException, thrown.getUndeclaredThrowable());
+ //}
+ }
+
+ /**
+ * Check that although a method is eligible for advice chain optimization and
+ * direct reflective invocation, it doesn't happen if we've asked to see the proxy,
+ * so as to guarantee a consistent programming model.
+ * @throws Throwable
+ */
+ public void testTargetCanGetInvocationEvenIfNoAdviceChain() throws Throwable {
+ NeedsToSeeProxy target = new NeedsToSeeProxy();
+ AdvisedSupport pc = new AdvisedSupport(new Class[] {INeedsToSeeProxy.class});
+ pc.setTarget(target);
+ pc.setExposeProxy(true);
+
+ // Now let's try it with the special target
+ AopProxy aop = createAopProxy(pc);
+ INeedsToSeeProxy proxied = (INeedsToSeeProxy) aop.getProxy();
+ // It will complain if it can't get the proxy
+ proxied.incrementViaProxy();
+ }
+
+ public void testTargetCanGetInvocation() throws Throwable {
+ final InvocationCheckExposedInvocationTestBean expectedTarget = new InvocationCheckExposedInvocationTestBean();
+
+ AdvisedSupport pc = new AdvisedSupport(new Class[] {ITestBean.class, IOther.class});
+ pc.addAdvice(ExposeInvocationInterceptor.INSTANCE);
+ TrapTargetInterceptor tii = new TrapTargetInterceptor() {
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ // Assert that target matches BEFORE invocation returns
+ assertEquals("Target is correct", expectedTarget, invocation.getThis());
+ return super.invoke(invocation);
+ }
+ };
+ pc.addAdvice(tii);
+ pc.setTarget(expectedTarget);
+ AopProxy aop = createAopProxy(pc);
+
+ ITestBean tb = (ITestBean) aop.getProxy();
+ tb.getName();
+ // Not safe to trap invocation
+ //assertTrue(tii.invocation == target.invocation);
+
+ //assertTrue(target.invocation.getProxy() == tb);
+
+ // ((IOther) tb).absquatulate();
+ //MethodInvocation minv = tii.invocation;
+ //assertTrue("invoked on iother, not " + minv.getMethod().getDeclaringClass(), minv.getMethod().getDeclaringClass() == IOther.class);
+ //assertTrue(target.invocation == tii.invocation);
+ }
+
+ /**
+ * Throw an exception if there is an Invocation.
+ */
+ private void assertNoInvocationContext() {
+ try {
+ ExposeInvocationInterceptor.currentInvocation();
+ fail("Expected no invocation context");
+ }
+ catch (IllegalStateException ex) {
+ // ok
+ }
+ }
+
+ /**
+ * Test stateful interceptor
+ */
+ public void testMixinWithIntroductionAdvisor() throws Throwable {
+ TestBean tb = new TestBean();
+ ProxyFactory pc = new ProxyFactory(new Class[] {ITestBean.class});
+ pc.addAdvisor(new LockMixinAdvisor());
+ pc.setTarget(tb);
+
+ testTestBeanIntroduction(pc);
+ }
+
+ public void testMixinWithIntroductionInfo() throws Throwable {
+ TestBean tb = new TestBean();
+ ProxyFactory pc = new ProxyFactory(new Class[] {ITestBean.class});
+ // We don't use an IntroductionAdvisor, we can just add an advice that implements IntroductionInfo
+ pc.addAdvice(new LockMixin());
+ pc.setTarget(tb);
+
+ testTestBeanIntroduction(pc);
+ }
+
+ private void testTestBeanIntroduction(ProxyFactory pc) {
+ int newAge = 65;
+ ITestBean itb = (ITestBean) createProxy(pc);
+ itb.setAge(newAge);
+ assertTrue(itb.getAge() == newAge);
+
+ Lockable lockable = (Lockable) itb;
+ assertFalse(lockable.locked());
+ lockable.lock();
+
+ assertTrue(itb.getAge() == newAge);
+ try {
+ itb.setAge(1);
+ fail("Setters should fail when locked");
+ }
+ catch (LockedException ex) {
+ // ok
+ }
+ assertTrue(itb.getAge() == newAge);
+
+ // Unlock
+ assertTrue(lockable.locked());
+ lockable.unlock();
+ itb.setAge(1);
+ assertTrue(itb.getAge() == 1);
+ }
+
+
+ public void testReplaceArgument() throws Throwable {
+ TestBean tb = new TestBean();
+ ProxyFactory pc = new ProxyFactory(new Class[] {ITestBean.class});
+ pc.setTarget(tb);
+ pc.addAdvisor(new StringSetterNullReplacementAdvice());
+
+ ITestBean t = (ITestBean) pc.getProxy();
+ int newAge = 5;
+ t.setAge(newAge);
+ assertTrue(t.getAge() == newAge);
+ String newName = "greg";
+ t.setName(newName);
+ assertEquals(newName, t.getName());
+
+ t.setName(null);
+ // Null replacement magic should work
+ assertTrue(t.getName().equals(""));
+ }
+
+ public void testCanCastProxyToProxyConfig() throws Throwable {
+ TestBean tb = new TestBean();
+ ProxyFactory pc = new ProxyFactory(tb);
+ NopInterceptor di = new NopInterceptor();
+ pc.addAdvice(0, di);
+
+ ITestBean t = (ITestBean) createProxy(pc);
+ assertEquals(0, di.getCount());
+ t.setAge(23);
+ assertEquals(23, t.getAge());
+ assertEquals(2, di.getCount());
+
+ Advised advised = (Advised) t;
+ assertEquals("Have 1 advisor", 1, advised.getAdvisors().length);
+ assertEquals(di, advised.getAdvisors()[0].getAdvice());
+ NopInterceptor di2 = new NopInterceptor();
+ advised.addAdvice(1, di2);
+ t.getName();
+ assertEquals(3, di.getCount());
+ assertEquals(1, di2.getCount());
+ // will remove di
+ advised.removeAdvisor(0);
+ t.getAge();
+ // Unchanged
+ assertEquals(3, di.getCount());
+ assertEquals(2, di2.getCount());
+
+ CountingBeforeAdvice cba = new CountingBeforeAdvice();
+ assertEquals(0, cba.getCalls());
+ advised.addAdvice(cba);
+ t.setAge(16);
+ assertEquals(16, t.getAge());
+ assertEquals(2, cba.getCalls());
+ }
+
+ public void testAdviceImplementsIntroductionInfo() throws Throwable {
+ TestBean tb = new TestBean();
+ String name = "tony";
+ tb.setName(name);
+ ProxyFactory pc = new ProxyFactory(tb);
+ NopInterceptor di = new NopInterceptor();
+ pc.addAdvice(di);
+ final long ts = 37;
+ pc.addAdvice(new DelegatingIntroductionInterceptor(new TimeStamped() {
+ public long getTimeStamp() {
+ return ts;
+ }
+ }));
+
+ ITestBean proxied = (ITestBean) createProxy(pc);
+ assertEquals(name, proxied.getName());
+ TimeStamped intro = (TimeStamped) proxied;
+ assertEquals(ts, intro.getTimeStamp());
+ }
+
+ public void testCannotAddDynamicIntroductionAdviceExceptInIntroductionAdvice() throws Throwable {
+ TestBean target = new TestBean();
+ target.setAge(21);
+ ProxyFactory pc = new ProxyFactory(target);
+ try {
+ pc.addAdvice(new DummyIntroductionAdviceImpl());
+ fail("Shouldn't be able to add introduction interceptor except via introduction advice");
+ }
+ catch (AopConfigException ex) {
+ assertTrue(ex.getMessage().indexOf("ntroduction") > -1);
+ }
+ // Check it still works: proxy factory state shouldn't have been corrupted
+ ITestBean proxied = (ITestBean) createProxy(pc);
+ assertEquals(target.getAge(), proxied.getAge());
+ }
+
+ public void testRejectsBogusDynamicIntroductionAdviceWithNoAdapter() throws Throwable {
+ TestBean target = new TestBean();
+ target.setAge(21);
+ ProxyFactory pc = new ProxyFactory(target);
+ pc.addAdvisor(new DefaultIntroductionAdvisor(new DummyIntroductionAdviceImpl(), Comparable.class));
+ try {
+ // TODO May fail on either call: may want to tighten up definition
+ ITestBean proxied = (ITestBean) createProxy(pc);
+ proxied.getName();
+ fail("Bogus introduction");
+ }
+ catch (Exception ex) {
+ // TODO used to catch UnknownAdviceTypeException, but
+ // with CGLIB some errors are in proxy creation and are wrapped
+ // in aspect exception. Error message is still fine.
+ //assertTrue(ex.getMessage().indexOf("ntroduction") > -1);
+ }
+ }
+
+ /**
+ * Check that the introduction advice isn't allowed to introduce interfaces
+ * that are unsupported by the IntroductionInterceptor.
+ */
+ public void testCannotAddIntroductionAdviceWithUnimplementedInterface() throws Throwable {
+ TestBean target = new TestBean();
+ target.setAge(21);
+ ProxyFactory pc = new ProxyFactory(target);
+ try {
+ pc.addAdvisor(0, new DefaultIntroductionAdvisor(new TimestampIntroductionInterceptor(), ITestBean.class));
+ fail("Shouldn't be able to add introduction advice introducing an unimplemented interface");
+ }
+ catch (IllegalArgumentException ex) {
+ //assertTrue(ex.getMessage().indexOf("ntroduction") > -1);
+ }
+ // Check it still works: proxy factory state shouldn't have been corrupted
+ ITestBean proxied = (ITestBean) createProxy(pc);
+ assertEquals(target.getAge(), proxied.getAge());
+ }
+
+ /**
+ * Note that an introduction can't throw an unexpected checked exception,
+ * as it's constained by the interface.
+ */
+ public void testIntroductionThrowsUncheckedException() throws Throwable {
+ TestBean target = new TestBean();
+ target.setAge(21);
+ ProxyFactory pc = new ProxyFactory(target);
+
+ class MyDi extends DelegatingIntroductionInterceptor implements TimeStamped {
+ /**
+ * @see org.springframework.aop.framework.TimeStamped#getTimeStamp()
+ */
+ public long getTimeStamp() {
+ throw new UnsupportedOperationException();
+ }
+ }
+ pc.addAdvisor(new DefaultIntroductionAdvisor(new MyDi()));
+
+ TimeStamped ts = (TimeStamped) createProxy(pc);
+ try {
+ ts.getTimeStamp();
+ fail("Should throw UnsupportedOperationException");
+ }
+ catch (UnsupportedOperationException ex) {
+ }
+ }
+
+ /**
+ * Should only be able to introduce interfaces, not classes.
+ */
+ public void testCannotAddIntroductionAdviceToIntroduceClass() throws Throwable {
+ TestBean target = new TestBean();
+ target.setAge(21);
+ ProxyFactory pc = new ProxyFactory(target);
+ try {
+ pc.addAdvisor(0, new DefaultIntroductionAdvisor(new TimestampIntroductionInterceptor(), TestBean.class));
+ fail("Shouldn't be able to add introduction advice that introduces a class, rather than an interface");
+ }
+ catch (IllegalArgumentException ex) {
+ assertTrue(ex.getMessage().indexOf("interface") > -1);
+ }
+ // Check it still works: proxy factory state shouldn't have been corrupted
+ ITestBean proxied = (ITestBean) createProxy(pc);
+ assertEquals(target.getAge(), proxied.getAge());
+ }
+
+ public void testCannotAddInterceptorWhenFrozen() throws Throwable {
+ TestBean target = new TestBean();
+ target.setAge(21);
+ ProxyFactory pc = new ProxyFactory(target);
+ assertFalse(pc.isFrozen());
+ pc.addAdvice(new NopInterceptor());
+ ITestBean proxied = (ITestBean) createProxy(pc);
+ pc.setFrozen(true);
+ try {
+ pc.addAdvice(0, new NopInterceptor());
+ fail("Shouldn't be able to add interceptor when frozen");
+ }
+ catch (AopConfigException ex) {
+ assertTrue(ex.getMessage().indexOf("frozen") > -1);
+ }
+ // Check it still works: proxy factory state shouldn't have been corrupted
+ assertEquals(target.getAge(), proxied.getAge());
+ assertEquals(1, ((Advised) proxied).getAdvisors().length);
+ }
+
+ /**
+ * Check that casting to Advised can't get around advice freeze.
+ */
+ public void testCannotAddAdvisorWhenFrozenUsingCast() throws Throwable {
+ TestBean target = new TestBean();
+ target.setAge(21);
+ ProxyFactory pc = new ProxyFactory(target);
+ assertFalse(pc.isFrozen());
+ pc.addAdvice(new NopInterceptor());
+ ITestBean proxied = (ITestBean) createProxy(pc);
+ pc.setFrozen(true);
+ Advised advised = (Advised) proxied;
+
+ assertTrue(pc.isFrozen());
+ try {
+ advised.addAdvisor(new DefaultPointcutAdvisor(new NopInterceptor()));
+ fail("Shouldn't be able to add Advisor when frozen");
+ }
+ catch (AopConfigException ex) {
+ assertTrue(ex.getMessage().indexOf("frozen") > -1);
+ }
+ // Check it still works: proxy factory state shouldn't have been corrupted
+ assertEquals(target.getAge(), proxied.getAge());
+ assertEquals(1, advised.getAdvisors().length);
+ }
+
+ public void testCannotRemoveAdvisorWhenFrozen() throws Throwable {
+ TestBean target = new TestBean();
+ target.setAge(21);
+ ProxyFactory pc = new ProxyFactory(target);
+ assertFalse(pc.isFrozen());
+ pc.addAdvice(new NopInterceptor());
+ ITestBean proxied = (ITestBean) createProxy(pc);
+ pc.setFrozen(true);
+ Advised advised = (Advised) proxied;
+
+ assertTrue(pc.isFrozen());
+ try {
+ advised.removeAdvisor(0);
+ fail("Shouldn't be able to remove Advisor when frozen");
+ }
+ catch (AopConfigException ex) {
+ assertTrue(ex.getMessage().indexOf("frozen") > -1);
+ }
+ // Didn't get removed
+ assertEquals(1, advised.getAdvisors().length);
+ pc.setFrozen(false);
+ // Can now remove it
+ advised.removeAdvisor(0);
+ // Check it still works: proxy factory state shouldn't have been corrupted
+ assertEquals(target.getAge(), proxied.getAge());
+ assertEquals(0, advised.getAdvisors().length);
+ }
+
+ public void testUseAsHashKey() {
+ TestBean target1 = new TestBean();
+ ProxyFactory pf1 = new ProxyFactory(target1);
+ pf1.addAdvice(new NopInterceptor());
+ ITestBean proxy1 = (ITestBean) createProxy(pf1);
+
+ TestBean target2 = new TestBean();
+ ProxyFactory pf2 = new ProxyFactory(target2);
+ pf2.addAdvisor(new DefaultIntroductionAdvisor(new TimestampIntroductionInterceptor()));
+ ITestBean proxy2 = (ITestBean) createProxy(pf2);
+
+ HashMap h = new HashMap();
+ Object value1 = "foo";
+ Object value2 = "bar";
+ assertNull(h.get(proxy1));
+ h.put(proxy1, value1);
+ h.put(proxy2, value2);
+ assertEquals(h.get(proxy1), value1);
+ assertEquals(h.get(proxy2), value2);
+ }
+
+ /**
+ * Check that the string is informative.
+ */
+ public void testProxyConfigString() {
+ TestBean target = new TestBean();
+ ProxyFactory pc = new ProxyFactory(target);
+ pc.setInterfaces(new Class[] {ITestBean.class});
+ pc.addAdvice(new NopInterceptor());
+ MethodBeforeAdvice mba = new CountingBeforeAdvice();
+ Advisor advisor = new DefaultPointcutAdvisor(new NameMatchMethodPointcut(), mba);
+ pc.addAdvisor(advisor);
+ ITestBean proxied = (ITestBean) createProxy(pc);
+
+ String proxyConfigString = ((Advised) proxied).toProxyConfigString();
+ assertTrue(proxyConfigString.indexOf(advisor.toString()) != -1);
+ assertTrue(proxyConfigString.indexOf("1 interface") != -1);
+ }
+
+ public void testCanPreventCastToAdvisedUsingOpaque() {
+ TestBean target = new TestBean();
+ ProxyFactory pc = new ProxyFactory(target);
+ pc.setInterfaces(new Class[] {ITestBean.class});
+ pc.addAdvice(new NopInterceptor());
+ CountingBeforeAdvice mba = new CountingBeforeAdvice();
+ Advisor advisor = new DefaultPointcutAdvisor(new NameMatchMethodPointcut().addMethodName("setAge"), mba);
+ pc.addAdvisor(advisor);
+ assertFalse("Opaque defaults to false", pc.isOpaque());
+ pc.setOpaque(true);
+ assertTrue("Opaque now true for this config", pc.isOpaque());
+ ITestBean proxied = (ITestBean) createProxy(pc);
+ proxied.setAge(10);
+ assertEquals(10, proxied.getAge());
+ assertEquals(1, mba.getCalls());
+
+ assertFalse("Cannot be cast to Advised", proxied instanceof Advised);
+ }
+
+ public void testAdviceSupportListeners() throws Throwable {
+ TestBean target = new TestBean();
+ target.setAge(21);
+
+ ProxyFactory pc = new ProxyFactory(target);
+ CountingAdvisorListener l = new CountingAdvisorListener(pc);
+ pc.addListener(l);
+ RefreshCountingAdvisorChainFactory acf = new RefreshCountingAdvisorChainFactory();
+ // Should be automatically added as a listener
+ pc.addListener(acf);
+ assertFalse(pc.isActive());
+ assertEquals(0, l.activates);
+ assertEquals(0, acf.refreshes);
+ ITestBean proxied = (ITestBean) createProxy(pc);
+ assertEquals(1, acf.refreshes);
+ assertEquals(1, l.activates);
+ assertTrue(pc.isActive());
+ assertEquals(target.getAge(), proxied.getAge());
+ assertEquals(0, l.adviceChanges);
+ NopInterceptor di = new NopInterceptor();
+ pc.addAdvice(0, di);
+ assertEquals(1, l.adviceChanges);
+ assertEquals(2, acf.refreshes);
+ assertEquals(target.getAge(), proxied.getAge());
+ pc.removeAdvice(di);
+ assertEquals(2, l.adviceChanges);
+ assertEquals(3, acf.refreshes);
+ assertEquals(target.getAge(), proxied.getAge());
+ pc.getProxy();
+ assertEquals(1, l.activates);
+
+ pc.removeListener(l);
+ assertEquals(2, l.adviceChanges);
+ pc.addAdvisor(new DefaultPointcutAdvisor(new NopInterceptor()));
+ // No longer counting
+ assertEquals(2, l.adviceChanges);
+ }
+
+ public void testExistingProxyChangesTarget() throws Throwable {
+ TestBean tb1 = new TestBean();
+ tb1.setAge(33);
+
+ TestBean tb2 = new TestBean();
+ tb2.setAge(26);
+ tb2.setName("Juergen");
+ TestBean tb3 = new TestBean();
+ tb3.setAge(37);
+ ProxyFactory pc = new ProxyFactory(tb1);
+ NopInterceptor nop = new NopInterceptor();
+ pc.addAdvice(nop);
+ ITestBean proxy = (ITestBean) createProxy(pc);
+ assertEquals(nop.getCount(), 0);
+ assertEquals(tb1.getAge(), proxy.getAge());
+ assertEquals(nop.getCount(), 1);
+ // Change to a new static target
+ pc.setTarget(tb2);
+ assertEquals(tb2.getAge(), proxy.getAge());
+ assertEquals(nop.getCount(), 2);
+
+ // Change to a new dynamic target
+ HotSwappableTargetSource hts = new HotSwappableTargetSource(tb3);
+ pc.setTargetSource(hts);
+ assertEquals(tb3.getAge(), proxy.getAge());
+ assertEquals(nop.getCount(), 3);
+ hts.swap(tb1);
+ assertEquals(tb1.getAge(), proxy.getAge());
+ tb1.setName("Colin");
+ assertEquals(tb1.getName(), proxy.getName());
+ assertEquals(nop.getCount(), 5);
+
+ // Change back, relying on casting to Advised
+ Advised advised = (Advised) proxy;
+ assertSame(hts, advised.getTargetSource());
+ SingletonTargetSource sts = new SingletonTargetSource(tb2);
+ advised.setTargetSource(sts);
+ assertEquals(tb2.getName(), proxy.getName());
+ assertSame(sts, advised.getTargetSource());
+ assertEquals(tb2.getAge(), proxy.getAge());
+ }
+
+ public void testDynamicMethodPointcutThatAlwaysAppliesStatically() throws Throwable {
+ TestBean tb = new TestBean();
+ ProxyFactory pc = new ProxyFactory(new Class[] {ITestBean.class});
+ TestDynamicPointcutAdvice dp = new TestDynamicPointcutAdvice(new NopInterceptor(), "getAge");
+ pc.addAdvisor(dp);
+ pc.setTarget(tb);
+ ITestBean it = (ITestBean) createProxy(pc);
+ assertEquals(dp.count, 0);
+ int age = it.getAge();
+ assertEquals(dp.count, 1);
+ it.setAge(11);
+ assertEquals(it.getAge(), 11);
+ assertEquals(dp.count, 2);
+ }
+
+ public void testDynamicMethodPointcutThatAppliesStaticallyOnlyToSetters() throws Throwable {
+ TestBean tb = new TestBean();
+ ProxyFactory pc = new ProxyFactory(new Class[] {ITestBean.class});
+ // Could apply dynamically to getAge/setAge but not to getName
+ TestDynamicPointcutForSettersOnly dp = new TestDynamicPointcutForSettersOnly(new NopInterceptor(), "Age");
+ pc.addAdvisor(dp);
+ this.mockTargetSource.setTarget(tb);
+ pc.setTargetSource(mockTargetSource);
+ ITestBean it = (ITestBean) createProxy(pc);
+ assertEquals(dp.count, 0);
+ int age = it.getAge();
+ // Statically vetoed
+ assertEquals(0, dp.count);
+ it.setAge(11);
+ assertEquals(it.getAge(), 11);
+ assertEquals(dp.count, 1);
+ // Applies statically but not dynamically
+ it.setName("joe");
+ assertEquals(dp.count, 1);
+ }
+
+ public void testStaticMethodPointcut() throws Throwable {
+ TestBean tb = new TestBean();
+ ProxyFactory pc = new ProxyFactory(new Class[] {ITestBean.class});
+ NopInterceptor di = new NopInterceptor();
+ TestStaticPointcutAdvice sp = new TestStaticPointcutAdvice(di, "getAge");
+ pc.addAdvisor(sp);
+ pc.setTarget(tb);
+ ITestBean it = (ITestBean) createProxy(pc);
+ assertEquals(di.getCount(), 0);
+ int age = it.getAge();
+ assertEquals(di.getCount(), 1);
+ it.setAge(11);
+ assertEquals(it.getAge(), 11);
+ assertEquals(di.getCount(), 2);
+ }
+
+ /**
+ * There are times when we want to call proceed() twice.
+ * We can do this if we clone the invocation.
+ */
+ public void testCloneInvocationToProceedThreeTimes() throws Throwable {
+ TestBean tb = new TestBean();
+ ProxyFactory pc = new ProxyFactory(tb);
+ pc.addInterface(ITestBean.class);
+
+ MethodInterceptor twoBirthdayInterceptor = new MethodInterceptor() {
+ public Object invoke(MethodInvocation mi) throws Throwable {
+ // Clone the invocation to proceed three times
+ // "The Moor's Last Sigh": this technology can cause premature aging
+ MethodInvocation clone1 = ((ReflectiveMethodInvocation) mi).invocableClone();
+ MethodInvocation clone2 = ((ReflectiveMethodInvocation) mi).invocableClone();
+ clone1.proceed();
+ clone2.proceed();
+ return mi.proceed();
+ }
+ };
+ StaticMethodMatcherPointcutAdvisor advisor = new StaticMethodMatcherPointcutAdvisor(twoBirthdayInterceptor) {
+ public boolean matches(Method m, Class targetClass) {
+ return "haveBirthday".equals(m.getName());
+ }
+ };
+ pc.addAdvisor(advisor);
+ ITestBean it = (ITestBean) createProxy(pc);
+
+ final int age = 20;
+ it.setAge(age);
+ assertEquals(age, it.getAge());
+ // Should return the age before the third, AOP-induced birthday
+ assertEquals(age + 2, it.haveBirthday());
+ // Return the final age produced by 3 birthdays
+ assertEquals(age + 3, it.getAge());
+ }
+
+ /**
+ * We want to change the arguments on a clone: it shouldn't affect the original.
+ */
+ public void testCanChangeArgumentsIndependentlyOnClonedInvocation() throws Throwable {
+ TestBean tb = new TestBean();
+ ProxyFactory pc = new ProxyFactory(tb);
+ pc.addInterface(ITestBean.class);
+
+ /**
+ * Changes the name, then changes it back.
+ */
+ MethodInterceptor nameReverter = new MethodInterceptor() {
+ public Object invoke(MethodInvocation mi) throws Throwable {
+ MethodInvocation clone = ((ReflectiveMethodInvocation) mi).invocableClone();
+ String oldName = ((ITestBean) mi.getThis()).getName();
+ clone.getArguments()[0] = oldName;
+ // Original method invocation should be unaffected by changes to argument list of clone
+ mi.proceed();
+ return clone.proceed();
+ }
+ };
+
+ class NameSaver implements MethodInterceptor {
+ private List names = new LinkedList();
+
+ public Object invoke(MethodInvocation mi) throws Throwable {
+ names.add(mi.getArguments()[0]);
+ return mi.proceed();
+ }
+ }
+
+ NameSaver saver = new NameSaver();
+
+ pc.addAdvisor(new DefaultPointcutAdvisor(Pointcuts.SETTERS, nameReverter));
+ pc.addAdvisor(new DefaultPointcutAdvisor(Pointcuts.SETTERS, saver));
+ ITestBean it = (ITestBean) createProxy(pc);
+
+ String name1 = "tony";
+ String name2 = "gordon";
+
+ tb.setName(name1);
+ assertEquals(name1, tb.getName());
+
+ it.setName(name2);
+ // NameReverter saved it back
+ assertEquals(name1, it.getName());
+ assertEquals(2, saver.names.size());
+ assertEquals(name2, saver.names.get(0));
+ assertEquals(name1, saver.names.get(1));
+ }
+
+ public void testOverloadedMethodsWithDifferentAdvice() throws Throwable {
+ Overloads target = new Overloads();
+ ProxyFactory pc = new ProxyFactory(target);
+ NopInterceptor overLoadVoids = new NopInterceptor();
+ pc.addAdvisor(new StaticMethodMatcherPointcutAdvisor(overLoadVoids) {
+ public boolean matches(Method m, Class targetClass) {
+ return m.getName().equals("overload") && m.getParameterTypes().length == 0;
+ }
+ });
+ NopInterceptor overLoadInts = new NopInterceptor();
+ pc.addAdvisor(new StaticMethodMatcherPointcutAdvisor(overLoadInts) {
+ public boolean matches(Method m, Class targetClass) {
+ return m.getName().equals("overload") && m.getParameterTypes().length == 1 &&
+ m.getParameterTypes()[0].equals(int.class);
+ }
+ });
+
+ IOverloads proxy = (IOverloads) createProxy(pc);
+ assertEquals(0, overLoadInts.getCount());
+ assertEquals(0, overLoadVoids.getCount());
+ proxy.overload();
+ assertEquals(0, overLoadInts.getCount());
+ assertEquals(1, overLoadVoids.getCount());
+ assertEquals(25, proxy.overload(25));
+ assertEquals(1, overLoadInts.getCount());
+ assertEquals(1, overLoadVoids.getCount());
+ proxy.noAdvice();
+ assertEquals(1, overLoadInts.getCount());
+ assertEquals(1, overLoadVoids.getCount());
+ }
+
+ public void testProxyIsBoundBeforeTargetSourceInvoked() {
+ final TestBean target = new TestBean();
+ ProxyFactory pf = new ProxyFactory(target);
+ pf.addAdvice(new DebugInterceptor());
+ pf.setExposeProxy(true);
+ final ITestBean proxy = (ITestBean) createProxy(pf);
+ Advised config = (Advised) proxy;
+ // This class just checks proxy is bound before getTarget() call
+ config.setTargetSource(new TargetSource() {
+ public Class getTargetClass() {
+ return TestBean.class;
+ }
+
+ public boolean isStatic() {
+ return false;
+ }
+
+ public Object getTarget() throws Exception {
+ assertEquals(proxy, AopContext.currentProxy());
+ return target;
+ }
+
+ public void releaseTarget(Object target) throws Exception {
+ }
+ });
+
+ // Just test anything: it will fail if context wasn't found
+ assertEquals(0, proxy.getAge());
+ }
+
+ public void testEquals() {
+ IOther a = new AllInstancesAreEqual();
+ IOther b = new AllInstancesAreEqual();
+ NopInterceptor i1 = new NopInterceptor();
+ NopInterceptor i2 = new NopInterceptor();
+ ProxyFactory pfa = new ProxyFactory(a);
+ pfa.addAdvice(i1);
+ ProxyFactory pfb = new ProxyFactory(b);
+ pfb.addAdvice(i2);
+ IOther proxyA = (IOther) createProxy(pfa);
+ IOther proxyB = (IOther) createProxy(pfb);
+
+ assertEquals(pfa.getAdvisors().length, pfb.getAdvisors().length);
+ assertTrue(a.equals(b));
+ assertTrue(i1.equals(i2));
+ assertTrue(proxyA.equals(proxyB));
+ assertEquals(proxyA.hashCode(), proxyB.hashCode());
+ assertFalse(proxyA.equals(a));
+
+ // Equality checks were handled by the proxy
+ assertEquals(0, i1.getCount());
+
+ // When we invoke A, it's NopInterceptor will have count == 1
+ // and won't think it's equal to B's NopInterceptor
+ proxyA.absquatulate();
+ assertEquals(1, i1.getCount());
+ assertFalse(proxyA.equals(proxyB));
+ }
+
+ public void testBeforeAdvisorIsInvoked() {
+ CountingBeforeAdvice cba = new CountingBeforeAdvice();
+ Advisor matchesNoArgs = new StaticMethodMatcherPointcutAdvisor(cba) {
+ public boolean matches(Method m, Class targetClass) {
+ return m.getParameterTypes().length == 0;
+ }
+ };
+ TestBean target = new TestBean();
+ target.setAge(80);
+ ProxyFactory pf = new ProxyFactory(target);
+ pf.addAdvice(new NopInterceptor());
+ pf.addAdvisor(matchesNoArgs);
+ assertEquals("Advisor was added", matchesNoArgs, pf.getAdvisors()[1]);
+ ITestBean proxied = (ITestBean) createProxy(pf);
+ assertEquals(0, cba.getCalls());
+ assertEquals(0, cba.getCalls("getAge"));
+ assertEquals(target.getAge(), proxied.getAge());
+ assertEquals(1, cba.getCalls());
+ assertEquals(1, cba.getCalls("getAge"));
+ assertEquals(0, cba.getCalls("setAge"));
+ // Won't be advised
+ proxied.setAge(26);
+ assertEquals(1, cba.getCalls());
+ assertEquals(26, proxied.getAge());
+ }
+
+ public void testUserAttributes() throws Throwable {
+ class MapAwareMethodInterceptor implements MethodInterceptor {
+ private final Map expectedValues;
+ private final Map valuesToAdd;
+ public MapAwareMethodInterceptor(Map expectedValues, Map valuesToAdd) {
+ this.expectedValues = expectedValues;
+ this.valuesToAdd = valuesToAdd;
+ }
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ ReflectiveMethodInvocation rmi = (ReflectiveMethodInvocation) invocation;
+ for (Iterator it = rmi.getUserAttributes().keySet().iterator(); it.hasNext(); ){
+ Object key = it.next();
+ assertEquals(expectedValues.get(key), rmi.getUserAttributes().get(key));
+ }
+ rmi.getUserAttributes().putAll(valuesToAdd);
+ return invocation.proceed();
+ }
+ };
+ AdvisedSupport pc = new AdvisedSupport(new Class[] {ITestBean.class});
+ MapAwareMethodInterceptor mami1 = new MapAwareMethodInterceptor(new HashMap(), new HashMap());
+ Map firstValuesToAdd = new HashMap();
+ firstValuesToAdd.put("test", "");
+ MapAwareMethodInterceptor mami2 = new MapAwareMethodInterceptor(new HashMap(), firstValuesToAdd);
+ MapAwareMethodInterceptor mami3 = new MapAwareMethodInterceptor(firstValuesToAdd, new HashMap());
+ MapAwareMethodInterceptor mami4 = new MapAwareMethodInterceptor(firstValuesToAdd, new HashMap());
+ Map secondValuesToAdd = new HashMap();
+ secondValuesToAdd.put("foo", "bar");
+ secondValuesToAdd.put("cat", "dog");
+ MapAwareMethodInterceptor mami5 = new MapAwareMethodInterceptor(firstValuesToAdd, secondValuesToAdd);
+ Map finalExpected = new HashMap(firstValuesToAdd);
+ finalExpected.putAll(secondValuesToAdd);
+ MapAwareMethodInterceptor mami6 = new MapAwareMethodInterceptor(finalExpected, secondValuesToAdd);
+
+ pc.addAdvice(mami1);
+ pc.addAdvice(mami2);
+ pc.addAdvice(mami3);
+ pc.addAdvice(mami4);
+ pc.addAdvice(mami5);
+ pc.addAdvice(mami6);
+
+ // We don't care about the object
+ pc.setTarget(new TestBean());
+ AopProxy aop = createAopProxy(pc);
+ ITestBean tb = (ITestBean) aop.getProxy();
+
+ String newName = "foo";
+ tb.setName(newName);
+ assertEquals(newName, tb.getName());
+ }
+
+ public void testMultiAdvice() throws Throwable {
+ CountingMultiAdvice cca = new CountingMultiAdvice();
+ Advisor matchesNoArgs = new StaticMethodMatcherPointcutAdvisor(cca) {
+ public boolean matches(Method m, Class targetClass) {
+ return m.getParameterTypes().length == 0 || "exceptional".equals(m.getName());
+ }
+ };
+ TestBean target = new TestBean();
+ target.setAge(80);
+ ProxyFactory pf = new ProxyFactory(target);
+ pf.addAdvice(new NopInterceptor());
+ pf.addAdvisor(matchesNoArgs);
+ assertEquals("Advisor was added", matchesNoArgs, pf.getAdvisors()[1]);
+ ITestBean proxied = (ITestBean) createProxy(pf);
+
+ assertEquals(0, cca.getCalls());
+ assertEquals(0, cca.getCalls("getAge"));
+ assertEquals(target.getAge(), proxied.getAge());
+ assertEquals(2, cca.getCalls());
+ assertEquals(2, cca.getCalls("getAge"));
+ assertEquals(0, cca.getCalls("setAge"));
+ // Won't be advised
+ proxied.setAge(26);
+ assertEquals(2, cca.getCalls());
+ assertEquals(26, proxied.getAge());
+ assertEquals(4, cca.getCalls());
+ try {
+ proxied.exceptional(new CannotGetJdbcConnectionException("foo", (SQLException)null));
+ fail("Should have thrown CannotGetJdbcConnectionException");
+ }
+ catch (CannotGetJdbcConnectionException ex) {
+ // expected
+ }
+ assertEquals(6, cca.getCalls());
+ }
+
+ public void testBeforeAdviceThrowsException() {
+ final RuntimeException rex = new RuntimeException();
+ CountingBeforeAdvice ba = new CountingBeforeAdvice() {
+ public void before(Method m, Object[] args, Object target) throws Throwable {
+ super.before(m, args, target);
+ if (m.getName().startsWith("set"))
+ throw rex;
+ }
+ };
+
+ TestBean target = new TestBean();
+ target.setAge(80);
+ NopInterceptor nop1 = new NopInterceptor();
+ NopInterceptor nop2 = new NopInterceptor();
+ ProxyFactory pf = new ProxyFactory(target);
+ pf.addAdvice(nop1);
+ pf.addAdvice(ba);
+ pf.addAdvice(nop2);
+ ITestBean proxied = (ITestBean) createProxy(pf);
+ // Won't throw an exception
+ assertEquals(target.getAge(), proxied.getAge());
+ assertEquals(1, ba.getCalls());
+ assertEquals(1, ba.getCalls("getAge"));
+ assertEquals(1, nop1.getCount());
+ assertEquals(1, nop2.getCount());
+ // Will fail, after invoking Nop1
+ try {
+ proxied.setAge(26);
+ fail("before advice should have ended chain");
+ }
+ catch (RuntimeException ex) {
+ assertEquals(rex, ex);
+ }
+ assertEquals(2, ba.getCalls());
+ assertEquals(2, nop1.getCount());
+ // Nop2 didn't get invoked when the exception was thrown
+ assertEquals(1, nop2.getCount());
+ // Shouldn't have changed value in joinpoint
+ assertEquals(target.getAge(), proxied.getAge());
+ }
+
+
+ public void testAfterReturningAdvisorIsInvoked() {
+ class SummingAfterAdvice implements AfterReturningAdvice {
+ public int sum;
+ public void afterReturning(Object returnValue, Method m, Object[] args, Object target) throws Throwable {
+ sum += ((Integer) returnValue).intValue();
+ }
+ }
+ SummingAfterAdvice aa = new SummingAfterAdvice();
+ Advisor matchesInt = new StaticMethodMatcherPointcutAdvisor(aa) {
+ public boolean matches(Method m, Class targetClass) {
+ return m.getReturnType() == int.class;
+ }
+ };
+ TestBean target = new TestBean();
+ ProxyFactory pf = new ProxyFactory(target);
+ pf.addAdvice(new NopInterceptor());
+ pf.addAdvisor(matchesInt);
+ assertEquals("Advisor was added", matchesInt, pf.getAdvisors()[1]);
+ ITestBean proxied = (ITestBean) createProxy(pf);
+ assertEquals(0, aa.sum);
+ int i1 = 12;
+ int i2 = 13;
+
+ // Won't be advised
+ proxied.setAge(i1);
+ assertEquals(i1, proxied.getAge());
+ assertEquals(i1, aa.sum);
+ proxied.setAge(i2);
+ assertEquals(i2, proxied.getAge());
+ assertEquals(i1 + i2, aa.sum);
+ assertEquals(i2, proxied.getAge());
+ }
+
+ public void testAfterReturningAdvisorIsNotInvokedOnException() {
+ CountingAfterReturningAdvice car = new CountingAfterReturningAdvice();
+ TestBean target = new TestBean();
+ ProxyFactory pf = new ProxyFactory(target);
+ pf.addAdvice(new NopInterceptor());
+ pf.addAdvice(car);
+ assertEquals("Advice was wrapped in Advisor and added", car, pf.getAdvisors()[1].getAdvice());
+ ITestBean proxied = (ITestBean) createProxy(pf);
+ assertEquals(0, car.getCalls());
+ int age = 10;
+ proxied.setAge(age);
+ assertEquals(age, proxied.getAge());
+ assertEquals(2, car.getCalls());
+ Exception exc = new Exception();
+ // On exception it won't be invoked
+ try {
+ proxied.exceptional(exc);
+ fail();
+ }
+ catch (Throwable t) {
+ assertSame(exc, t);
+ }
+ assertEquals(2, car.getCalls());
+ }
+
+
+ public void testThrowsAdvisorIsInvoked() throws Throwable {
+ // Reacts to ServletException and RemoteException
+ ThrowsAdviceInterceptorTests.MyThrowsHandler th = new ThrowsAdviceInterceptorTests.MyThrowsHandler();
+ Advisor matchesEchoInvocations = new StaticMethodMatcherPointcutAdvisor(th) {
+ public boolean matches(Method m, Class targetClass) {
+ return m.getName().startsWith("echo");
+ }
+ };
+
+ ThrowsAdviceInterceptorTests.Echo target = new ThrowsAdviceInterceptorTests.Echo();
+ target.setA(16);
+ ProxyFactory pf = new ProxyFactory(target);
+ pf.addAdvice(new NopInterceptor());
+ pf.addAdvisor(matchesEchoInvocations);
+ assertEquals("Advisor was added", matchesEchoInvocations, pf.getAdvisors()[1]);
+ ThrowsAdviceInterceptorTests.IEcho proxied = (ThrowsAdviceInterceptorTests.IEcho) createProxy(pf);
+ assertEquals(0, th.getCalls());
+ assertEquals(target.getA(), proxied.getA());
+ assertEquals(0, th.getCalls());
+ Exception ex = new Exception();
+ // Will be advised but doesn't match
+ try {
+ proxied.echoException(1, ex);
+ fail();
+ }
+ catch (Exception caught) {
+ assertEquals(ex, caught);
+ }
+
+ ex = new ServletException();
+ try {
+ proxied.echoException(1, ex);
+ fail();
+ }
+ catch (ServletException caught) {
+ assertEquals(ex, caught);
+ }
+ assertEquals(1, th.getCalls("servletException"));
+ }
+
+ public void testAddThrowsAdviceWithoutAdvisor() throws Throwable {
+ // Reacts to ServletException and RemoteException
+ ThrowsAdviceInterceptorTests.MyThrowsHandler th = new ThrowsAdviceInterceptorTests.MyThrowsHandler();
+
+ ThrowsAdviceInterceptorTests.Echo target = new ThrowsAdviceInterceptorTests.Echo();
+ target.setA(16);
+ ProxyFactory pf = new ProxyFactory(target);
+ pf.addAdvice(new NopInterceptor());
+ pf.addAdvice(th);
+ ThrowsAdviceInterceptorTests.IEcho proxied = (ThrowsAdviceInterceptorTests.IEcho) createProxy(pf);
+ assertEquals(0, th.getCalls());
+ assertEquals(target.getA(), proxied.getA());
+ assertEquals(0, th.getCalls());
+ Exception ex = new Exception();
+ // Will be advised but doesn't match
+ try {
+ proxied.echoException(1, ex);
+ fail();
+ }
+ catch (Exception caught) {
+ assertEquals(ex, caught);
+ }
+
+ // Subclass of RemoteException
+ ex = new TransactionRequiredException();
+ try {
+ proxied.echoException(1, ex);
+ fail();
+ }
+ catch (TransactionRequiredException caught) {
+ assertEquals(ex, caught);
+ }
+ assertEquals(1, th.getCalls("remoteException"));
+ }
+
+
+ private static class CheckMethodInvocationIsSameInAndOutInterceptor implements MethodInterceptor {
+
+ public Object invoke(MethodInvocation mi) throws Throwable {
+ Method m = mi.getMethod();
+ Object retval = mi.proceed();
+ assertEquals("Method invocation has same method on way back", m, mi.getMethod());
+ return retval;
+ }
+ }
+
+
+ /**
+ * ExposeInvocation must be set to true.
+ */
+ private static class CheckMethodInvocationViaThreadLocalIsSameInAndOutInterceptor implements MethodInterceptor {
+
+ public Object invoke(MethodInvocation mi) throws Throwable {
+ String task = "get invocation on way IN";
+ try {
+ MethodInvocation current = ExposeInvocationInterceptor.currentInvocation();
+ assertEquals(mi.getMethod(), current.getMethod());
+ Object retval = mi.proceed();
+ task = "get invocation on way OUT";
+ assertEquals(current, ExposeInvocationInterceptor.currentInvocation());
+ return retval;
+ }
+ catch (IllegalStateException ex) {
+ System.err.println(task + " for " + mi.getMethod());
+ ex.printStackTrace();
+ throw ex;
+ }
+ }
+ }
+
+
+ /**
+ * Same thing for a proxy.
+ * Only works when exposeProxy is set to true.
+ * Checks that the proxy is the same on the way in and out.
+ */
+ private static class ProxyMatcherInterceptor implements MethodInterceptor {
+
+ public Object invoke(MethodInvocation mi) throws Throwable {
+ Object proxy = AopContext.currentProxy();
+ Object ret = mi.proceed();
+ // TODO why does this cause stack overflow?
+ //assertEquals(proxy, AopContext.currentProxy());
+ assertTrue(proxy == AopContext.currentProxy());
+ return ret;
+ }
+ }
+
+
+ /**
+ * Fires on setter methods that take a string. Replaces null arg with "".
+ */
+ protected static class StringSetterNullReplacementAdvice extends DefaultPointcutAdvisor {
+
+ private static MethodInterceptor cleaner = new MethodInterceptor() {
+ public Object invoke(MethodInvocation mi) throws Throwable {
+ // We know it can only be invoked if there's a single parameter of type string
+ mi.getArguments()[0] = "";
+ return mi.proceed();
+ }
+ };
+
+ public StringSetterNullReplacementAdvice() {
+ super(cleaner);
+ setPointcut(new DynamicMethodMatcherPointcut() {
+ public boolean matches(Method m, Class targetClass, Object[] args) {
+ return args[0] == null;
+ }
+ public boolean matches(Method m, Class targetClass) {
+ return m.getName().startsWith("set") &&
+ m.getParameterTypes().length == 1 &&
+ m.getParameterTypes()[0].equals(String.class);
+ }
+ });
+ }
+ }
+
+
+ protected static class TestDynamicPointcutAdvice extends DefaultPointcutAdvisor {
+
+ public int count;
+
+ public TestDynamicPointcutAdvice(MethodInterceptor mi, final String pattern) {
+ super(mi);
+ setPointcut(new DynamicMethodMatcherPointcut() {
+ public boolean matches(Method m, Class targetClass, Object[] args) {
+ boolean run = m.getName().indexOf(pattern) != -1;
+ if (run) ++count;
+ return run;
+ }
+ });
+ }
+ }
+
+
+ protected static class TestDynamicPointcutForSettersOnly extends DefaultPointcutAdvisor {
+
+ public int count;
+
+ public TestDynamicPointcutForSettersOnly(MethodInterceptor mi, final String pattern) {
+ super(mi);
+ setPointcut(new DynamicMethodMatcherPointcut() {
+ public boolean matches(Method m, Class targetClass, Object[] args) {
+ boolean run = m.getName().indexOf(pattern) != -1;
+ if (run) ++count;
+ return run;
+ }
+ public boolean matches(Method m, Class clazz) {
+ return m.getName().startsWith("set");
+ }
+ });
+ }
+ }
+
+
+ protected static class TestStaticPointcutAdvice extends StaticMethodMatcherPointcutAdvisor {
+
+ private String pattern;
+ private int count;
+
+ public TestStaticPointcutAdvice(MethodInterceptor mi, String pattern) {
+ super(mi);
+ this.pattern = pattern;
+ }
+ public boolean matches(Method m, Class targetClass) {
+ boolean run = m.getName().indexOf(pattern) != -1;
+ if (run) ++count;
+ return run;
+ }
+ }
+
+
+ /**
+ * Note that trapping the Invocation as in previous version of this test
+ * isn't safe, as invocations may be reused
+ * and hence cleared at the end of each invocation.
+ * So we trap only the targe.
+ */
+ protected static class TrapTargetInterceptor implements MethodInterceptor {
+
+ public Object target;
+
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ this.target = invocation.getThis();
+ return invocation.proceed();
+ }
+ }
+
+
+ private static class DummyIntroductionAdviceImpl implements DynamicIntroductionAdvice {
+
+ public boolean implementsInterface(Class intf) {
+ return true;
+ }
+ }
+
+
+ public static class OwnSpouse extends TestBean {
+
+ public ITestBean getSpouse() {
+ return this;
+ }
+ }
+
+
+ public static class AllInstancesAreEqual implements IOther {
+
+ public boolean equals(Object other) {
+ return (other instanceof AllInstancesAreEqual);
+ }
+
+ public int hashCode() {
+ return getClass().hashCode();
+ }
+
+ public void absquatulate() {
+ }
+ }
+
+
+ public interface INeedsToSeeProxy {
+
+ int getCount();
+
+ void incrementViaThis();
+
+ void incrementViaProxy();
+
+ void increment();
+ }
+
+
+ public static class NeedsToSeeProxy implements INeedsToSeeProxy {
+
+ private int count;
+
+ public int getCount() {
+ return count;
+ }
+
+ public void incrementViaThis() {
+ this.increment();
+ }
+
+ public void incrementViaProxy() {
+ INeedsToSeeProxy thisViaProxy = (INeedsToSeeProxy) AopContext.currentProxy();
+ thisViaProxy.increment();
+ Advised advised = (Advised) thisViaProxy;
+ checkAdvised(advised);
+ }
+
+ protected void checkAdvised(Advised advised) {
+ }
+
+ public void increment() {
+ ++count;
+ }
+ }
+
+
+ public static class TargetChecker extends NeedsToSeeProxy {
+
+ protected void checkAdvised(Advised advised) {
+ // TODO replace this check: no longer possible
+ //assertEquals(advised.getTarget(), this);
+ }
+ }
+
+
+ public static class CountingAdvisorListener implements AdvisedSupportListener {
+
+ public int adviceChanges;
+ public int activates;
+ private AdvisedSupport expectedSource;
+
+ public CountingAdvisorListener(AdvisedSupport expectedSource) {
+ this.expectedSource = expectedSource;
+ }
+
+ public void activated(AdvisedSupport advised) {
+ assertEquals(expectedSource, advised);
+ ++activates;
+ }
+
+ public void adviceChanged(AdvisedSupport advised) {
+ assertEquals(expectedSource, advised);
+ ++adviceChanges;
+ }
+ }
+
+
+ public static class RefreshCountingAdvisorChainFactory implements AdvisedSupportListener {
+
+ public int refreshes;
+
+ public void activated(AdvisedSupport advised) {
+ ++refreshes;
+ }
+
+ public void adviceChanged(AdvisedSupport advised) {
+ ++refreshes;
+ }
+ }
+
+
+ public static interface IOverloads {
+
+ void overload();
+
+ int overload(int i);
+
+ String overload(String foo);
+
+ void noAdvice();
+ }
+
+
+ public static class Overloads implements IOverloads {
+
+ public void overload() {
+ }
+
+ public int overload(int i) {
+ return i;
+ }
+
+ public String overload(String s) {
+ return s;
+ }
+
+ public void noAdvice() {
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/AopProxyUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/AopProxyUtilsTests.java
new file mode 100644
index 00000000000..22a9a655e36
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/AopProxyUtilsTests.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.SpringProxy;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+
+/**
+ * @author Rod Johnson
+ */
+public class AopProxyUtilsTests extends TestCase {
+
+ public void testCompleteProxiedInterfacesWorksWithNull() {
+ AdvisedSupport as = new AdvisedSupport();
+ Class[] completedInterfaces = AopProxyUtils.completeProxiedInterfaces(as);
+ assertEquals(2, completedInterfaces.length);
+ List ifaces = Arrays.asList(completedInterfaces);
+ assertTrue(ifaces.contains(Advised.class));
+ assertTrue(ifaces.contains(SpringProxy.class));
+ }
+
+ public void testCompleteProxiedInterfacesWorksWithNullOpaque() {
+ AdvisedSupport as = new AdvisedSupport();
+ as.setOpaque(true);
+ Class[] completedInterfaces = AopProxyUtils.completeProxiedInterfaces(as);
+ assertEquals(1, completedInterfaces.length);
+ }
+
+ public void testCompleteProxiedInterfacesAdvisedNotIncluded() {
+ AdvisedSupport as = new AdvisedSupport();
+ as.addInterface(ITestBean.class);
+ as.addInterface(Comparable.class);
+ Class[] completedInterfaces = AopProxyUtils.completeProxiedInterfaces(as);
+ assertEquals(4, completedInterfaces.length);
+
+ // Can't assume ordering for others, so use a list
+ List l = Arrays.asList(completedInterfaces);
+ assertTrue(l.contains(Advised.class));
+ assertTrue(l.contains(ITestBean.class));
+ assertTrue(l.contains(Comparable.class));
+ }
+
+ public void testCompleteProxiedInterfacesAdvisedIncluded() {
+ AdvisedSupport as = new AdvisedSupport();
+ as.addInterface(ITestBean.class);
+ as.addInterface(Comparable.class);
+ as.addInterface(Advised.class);
+ Class[] completedInterfaces = AopProxyUtils.completeProxiedInterfaces(as);
+ assertEquals(4, completedInterfaces.length);
+
+ // Can't assume ordering for others, so use a list
+ List l = Arrays.asList(completedInterfaces);
+ assertTrue(l.contains(Advised.class));
+ assertTrue(l.contains(ITestBean.class));
+ assertTrue(l.contains(Comparable.class));
+ }
+
+ public void testCompleteProxiedInterfacesAdvisedNotIncludedOpaque() {
+ AdvisedSupport as = new AdvisedSupport();
+ as.setOpaque(true);
+ as.addInterface(ITestBean.class);
+ as.addInterface(Comparable.class);
+ Class[] completedInterfaces = AopProxyUtils.completeProxiedInterfaces(as);
+ assertEquals(3, completedInterfaces.length);
+
+ // Can't assume ordering for others, so use a list
+ List l = Arrays.asList(completedInterfaces);
+ assertFalse(l.contains(Advised.class));
+ assertTrue(l.contains(ITestBean.class));
+ assertTrue(l.contains(Comparable.class));
+ }
+
+ public void testProxiedUserInterfacesWithSingleInterface() {
+ ProxyFactory pf = new ProxyFactory();
+ pf.setTarget(new TestBean());
+ pf.addInterface(ITestBean.class);
+ Object proxy = pf.getProxy();
+ Class[] userInterfaces = AopProxyUtils.proxiedUserInterfaces(proxy);
+ assertEquals(1, userInterfaces.length);
+ assertEquals(ITestBean.class, userInterfaces[0]);
+ }
+
+ public void testProxiedUserInterfacesWithMultipleInterfaces() {
+ ProxyFactory pf = new ProxyFactory();
+ pf.setTarget(new TestBean());
+ pf.addInterface(ITestBean.class);
+ pf.addInterface(Comparable.class);
+ Object proxy = pf.getProxy();
+ Class[] userInterfaces = AopProxyUtils.proxiedUserInterfaces(proxy);
+ assertEquals(2, userInterfaces.length);
+ assertEquals(ITestBean.class, userInterfaces[0]);
+ assertEquals(Comparable.class, userInterfaces[1]);
+ }
+
+ public void testProxiedUserInterfacesWithNoInterface() {
+ Object proxy = Proxy.newProxyInstance(getClass().getClassLoader(), new Class[0],
+ new InvocationHandler() {
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ return null;
+ }
+ });
+ try {
+ Class[] userInterfaces = AopProxyUtils.proxiedUserInterfaces(proxy);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/CglibProxyTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/CglibProxyTests.java
new file mode 100644
index 00000000000..13c9a8f8b0b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/CglibProxyTests.java
@@ -0,0 +1,411 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+import java.io.Serializable;
+import java.lang.reflect.Modifier;
+
+import net.sf.cglib.core.CodeGenerationException;
+import org.aopalliance.intercept.MethodInterceptor;
+
+import org.springframework.aop.ClassFilter;
+import org.springframework.aop.MethodMatcher;
+import org.springframework.aop.Pointcut;
+import org.springframework.aop.interceptor.NopInterceptor;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.aop.support.DefaultPointcutAdvisor;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextException;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * Additional and overridden tests for the CGLIB proxy.
+ *
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @author Rob Harrop
+ * @author Ramnivas Laddad
+ */
+public class CglibProxyTests extends AbstractAopProxyTests {
+
+ protected Object createProxy(ProxyCreatorSupport as) {
+ as.setProxyTargetClass(true);
+ Object proxy = as.createAopProxy().getProxy();
+ assertTrue(AopUtils.isCglibProxy(proxy));
+ return proxy;
+ }
+
+ protected AopProxy createAopProxy(AdvisedSupport as) {
+ as.setProxyTargetClass(true);
+ return new Cglib2AopProxy(as);
+ }
+
+ protected boolean requiresTarget() {
+ return true;
+ }
+
+ public void testNullConfig() {
+ try {
+ AopProxy aop = new Cglib2AopProxy(null);
+ fail("Shouldn't allow null interceptors");
+ }
+ catch (IllegalArgumentException ex) {
+ // Ok
+ }
+ }
+
+ public void testNoTarget() {
+ AdvisedSupport pc = new AdvisedSupport(new Class[]{ITestBean.class});
+ pc.addAdvice(new NopInterceptor());
+ try {
+ AopProxy aop = createAopProxy(pc);
+ aop.getProxy();
+ fail("Shouldn't allow no target with CGLIB proxy");
+ }
+ catch (AopConfigException ex) {
+ // Ok
+ }
+ }
+
+ public void testProtectedMethodInvocation() {
+ ProtectedMethodTestBean bean = new ProtectedMethodTestBean();
+ mockTargetSource.setTarget(bean);
+
+ AdvisedSupport as = new AdvisedSupport(new Class[]{});
+ as.setTargetSource(mockTargetSource);
+ as.addAdvice(new NopInterceptor());
+ AopProxy aop = new Cglib2AopProxy(as);
+
+ Object proxy = aop.getProxy();
+ assertTrue(AopUtils.isCglibProxy(proxy));
+ }
+
+ public void testProxyCanBeClassNotInterface() throws Exception {
+ TestBean raw = new TestBean();
+ raw.setAge(32);
+ mockTargetSource.setTarget(raw);
+ AdvisedSupport pc = new AdvisedSupport();
+ pc.setTargetSource(mockTargetSource);
+ AopProxy aop = new Cglib2AopProxy(pc);
+
+ Object proxy = aop.getProxy();
+ assertTrue(AopUtils.isCglibProxy(proxy));
+ assertTrue(proxy instanceof ITestBean);
+ assertTrue(proxy instanceof TestBean);
+
+ TestBean tb = (TestBean) proxy;
+ assertEquals(32, tb.getAge());
+ }
+
+ public void testCglibProxyingGivesMeaningfulExceptionIfAskedToProxyNonvisibleClass() {
+ class YouCantSeeThis {
+ void hidden() {
+ }
+ }
+ YouCantSeeThis mine = new YouCantSeeThis();
+ try {
+ ProxyFactory pf = new ProxyFactory(mine);
+ pf.getProxy();
+ fail("Shouldn't be able to proxy non-visible class with CGLIB");
+ }
+ catch (AopConfigException ex) {
+ // Check that stack trace is preserved
+ assertTrue(ex.getCause() instanceof CodeGenerationException ||
+ ex.getCause() instanceof IllegalArgumentException);
+ // Check that error message is helpful
+ assertTrue(ex.getMessage().indexOf("final") != -1);
+ assertTrue(ex.getMessage().indexOf("visible") != -1);
+ }
+ }
+
+ public void testMethodInvocationDuringConstructor() {
+ CglibTestBean bean = new CglibTestBean();
+ bean.setName("Rob Harrop");
+
+ AdvisedSupport as = new AdvisedSupport(new Class[]{});
+ as.setTarget(bean);
+ as.addAdvice(new NopInterceptor());
+ AopProxy aop = new Cglib2AopProxy(as);
+
+ CglibTestBean proxy = (CglibTestBean) aop.getProxy();
+
+ assertEquals("The name property has been overwritten by the constructor",
+ "Rob Harrop", proxy.getName());
+ }
+
+ public void testUnadvisedProxyCreationWithCallDuringConstructor() throws Exception {
+ CglibTestBean target = new CglibTestBean();
+ target.setName("Rob Harrop");
+
+ AdvisedSupport pc = new AdvisedSupport(new Class[]{});
+ pc.setFrozen(true);
+ pc.setTarget(target);
+
+ Cglib2AopProxy aop = new Cglib2AopProxy(pc);
+
+ CglibTestBean proxy = (CglibTestBean) aop.getProxy();
+
+ assertNotNull("Proxy should not be null", proxy);
+ assertEquals("Constructor overrode the value of name", "Rob Harrop", proxy.getName());
+
+ }
+
+ public void testMultipleProxies() {
+ TestBean target = new TestBean();
+ target.setAge(20);
+ TestBean target2 = new TestBean();
+ target2.setAge(21);
+
+ ITestBean proxy1 = getAdvisedProxy(target);
+ ITestBean proxy2 = getAdvisedProxy(target2);
+ assertTrue(proxy1.getClass() == proxy2.getClass());
+ assertEquals(target.getAge(), proxy1.getAge());
+ assertEquals(target2.getAge(), proxy2.getAge());
+ }
+
+ private ITestBean getAdvisedProxy(TestBean target) {
+ ProxyFactory pf = new ProxyFactory(new Class[]{ITestBean.class});
+ pf.setProxyTargetClass(true);
+
+ MethodInterceptor advice = new NopInterceptor();
+ Pointcut pointcut = new Pointcut() {
+ public ClassFilter getClassFilter() {
+ return ClassFilter.TRUE;
+ }
+
+ public MethodMatcher getMethodMatcher() {
+ return MethodMatcher.TRUE;
+ }
+
+ public boolean equals(Object obj) {
+ return true;
+ }
+ };
+ pf.addAdvisor(new DefaultPointcutAdvisor(pointcut, advice));
+
+ pf.setTarget(target);
+ pf.setFrozen(true);
+ pf.setExposeProxy(false);
+
+ return (ITestBean) pf.getProxy();
+ }
+
+ public void testMultipleProxiesForIntroductionAdvisor() {
+ TestBean target = new TestBean();
+ target.setAge(20);
+ TestBean target2 = new TestBean();
+ target2.setAge(21);
+
+ ITestBean proxy1 = getIntroductionAdvisorProxy(target);
+ ITestBean proxy2 = getIntroductionAdvisorProxy(target2);
+ assertTrue("Incorrect duplicate creation of proxy classes", proxy1.getClass() == proxy2.getClass());
+ }
+
+ private ITestBean getIntroductionAdvisorProxy(TestBean target) {
+ ProxyFactory pf = new ProxyFactory(new Class[]{ITestBean.class});
+ pf.setProxyTargetClass(true);
+
+ pf.addAdvisor(new LockMixinAdvisor());
+ pf.setTarget(target);
+ pf.setFrozen(true);
+ pf.setExposeProxy(false);
+
+ return (ITestBean) pf.getProxy();
+ }
+
+ public void testWithNoArgConstructor() {
+ NoArgCtorTestBean target = new NoArgCtorTestBean("b", 1);
+ target.reset();
+
+ mockTargetSource.setTarget(target);
+ AdvisedSupport pc = new AdvisedSupport(new Class[]{});
+ pc.setTargetSource(mockTargetSource);
+ Cglib2AopProxy aop = new Cglib2AopProxy(pc);
+ aop.setConstructorArguments(new Object[] {"Rob Harrop", new Integer(22)},
+ new Class[] {String.class, int.class});
+
+ NoArgCtorTestBean proxy = (NoArgCtorTestBean) aop.getProxy();
+ proxy = (NoArgCtorTestBean) aop.getProxy();
+
+ assertNotNull("Proxy should be null", proxy);
+ }
+
+ public void testProxyAProxy() {
+ ITestBean target = new TestBean();
+
+ mockTargetSource.setTarget(target);
+ AdvisedSupport as = new AdvisedSupport(new Class[]{});
+ as.setTargetSource(mockTargetSource);
+ as.addAdvice(new NopInterceptor());
+ Cglib2AopProxy cglib = new Cglib2AopProxy(as);
+
+ ITestBean proxy1 = (ITestBean) cglib.getProxy();
+
+ mockTargetSource.setTarget(proxy1);
+ as = new AdvisedSupport(new Class[]{});
+ as.setTargetSource(mockTargetSource);
+ as.addAdvice(new NopInterceptor());
+ cglib = new Cglib2AopProxy(as);
+
+ ITestBean proxy2 = (ITestBean) cglib.getProxy();
+ }
+
+ public void testProxyAProxyWithAdditionalInterface() {
+ ITestBean target = new TestBean();
+ mockTargetSource.setTarget(target);
+
+ AdvisedSupport as = new AdvisedSupport(new Class[]{});
+ as.setTargetSource(mockTargetSource);
+ as.addAdvice(new NopInterceptor());
+ as.addInterface(Serializable.class);
+ Cglib2AopProxy cglib = new Cglib2AopProxy(as);
+
+ ITestBean proxy1 = (ITestBean) cglib.getProxy();
+
+ mockTargetSource.setTarget(proxy1);
+ as = new AdvisedSupport(new Class[]{});
+ as.setTargetSource(mockTargetSource);
+ as.addAdvice(new NopInterceptor());
+ cglib = new Cglib2AopProxy(as);
+
+ ITestBean proxy2 = (ITestBean) cglib.getProxy();
+ assertTrue(proxy2 instanceof Serializable);
+ }
+
+ public void testExceptionHandling() {
+ ExceptionThrower bean = new ExceptionThrower();
+ mockTargetSource.setTarget(bean);
+
+ AdvisedSupport as = new AdvisedSupport(new Class[]{});
+ as.setTargetSource(mockTargetSource);
+ as.addAdvice(new NopInterceptor());
+ AopProxy aop = new Cglib2AopProxy(as);
+
+ ExceptionThrower proxy = (ExceptionThrower) aop.getProxy();
+
+ try {
+ proxy.doTest();
+ }
+ catch (Exception ex) {
+ assertTrue("Invalid exception class", ex instanceof ApplicationContextException);
+ }
+
+ assertTrue("Catch was not invoked", proxy.isCatchInvoked());
+ assertTrue("Finally was not invoked", proxy.isFinallyInvoked());
+ }
+
+ public void testWithDependencyChecking() {
+ ApplicationContext ctx =
+ new ClassPathXmlApplicationContext("org/springframework/aop/framework/withDependencyChecking.xml");
+ ctx.getBean("testBean");
+ }
+
+ public void testAddAdviceAtRuntime() {
+ TestBean bean = new TestBean();
+
+ CountingBeforeAdvice cba = new CountingBeforeAdvice();
+
+ ProxyFactory pf = new ProxyFactory();
+ pf.setTarget(bean);
+ pf.setFrozen(false);
+ pf.setOpaque(false);
+ pf.setProxyTargetClass(true);
+
+ TestBean proxy = (TestBean) pf.getProxy();
+
+ assertTrue(AopUtils.isCglibProxy(proxy));
+
+ proxy.getAge();
+
+ assertEquals(0, cba.getCalls());
+
+ ((Advised) proxy).addAdvice(cba);
+
+ proxy.getAge();
+
+ assertEquals(1, cba.getCalls());
+ }
+
+ public void testProxyProtectedMethod() throws Exception {
+ CountingBeforeAdvice advice = new CountingBeforeAdvice();
+ ProxyFactory proxyFactory = new ProxyFactory(new MyBean());
+ proxyFactory.addAdvice(advice);
+ proxyFactory.setProxyTargetClass(true);
+
+ MyBean proxy = (MyBean) proxyFactory.getProxy();
+
+ assertEquals(4, proxy.add(1, 3));
+ assertEquals(1, advice.getCalls("add"));
+ }
+
+
+ public static class MyBean {
+
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ protected int add(int x, int y) {
+ return x + y;
+ }
+ }
+
+
+ public static class ExceptionThrower {
+
+ private boolean catchInvoked;
+
+ private boolean finallyInvoked;
+
+ public boolean isCatchInvoked() {
+ return catchInvoked;
+ }
+
+ public boolean isFinallyInvoked() {
+ return finallyInvoked;
+ }
+
+ public void doTest() throws Exception {
+ try {
+ throw new ApplicationContextException("foo");
+ }
+ catch (Exception ex) {
+ catchInvoked = true;
+ throw ex;
+ }
+ finally {
+ finallyInvoked = true;
+ }
+ }
+ }
+
+
+ public static class HasFinalMethod {
+
+ public final void foo() {
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/CglibTestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/CglibTestBean.java
new file mode 100644
index 00000000000..690e8b097f5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/CglibTestBean.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+/**
+ * @author Rob Harrop
+ */
+public class CglibTestBean {
+
+ private String name;
+
+ public CglibTestBean() {
+ setName("Some Default");
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/CountingAfterReturningAdvice.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/CountingAfterReturningAdvice.java
new file mode 100644
index 00000000000..d59f74800bd
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/CountingAfterReturningAdvice.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+import java.lang.reflect.Method;
+
+import org.springframework.aop.AfterReturningAdvice;
+
+/**
+ * Simple before advice example that we can use for counting checks.
+ *
+ * @author Rod Johnson
+ */
+public class CountingAfterReturningAdvice extends MethodCounter implements AfterReturningAdvice {
+
+ public void afterReturning(Object o, Method m, Object[] args, Object target) throws Throwable {
+ count(m);
+ }
+
+}
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/CountingBeforeAdvice.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/CountingBeforeAdvice.java
new file mode 100644
index 00000000000..3f391b2c68c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/CountingBeforeAdvice.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+import java.lang.reflect.Method;
+
+import org.springframework.aop.MethodBeforeAdvice;
+
+/**
+ * Simple before advice example that we can use for counting checks.
+ *
+ * @author Rod Johnson
+ */
+public class CountingBeforeAdvice extends MethodCounter implements MethodBeforeAdvice {
+
+ public void before(Method m, Object[] args, Object target) throws Throwable {
+ count(m);
+ }
+
+}
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/CountingMultiAdvice.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/CountingMultiAdvice.java
new file mode 100644
index 00000000000..2b27d2e7907
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/CountingMultiAdvice.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+import java.lang.reflect.Method;
+
+import javax.servlet.ServletException;
+
+import org.springframework.aop.AfterReturningAdvice;
+import org.springframework.aop.MethodBeforeAdvice;
+import org.springframework.aop.ThrowsAdvice;
+import org.springframework.dao.DataAccessException;
+
+/**
+ * Advice object that implements multiple Advice interfaces.
+ *
+ * @author Juergen Hoeller
+ * @since 19.05.2005
+ */
+public class CountingMultiAdvice extends MethodCounter
+ implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice {
+
+ public void before(Method m, Object[] args, Object target) throws Throwable {
+ count(m);
+ }
+
+ public void afterReturning(Object o, Method m, Object[] args, Object target) throws Throwable {
+ count(m);
+ }
+
+ public void afterThrowing(ServletException sex) throws Throwable {
+ count(ServletException.class.getName());
+ }
+
+ public void afterThrowing(DataAccessException ex) throws Throwable {
+ count(DataAccessException.class.getName());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/CountingThrowsAdvice.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/CountingThrowsAdvice.java
new file mode 100644
index 00000000000..b17153124f0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/CountingThrowsAdvice.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+import javax.servlet.ServletException;
+
+import org.springframework.aop.ThrowsAdvice;
+import org.springframework.dao.DataAccessException;
+
+/**
+ * @author Rod Johnson
+ */
+public class CountingThrowsAdvice extends MethodCounter implements ThrowsAdvice {
+
+ public void afterThrowing(ServletException sex) throws Throwable {
+ count(ServletException.class.getName());
+ }
+
+ public void afterThrowing(DataAccessException ex) throws Throwable {
+ count(DataAccessException.class.getName());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/DefaultLockable.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/DefaultLockable.java
new file mode 100644
index 00000000000..a7b4d48b39d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/DefaultLockable.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+/**
+ * Simple implementation of Lockable interface for use in mixins.
+ *
+ * @author Rod Johnson
+ */
+public class DefaultLockable implements Lockable {
+
+ private boolean locked;
+
+ public void lock() {
+ this.locked = true;
+ }
+
+ public void unlock() {
+ this.locked = false;
+ }
+
+ public boolean locked() {
+ return this.locked;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/ExposedInvocationTestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/ExposedInvocationTestBean.java
new file mode 100644
index 00000000000..83f56173791
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/ExposedInvocationTestBean.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+import org.aopalliance.intercept.MethodInvocation;
+import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
+import org.springframework.beans.TestBean;
+
+
+/**
+ * Used to test ExposeInvocationInterceptor.
+ * @author Rod Johnson
+ */
+public abstract class ExposedInvocationTestBean extends TestBean {
+
+ public String getName() {
+ MethodInvocation invocation = ExposeInvocationInterceptor.currentInvocation();
+ assertions(invocation);
+ return super.getName();
+ }
+
+ public void absquatulate() {
+ MethodInvocation invocation = ExposeInvocationInterceptor.currentInvocation();
+ assertions(invocation);
+ super.absquatulate();
+ }
+
+ protected abstract void assertions(MethodInvocation invocation);
+}
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/IntroductionBenchmarkTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/IntroductionBenchmarkTests.java
new file mode 100644
index 00000000000..d3383ab8f7b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/IntroductionBenchmarkTests.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.support.DelegatingIntroductionInterceptor;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.util.StopWatch;
+
+/**
+ * Benchmarks for introductions.
+ *
+ * @author Rod Johnson
+ * @since 2.0
+ */
+public class IntroductionBenchmarkTests extends TestCase {
+
+ private static final int EXPECTED_COMPARE = 13;
+
+ /** Increase this if you want meaningful results! */
+ private static final int INVOCATIONS = 100000;
+
+
+ public void testBenchmarks() {
+ timeManyInvocations();
+ }
+
+ public static class SimpleCounterIntroduction extends DelegatingIntroductionInterceptor implements Counter {
+
+ public int getCount() {
+ return EXPECTED_COMPARE;
+ }
+ }
+
+ public static interface Counter {
+ int getCount();
+ }
+
+ protected long timeManyInvocations() {
+ StopWatch sw = new StopWatch();
+
+ TestBean target = new TestBean();
+ ProxyFactory pf = new ProxyFactory(target);
+ pf.setProxyTargetClass(false);
+ pf.addAdvice(new SimpleCounterIntroduction());
+ ITestBean proxy = (ITestBean) pf.getProxy();
+
+ Counter counter = (Counter) proxy;
+
+ sw.start(INVOCATIONS + " invocations on proxy, not hitting introduction");
+ for (int i = 0; i < INVOCATIONS; i++) {
+ proxy.getAge();
+ }
+ sw.stop();
+
+ sw.start(INVOCATIONS + " invocations on proxy, hitting introduction");
+ for (int i = 0; i < INVOCATIONS; i++) {
+ counter.getCount();
+ }
+ sw.stop();
+
+ sw.start(INVOCATIONS + " invocations on target");
+ for (int i = 0; i < INVOCATIONS; i++) {
+ target.getAge();
+ }
+ sw.stop();
+
+ System.out.println(sw.prettyPrint());
+ return sw.getLastTaskTimeMillis();
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/InvocationCheckExposedInvocationTestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/InvocationCheckExposedInvocationTestBean.java
new file mode 100644
index 00000000000..7f6b3115469
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/InvocationCheckExposedInvocationTestBean.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+import junit.framework.TestCase;
+
+import org.aopalliance.intercept.MethodInvocation;
+import org.springframework.beans.ITestBean;
+
+
+/**
+ *
+ */
+public class InvocationCheckExposedInvocationTestBean extends ExposedInvocationTestBean {
+ protected void assertions(MethodInvocation invocation) {
+ TestCase.assertTrue(invocation.getThis() == this);
+ TestCase.assertTrue("Invocation should be on ITestBean: " + invocation.getMethod(),
+ ITestBean.class.isAssignableFrom(invocation.getMethod().getDeclaringClass()));
+ }
+}
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/JdkDynamicProxyTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/JdkDynamicProxyTests.java
new file mode 100644
index 00000000000..a82ffa85b6e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/JdkDynamicProxyTests.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+import org.easymock.MockControl;
+
+import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.beans.IOther;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @since 13.03.2003
+ */
+public class JdkDynamicProxyTests extends AbstractAopProxyTests {
+
+ protected Object createProxy(ProxyCreatorSupport as) {
+ assertFalse("Not forcible CGLIB", as.isProxyTargetClass());
+ Object proxy = as.createAopProxy().getProxy();
+ assertTrue("Should be a JDK proxy: " + proxy.getClass(), AopUtils.isJdkDynamicProxy(proxy));
+ return proxy;
+ }
+
+ protected AopProxy createAopProxy(AdvisedSupport as) {
+ return new JdkDynamicAopProxy(as);
+ }
+
+ public void testNullConfig() {
+ try {
+ JdkDynamicAopProxy aop = new JdkDynamicAopProxy(null);
+ fail("Shouldn't allow null interceptors");
+ }
+ catch (IllegalArgumentException ex) {
+ // Ok
+ }
+ }
+
+ public void testProxyIsJustInterface() throws Throwable {
+ TestBean raw = new TestBean();
+ raw.setAge(32);
+ AdvisedSupport pc = new AdvisedSupport(new Class[] {ITestBean.class});
+ pc.setTarget(raw);
+ JdkDynamicAopProxy aop = new JdkDynamicAopProxy(pc);
+
+ Object proxy = aop.getProxy();
+ assertTrue(proxy instanceof ITestBean);
+ assertTrue(!(proxy instanceof TestBean));
+ }
+
+ public void testInterceptorIsInvokedWithNoTarget() throws Throwable {
+ // Test return value
+ int age = 25;
+ MockControl miControl = MockControl.createControl(MethodInterceptor.class);
+ MethodInterceptor mi = (MethodInterceptor) miControl.getMock();
+
+ AdvisedSupport pc = new AdvisedSupport(new Class[] { ITestBean.class });
+ pc.addAdvice(mi);
+ AopProxy aop = createAopProxy(pc);
+
+ // Really would like to permit null arg:can't get exact mi
+ mi.invoke(null);
+ //mi.invoke(new MethodInvocationImpl(aop, null, ITestBean.class,
+ // ITestBean.class.getMethod("getAge", null),
+ // null, l, r));
+ //miControl.
+ //miControl.setReturnValue(new Integer(age));
+ // Have disabled strong argument checking
+ miControl.setDefaultReturnValue(new Integer(age));
+ miControl.replay();
+
+ ITestBean tb = (ITestBean) aop.getProxy();
+ assertTrue("correct return value", tb.getAge() == age);
+ miControl.verify();
+ }
+
+ public void testTargetCanGetInvocationWithPrivateClass() throws Throwable {
+ final ExposedInvocationTestBean expectedTarget = new ExposedInvocationTestBean() {
+ protected void assertions(MethodInvocation invocation) {
+ assertTrue(invocation.getThis() == this);
+ assertTrue("Invocation should be on ITestBean: " + invocation.getMethod(),
+ invocation.getMethod().getDeclaringClass() == ITestBean.class);
+ }
+ };
+
+ AdvisedSupport pc = new AdvisedSupport(new Class[] { ITestBean.class, IOther.class });
+ pc.addAdvice(ExposeInvocationInterceptor.INSTANCE);
+ TrapTargetInterceptor tii = new TrapTargetInterceptor() {
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ // Assert that target matches BEFORE invocation returns
+ assertEquals("Target is correct", expectedTarget, invocation.getThis());
+ return super.invoke(invocation);
+ }
+ };
+ pc.addAdvice(tii);
+ pc.setTarget(expectedTarget);
+ AopProxy aop = createAopProxy(pc);
+
+ ITestBean tb = (ITestBean) aop.getProxy();
+ tb.getName();
+ // Not safe to trap invocation
+ //assertTrue(tii.invocation == target.invocation);
+
+ //assertTrue(target.invocation.getProxy() == tb);
+
+ // ((IOther) tb).absquatulate();
+ //MethodInvocation minv = tii.invocation;
+ //assertTrue("invoked on iother, not " + minv.getMethod().getDeclaringClass(), minv.getMethod().getDeclaringClass() == IOther.class);
+ //assertTrue(target.invocation == tii.invocation);
+ }
+
+ public void testProxyNotWrappedIfIncompatible() {
+ FooBar bean = new FooBar();
+ ProxyCreatorSupport as = new ProxyCreatorSupport();
+ as.setInterfaces(new Class[] {Foo.class});
+ as.setTarget(bean);
+
+ Foo proxy = (Foo) createProxy(as);
+ assertSame("Target should be returned when return types are incompatible", bean, proxy.getBarThis());
+ assertSame("Proxy should be returned when return types are compatible", proxy, proxy.getFooThis());
+
+ }
+
+ public void testEqualsAndHashCodeDefined() throws Exception {
+ AdvisedSupport as = new AdvisedSupport(new Class[]{Named.class});
+ as.setTarget(new Person());
+ JdkDynamicAopProxy aopProxy = new JdkDynamicAopProxy(as);
+ Named proxy = (Named) aopProxy.getProxy();
+ Named named = new Person();
+ assertEquals("equals() returned false", proxy, named);
+ assertEquals("hashCode() not equal", proxy.hashCode(), named.hashCode());
+ }
+
+
+ public static interface Foo {
+
+ Bar getBarThis();
+
+ Foo getFooThis();
+ }
+
+
+ public static interface Bar {
+
+ }
+
+
+ public static class FooBar implements Foo, Bar {
+
+ public Bar getBarThis() {
+ return this;
+ }
+
+ public Foo getFooThis() {
+ return this;
+ }
+ }
+
+
+ public static interface Named {
+
+ String getName();
+
+ boolean equals(Object other);
+
+ int hashCode();
+ }
+
+
+ public static class Person implements Named {
+
+ private final String name = "Rob Harrop";
+
+ public String getName() {
+ return this.name;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final Person person = (Person) o;
+
+ if (!name.equals(person.name)) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ return name.hashCode();
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/LockMixin.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/LockMixin.java
new file mode 100644
index 00000000000..635588aaaa1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/LockMixin.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+import org.aopalliance.intercept.MethodInvocation;
+import org.springframework.aop.support.DelegatingIntroductionInterceptor;
+
+
+/**
+ * Mixin to provide stateful locking functionality.
+ * Test/demonstration of AOP mixin support rather than a
+ * useful interceptor in its own right.
+ *
+ * @author Rod Johnson
+ * @since 10.07.2003
+ */
+public class LockMixin extends DelegatingIntroductionInterceptor implements Lockable {
+
+ /** This field demonstrates additional state in the mixin */
+ private boolean locked;
+
+ public void lock() {
+ this.locked = true;
+ }
+
+ public void unlock() {
+ this.locked = false;
+ }
+
+ /**
+ * @see org.springframework.aop.framework.AopProxyTests.Lockable#locked()
+ */
+ public boolean locked() {
+ return this.locked;
+ }
+
+ /**
+ * Note that we need to override around advice.
+ * If the method is a setter and we're locked, prevent execution.
+ * Otherwise let super.invoke() handle it, and do normal
+ * Lockable(this) then target behaviour.
+ * @see org.aopalliance.MethodInterceptor#invoke(org.aopalliance.MethodInvocation)
+ */
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ if (locked() && invocation.getMethod().getName().indexOf("set") == 0)
+ throw new LockedException();
+ return super.invoke(invocation);
+ }
+
+}
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/LockMixinAdvisor.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/LockMixinAdvisor.java
new file mode 100644
index 00000000000..a3b600cc739
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/LockMixinAdvisor.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+import org.springframework.aop.support.DefaultIntroductionAdvisor;
+
+/**
+ * Advisor for use with a LockMixin. Applies to all classes.
+ *
+ * @author Rod Johnson
+ */
+public class LockMixinAdvisor extends DefaultIntroductionAdvisor {
+
+ public LockMixinAdvisor() {
+ super(new LockMixin(), Lockable.class);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/Lockable.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/Lockable.java
new file mode 100644
index 00000000000..70d6b2cfa5f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/Lockable.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+
+/**
+ * Simple interface to use for mixins
+ *
+ * @author Rod Johnson
+ *
+ */
+public interface Lockable {
+
+ void lock();
+
+ void unlock();
+
+ boolean locked();
+}
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/LockedException.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/LockedException.java
new file mode 100644
index 00000000000..cbea82f2a28
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/LockedException.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+
+public class LockedException extends RuntimeException {
+
+ public LockedException() {
+ }
+}
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/MethodCounter.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/MethodCounter.java
new file mode 100644
index 00000000000..d3030ffe8e0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/MethodCounter.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+
+/**
+ * Useful abstract superclass for counting advices etc.
+ *
+ * @author Rod Johnson
+ */
+public class MethodCounter implements Serializable {
+
+ /** Method name --> count, does not understand overloading */
+ private HashMap map = new HashMap();
+
+ private int allCount;
+
+ protected void count(Method m) {
+ count(m.getName());
+ }
+
+ protected void count(String methodName) {
+ Integer i = (Integer) map.get(methodName);
+ i = (i != null) ? new Integer(i.intValue() + 1) : new Integer(1);
+ map.put(methodName, i);
+ ++allCount;
+ }
+
+ public int getCalls(String methodName) {
+ Integer i = (Integer) map.get(methodName);
+ return (i != null ? i.intValue() : 0);
+ }
+
+ public int getCalls() {
+ return allCount;
+ }
+
+ /**
+ * A bit simplistic: just wants the same class.
+ * Doesn't worry about counts.
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object other) {
+ return (other != null && other.getClass() == this.getClass());
+ }
+
+ public int hashCode() {
+ return getClass().hashCode();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/MethodInvocationTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/MethodInvocationTests.java
new file mode 100644
index 00000000000..45d3f970e50
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/MethodInvocationTests.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+import java.lang.reflect.Method;
+import java.util.LinkedList;
+import java.util.List;
+
+import junit.framework.TestCase;
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+import org.springframework.beans.TestBean;
+
+/**
+ * TODO: could refactor to be generic.
+ * @author Rod Johnson
+ * @since 14.03.2003
+ */
+public class MethodInvocationTests extends TestCase {
+
+ /*
+ public static MethodInvocation testInvocation(Object o, String methodName, Class[] args, Interceptor[] interceptors) throws Exception {
+ Method m = o.getClass().getMethod(methodName, args);
+ MethodInvocationImpl invocation = new MethodInvocationImpl(null, null, m.getDeclaringClass(),
+ m, null, interceptors, // list
+ new Attrib4jAttributeRegistry());
+ return invocation;
+ }*/
+
+ /*
+ public void testNullInterceptor() throws Exception {
+ Method m = Object.class.getMethod("hashCode", null);
+ Object proxy = new Object();
+ try {
+ MethodInvocationImpl invocation = new MethodInvocationImpl(proxy, null, m.getDeclaringClass(), //?
+ m, null, null // could customize here
+ );
+ fail("Shouldn't be able to create methodInvocationImpl with null interceptors");
+ } catch (AopConfigException ex) {
+ }
+ }
+
+ public void testEmptyInterceptorList() throws Exception {
+ Method m = Object.class.getMethod("hashCode", null);
+ Object proxy = new Object();
+ try {
+ MethodInvocationImpl invocation = new MethodInvocationImpl(proxy, null, m.getDeclaringClass(), //?
+ m, null, new LinkedList() // list
+ );
+ fail("Shouldn't be able to create methodInvocationImpl with no interceptors");
+ } catch (AopConfigException ex) {
+ }
+ }
+ */
+
+ public void testValidInvocation() throws Throwable {
+ Method m = Object.class.getMethod("hashCode", (Class[]) null);
+ Object proxy = new Object();
+ final Object returnValue = new Object();
+ List is = new LinkedList();
+ is.add(new MethodInterceptor() {
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ return returnValue;
+ }
+ });
+ ReflectiveMethodInvocation invocation = new ReflectiveMethodInvocation(proxy, null, //?
+ m, null, null, is // list
+ );
+ Object rv = invocation.proceed();
+ assertTrue("correct response", rv == returnValue);
+ }
+
+ /**
+ * ToString on target can cause failure.
+ */
+ public void testToStringDoesntHitTarget() throws Throwable {
+ Object target = new TestBean() {
+ public String toString() {
+ throw new UnsupportedOperationException("toString");
+ }
+ };
+ final Object returnValue = new Object();
+ List is = new LinkedList();
+
+ Method m = Object.class.getMethod("hashCode", (Class[]) null);
+ Object proxy = new Object();
+ ReflectiveMethodInvocation invocation =
+ new ReflectiveMethodInvocation(proxy, target, m, null, null, is);
+
+ // If it hits target, the test will fail with the UnsupportedOpException
+ // in the inner class above.
+ invocation.toString();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/MethodVisibilities.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/MethodVisibilities.java
new file mode 100644
index 00000000000..ad6b83463e1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/MethodVisibilities.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+/**
+ * Test for different method visibilities to
+ * test AOP proxying capabilities
+ * @author Rod Johnson
+ */
+public class MethodVisibilities {
+
+ public String publicMethod(String s) {
+ return s;
+ }
+
+ protected String protectedMethod(String s) {
+ return s;
+ }
+
+ private String privateMethod(String s) {
+ return s;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/MockTargetSource.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/MockTargetSource.java
new file mode 100644
index 00000000000..c2761d8492a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/MockTargetSource.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+import org.springframework.aop.TargetSource;
+
+/**
+ *
+ * @author Rod Johnson
+ */
+public class MockTargetSource implements TargetSource {
+
+ private Object target;
+
+ public int gets;
+
+ public int releases;
+
+ public void reset() {
+ this.target = null;
+ gets = releases = 0;
+ }
+
+ public void setTarget(Object target) {
+ this.target = target;
+ }
+
+ /**
+ * @see org.springframework.aop.TargetSource#getTargetClass()
+ */
+ public Class getTargetClass() {
+ return target.getClass();
+ }
+
+ /**
+ * @see org.springframework.aop.TargetSource#getTarget()
+ */
+ public Object getTarget() throws Exception {
+ ++gets;
+ return target;
+ }
+
+ /**
+ * @see org.springframework.aop.TargetSource#releaseTarget(java.lang.Object)
+ */
+ public void releaseTarget(Object pTarget) throws Exception {
+ if (pTarget != this.target)
+ throw new RuntimeException("Released wrong target");
+ ++releases;
+ }
+
+ /**
+ * Check that gets and releases match
+ *
+ */
+ public void verify() {
+ if (gets != releases)
+ throw new RuntimeException("Expectation failed: " + gets + " gets and " + releases + " releases");
+ }
+
+ /**
+ * @see org.springframework.aop.TargetSource#isStatic()
+ */
+ public boolean isStatic() {
+ return false;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/NoArgCtorTestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/NoArgCtorTestBean.java
new file mode 100644
index 00000000000..e872f72d82d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/NoArgCtorTestBean.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+/**
+ * @author Rob Harrop
+ */
+public class NoArgCtorTestBean {
+
+ private boolean called = false;
+
+ public NoArgCtorTestBean(String x, int y) {
+ called = true;
+ }
+
+ public boolean wasCalled() {
+ return called;
+ }
+
+ public void reset() {
+ called = false;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/NoInterfaces.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/NoInterfaces.java
new file mode 100644
index 00000000000..603f14112d6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/NoInterfaces.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+/**
+ * Used for testing CGLIB proxying.
+ *
+ * @author Rod Johnson
+ */
+public class NoInterfaces {
+
+ private int age;
+
+ public int getAge() {
+ return age;
+ }
+ public void setAge(int age) {
+ this.age = age;
+ }
+}
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/NoInterfacesConstructor.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/NoInterfacesConstructor.java
new file mode 100644
index 00000000000..e13bf0c901c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/NoInterfacesConstructor.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+/**
+ *
+ * @author Rod Johnson
+ */
+public class NoInterfacesConstructor extends NoInterfaces {
+
+ public NoInterfacesConstructor(int age) {
+ setAge(age);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/ProtectedMethodTestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/ProtectedMethodTestBean.java
new file mode 100644
index 00000000000..e4f45fe50fe
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/ProtectedMethodTestBean.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+/**
+ * @author Rob Harrop
+ */
+public class ProtectedMethodTestBean {
+
+ protected String getString() {
+ return "foo";
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/PrototypeTargetTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/PrototypeTargetTests.java
new file mode 100644
index 00000000000..e8604759fd2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/PrototypeTargetTests.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+import junit.framework.TestCase;
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Juergen Hoeller
+ * @since 03.09.2004
+ */
+public class PrototypeTargetTests extends TestCase {
+
+ public void testPrototypeProxyWithPrototypeTarget() {
+ TestBeanImpl.constructionCount = 0;
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("prototypeTarget.xml", getClass()));
+ for (int i = 0; i < 10; i++) {
+ TestBean tb = (TestBean) xbf.getBean("testBeanPrototype");
+ tb.doSomething();
+ }
+ TestInterceptor interceptor = (TestInterceptor) xbf.getBean("testInterceptor");
+ assertEquals(10, TestBeanImpl.constructionCount);
+ assertEquals(10, interceptor.invocationCount);
+ }
+
+ public void testSingletonProxyWithPrototypeTarget() {
+ TestBeanImpl.constructionCount = 0;
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("prototypeTarget.xml", getClass()));
+ for (int i = 0; i < 10; i++) {
+ TestBean tb = (TestBean) xbf.getBean("testBeanSingleton");
+ tb.doSomething();
+ }
+ TestInterceptor interceptor = (TestInterceptor) xbf.getBean("testInterceptor");
+ assertEquals(1, TestBeanImpl.constructionCount);
+ assertEquals(10, interceptor.invocationCount);
+ }
+
+
+ public static interface TestBean {
+
+ public void doSomething();
+ }
+
+
+ public static class TestBeanImpl implements TestBean {
+
+ private static int constructionCount = 0;
+
+ public TestBeanImpl() {
+ constructionCount++;
+ }
+
+ public void doSomething() {
+ }
+ }
+
+
+ public static class TestInterceptor implements MethodInterceptor {
+
+ private int invocationCount = 0;
+
+ public Object invoke(MethodInvocation methodInvocation) throws Throwable {
+ invocationCount++;
+ return methodInvocation.proceed();
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/ProxyFactoryBeanTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/ProxyFactoryBeanTests.java
new file mode 100644
index 00000000000..6a037a26cd7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/ProxyFactoryBeanTests.java
@@ -0,0 +1,722 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.servlet.ServletException;
+
+import junit.framework.TestCase;
+import org.aopalliance.aop.Advice;
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+import org.springframework.aop.ClassFilter;
+import org.springframework.aop.IntroductionAdvisor;
+import org.springframework.aop.IntroductionInterceptor;
+import org.springframework.aop.framework.adapter.ThrowsAdviceInterceptorTests;
+import org.springframework.aop.interceptor.DebugInterceptor;
+import org.springframework.aop.interceptor.NopInterceptor;
+import org.springframework.aop.interceptor.SideEffectBean;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.aop.support.DefaultIntroductionAdvisor;
+import org.springframework.aop.support.DefaultPointcutAdvisor;
+import org.springframework.aop.support.DynamicMethodMatcherPointcut;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.Person;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.ListableBeanFactory;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.TestListener;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.util.SerializationTestUtils;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @since 13.03.2003
+ */
+public class ProxyFactoryBeanTests extends TestCase {
+
+ private BeanFactory factory;
+
+ protected void setUp() throws Exception {
+ DefaultListableBeanFactory parent = new DefaultListableBeanFactory();
+ parent.registerBeanDefinition("target2", new RootBeanDefinition(TestListener.class));
+ this.factory = new XmlBeanFactory(new ClassPathResource("proxyFactoryTests.xml", getClass()), parent);
+ }
+
+ public void testIsDynamicProxyWhenInterfaceSpecified() {
+ ITestBean test1 = (ITestBean) factory.getBean("test1");
+ assertTrue("test1 is a dynamic proxy", Proxy.isProxyClass(test1.getClass()));
+ }
+
+ public void testIsDynamicProxyWhenInterfaceSpecifiedForPrototype() {
+ ITestBean test1 = (ITestBean) factory.getBean("test2");
+ assertTrue("test2 is a dynamic proxy", Proxy.isProxyClass(test1.getClass()));
+ }
+
+ public void testIsDynamicProxyWhenAutodetectingInterfaces() {
+ ITestBean test1 = (ITestBean) factory.getBean("test3");
+ assertTrue("test3 is a dynamic proxy", Proxy.isProxyClass(test1.getClass()));
+ }
+
+ public void testIsDynamicProxyWhenAutodetectingInterfacesForPrototype() {
+ ITestBean test1 = (ITestBean) factory.getBean("test4");
+ assertTrue("test4 is a dynamic proxy", Proxy.isProxyClass(test1.getClass()));
+ }
+
+ /**
+ * Test that it's forbidden to specify TargetSource in both
+ * interceptor chain and targetSource property.
+ */
+ public void testDoubleTargetSourcesAreRejected() {
+ testDoubleTargetSourceIsRejected("doubleTarget");
+ // Now with conversion from arbitrary bean to a TargetSource
+ testDoubleTargetSourceIsRejected("arbitraryTarget");
+ }
+
+ private void testDoubleTargetSourceIsRejected(String name) {
+ try {
+ BeanFactory bf = new XmlBeanFactory(new ClassPathResource("proxyFactoryDoubleTargetSourceTests.xml", getClass()));
+ ITestBean tb = (ITestBean) bf.getBean(name);
+ //assertEquals("Adam", tb.getName());
+ fail("Should not allow TargetSource to be specified in interceptorNames as well as targetSource property");
+ }
+ catch (BeanCreationException ex) {
+ // Root cause of the problem must be an AOP exception
+ AopConfigException aex = (AopConfigException) ex.getCause();
+ assertTrue(aex.getMessage().indexOf("TargetSource") != -1);
+ }
+ }
+
+ public void testTargetSourceNotAtEndOfInterceptorNamesIsRejected() {
+ try {
+ BeanFactory bf = new XmlBeanFactory(new ClassPathResource("proxyFactoryTargetSourceNotLastTests.xml", getClass()));
+ bf.getBean("targetSourceNotLast");
+ fail("TargetSource or non-advised object must be last in interceptorNames");
+ }
+ catch (BeanCreationException ex) {
+ // Root cause of the problem must be an AOP exception
+ AopConfigException aex = (AopConfigException) ex.getCause();
+ assertTrue(aex.getMessage().indexOf("interceptorNames") != -1);
+ }
+ }
+
+ public void testGetObjectTypeWithDirectTarget() {
+ BeanFactory bf = new XmlBeanFactory(new ClassPathResource("proxyFactoryTargetSourceTests.xml", getClass()));
+
+ // We have a counting before advice here
+ CountingBeforeAdvice cba = (CountingBeforeAdvice) bf.getBean("countingBeforeAdvice");
+ assertEquals(0, cba.getCalls());
+
+ ITestBean tb = (ITestBean) bf.getBean("directTarget");
+ assertTrue(tb.getName().equals("Adam"));
+ assertEquals(1, cba.getCalls());
+
+ ProxyFactoryBean pfb = (ProxyFactoryBean) bf.getBean("&directTarget");
+ assertTrue("Has correct object type", TestBean.class.isAssignableFrom(pfb.getObjectType()));
+ }
+
+ public void testGetObjectTypeWithTargetViaTargetSource() {
+ BeanFactory bf = new XmlBeanFactory(new ClassPathResource("proxyFactoryTargetSourceTests.xml", getClass()));
+ ITestBean tb = (ITestBean) bf.getBean("viaTargetSource");
+ assertTrue(tb.getName().equals("Adam"));
+ ProxyFactoryBean pfb = (ProxyFactoryBean) bf.getBean("&viaTargetSource");
+ assertTrue("Has correct object type", TestBean.class.isAssignableFrom(pfb.getObjectType()));
+ }
+
+ public void testGetObjectTypeWithNoTargetOrTargetSource() {
+ BeanFactory bf = new XmlBeanFactory(new ClassPathResource("proxyFactoryTargetSourceTests.xml", getClass()));
+
+ ITestBean tb = (ITestBean) bf.getBean("noTarget");
+ try {
+ tb.getName();
+ fail();
+ }
+ catch (UnsupportedOperationException ex) {
+ assertEquals("getName", ex.getMessage());
+ }
+ FactoryBean pfb = (ProxyFactoryBean) bf.getBean("&noTarget");
+ assertTrue("Has correct object type", ITestBean.class.isAssignableFrom(pfb.getObjectType()));
+ }
+
+ /**
+ * The instances are equal, but do not have object identity.
+ * Interceptors and interfaces and the target are the same.
+ */
+ public void testSingletonInstancesAreEqual() {
+ ITestBean test1 = (ITestBean) factory.getBean("test1");
+ ITestBean test1_1 = (ITestBean) factory.getBean("test1");
+ //assertTrue("Singleton instances ==", test1 == test1_1);
+ assertEquals("Singleton instances ==", test1, test1_1);
+ test1.setAge(25);
+ assertEquals(test1.getAge(), test1_1.getAge());
+ test1.setAge(250);
+ assertEquals(test1.getAge(), test1_1.getAge());
+ Advised pc1 = (Advised) test1;
+ Advised pc2 = (Advised) test1_1;
+ assertEquals(pc1.getAdvisors(), pc2.getAdvisors());
+ int oldLength = pc1.getAdvisors().length;
+ NopInterceptor di = new NopInterceptor();
+ pc1.addAdvice(1, di);
+ assertEquals(pc1.getAdvisors(), pc2.getAdvisors());
+ assertEquals("Now have one more advisor", oldLength + 1, pc2.getAdvisors().length);
+ assertEquals(di.getCount(), 0);
+ test1.setAge(5);
+ assertEquals(test1_1.getAge(), test1.getAge());
+ assertEquals(di.getCount(), 3);
+ }
+
+ public void testPrototypeInstancesAreNotEqual() {
+ assertTrue("Has correct object type", ITestBean.class.isAssignableFrom(factory.getType("prototype")));
+ ITestBean test2 = (ITestBean) factory.getBean("prototype");
+ ITestBean test2_1 = (ITestBean) factory.getBean("prototype");
+ assertTrue("Prototype instances !=", test2 != test2_1);
+ assertTrue("Prototype instances equal", test2.equals(test2_1));
+ assertTrue("Has correct object type", ITestBean.class.isAssignableFrom(factory.getType("prototype")));
+ }
+
+ /**
+ * Uses its own bean factory XML for clarity
+ * @param beanName name of the ProxyFactoryBean definition that should
+ * be a prototype
+ */
+ private Object testPrototypeInstancesAreIndependent(String beanName) {
+ // Initial count value set in bean factory XML
+ int INITIAL_COUNT = 10;
+
+ BeanFactory bf = new XmlBeanFactory(new ClassPathResource("prototypeTests.xml", getClass()));
+
+ // Check it works without AOP
+ SideEffectBean raw = (SideEffectBean) bf.getBean("prototypeTarget");
+ assertEquals(INITIAL_COUNT, raw.getCount() );
+ raw.doWork();
+ assertEquals(INITIAL_COUNT+1, raw.getCount() );
+ raw = (SideEffectBean) bf.getBean("prototypeTarget");
+ assertEquals(INITIAL_COUNT, raw.getCount() );
+
+ // Now try with advised instances
+ SideEffectBean prototype2FirstInstance = (SideEffectBean) bf.getBean(beanName);
+ assertEquals(INITIAL_COUNT, prototype2FirstInstance.getCount() );
+ prototype2FirstInstance.doWork();
+ assertEquals(INITIAL_COUNT + 1, prototype2FirstInstance.getCount() );
+
+ SideEffectBean prototype2SecondInstance = (SideEffectBean) bf.getBean(beanName);
+ assertFalse("Prototypes are not ==", prototype2FirstInstance == prototype2SecondInstance);
+ assertEquals(INITIAL_COUNT, prototype2SecondInstance.getCount() );
+ assertEquals(INITIAL_COUNT + 1, prototype2FirstInstance.getCount() );
+
+ return prototype2FirstInstance;
+ }
+
+ public void testCglibPrototypeInstance() {
+ Object prototype = testPrototypeInstancesAreIndependent("cglibPrototype");
+ assertTrue("It's a cglib proxy", AopUtils.isCglibProxy(prototype));
+ assertFalse("It's not a dynamic proxy", AopUtils.isJdkDynamicProxy(prototype));
+ }
+
+ /**
+ * Test invoker is automatically added to manipulate target.
+ */
+ public void testAutoInvoker() {
+ String name = "Hieronymous";
+ TestBean target = (TestBean) factory.getBean("test");
+ target.setName(name);
+ ITestBean autoInvoker = (ITestBean) factory.getBean("autoInvoker");
+ assertTrue(autoInvoker.getName().equals(name));
+ }
+
+ public void testCanGetFactoryReferenceAndManipulate() {
+ ProxyFactoryBean config = (ProxyFactoryBean) factory.getBean("&test1");
+ assertTrue("Has correct object type", ITestBean.class.isAssignableFrom(config.getObjectType()));
+ assertTrue("Has correct object type", ITestBean.class.isAssignableFrom(factory.getType("test1")));
+ // Trigger lazy initialization.
+ config.getObject();
+ assertEquals("Have one advisors", 1, config.getAdvisors().length);
+ assertTrue("Has correct object type", ITestBean.class.isAssignableFrom(config.getObjectType()));
+ assertTrue("Has correct object type", ITestBean.class.isAssignableFrom(factory.getType("test1")));
+
+ ITestBean tb = (ITestBean) factory.getBean("test1");
+ // no exception
+ tb.hashCode();
+
+ final Exception ex = new UnsupportedOperationException("invoke");
+ // Add evil interceptor to head of list
+ config.addAdvice(0, new MethodInterceptor() {
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ throw ex;
+ }
+ });
+ assertEquals("Have correct advisor count", 2, config.getAdvisors().length);
+
+ tb = (ITestBean) factory.getBean("test1");
+ try {
+ // Will fail now
+ tb.toString();
+ fail("Evil interceptor added programmatically should fail all method calls");
+ }
+ catch (Exception thrown) {
+ assertTrue(thrown == ex);
+ }
+ }
+
+ public static class DependsOnITestBean {
+ public final ITestBean tb;
+ public DependsOnITestBean(ITestBean tb) {
+ this.tb = tb;
+ }
+ }
+
+ /**
+ * Test that inner bean for target means that we can use
+ * autowire without ambiguity from target and proxy
+ */
+ public void testTargetAsInnerBean() {
+ ListableBeanFactory bf = new XmlBeanFactory(new ClassPathResource("innerBeanTarget.xml", getClass()));
+ ITestBean itb = (ITestBean) bf.getBean("testBean");
+ assertEquals("innerBeanTarget", itb.getName());
+ assertEquals("Only have proxy and interceptor: no target", 3, bf.getBeanDefinitionCount());
+ DependsOnITestBean doit = (DependsOnITestBean) bf.getBean("autowireCheck");
+ assertSame(itb, doit.tb);
+ }
+
+ /**
+ * Try adding and removing interfaces and interceptors on prototype.
+ * Changes will only affect future references obtained from the factory.
+ * Each instance will be independent.
+ */
+ public void testCanAddAndRemoveAspectInterfacesOnPrototype() {
+ try {
+ TimeStamped ts = (TimeStamped) factory.getBean("test2");
+ fail("Shouldn't implement TimeStamped before manipulation");
+ }
+ catch (ClassCastException ex) {
+ }
+
+ ProxyFactoryBean config = (ProxyFactoryBean) factory.getBean("&test2");
+ long time = 666L;
+ TimestampIntroductionInterceptor ti = new TimestampIntroductionInterceptor();
+ ti.setTime(time);
+ // Add to head of interceptor chain
+ int oldCount = config.getAdvisors().length;
+ config.addAdvisor(0, new DefaultIntroductionAdvisor(ti, TimeStamped.class));
+ assertTrue(config.getAdvisors().length == oldCount + 1);
+
+ TimeStamped ts = (TimeStamped) factory.getBean("test2");
+ assertEquals(time, ts.getTimeStamp());
+
+ // Can remove
+ config.removeAdvice(ti);
+ assertTrue(config.getAdvisors().length == oldCount);
+
+ // Check no change on existing object reference
+ assertTrue(ts.getTimeStamp() == time);
+
+ try {
+ ts = (TimeStamped) factory.getBean("test2");
+ fail("Should no longer implement TimeStamped");
+ }
+ catch (ClassCastException ex) {
+ }
+
+ // Now check non-effect of removing interceptor that isn't there
+ config.removeAdvice(new DebugInterceptor());
+ assertTrue(config.getAdvisors().length == oldCount);
+
+ ITestBean it = (ITestBean) ts;
+ DebugInterceptor debugInterceptor = new DebugInterceptor();
+ config.addAdvice(0, debugInterceptor);
+ it.getSpouse();
+ // Won't affect existing reference
+ assertTrue(debugInterceptor.getCount() == 0);
+ it = (ITestBean) factory.getBean("test2");
+ it.getSpouse();
+ assertEquals(1, debugInterceptor.getCount());
+ config.removeAdvice(debugInterceptor);
+ it.getSpouse();
+
+ // Still invoked wiht old reference
+ assertEquals(2, debugInterceptor.getCount());
+
+ // not invoked with new object
+ it = (ITestBean) factory.getBean("test2");
+ it.getSpouse();
+ assertEquals(2, debugInterceptor.getCount());
+
+ // Our own timestamped reference should still work
+ assertEquals(time, ts.getTimeStamp());
+ }
+
+ /**
+ * Note that we can't add or remove interfaces without reconfiguring the
+ * singleton.
+ */
+ public void testCanAddAndRemoveAdvicesOnSingleton() {
+ ITestBean it = (ITestBean) factory.getBean("test1");
+ Advised pc = (Advised) it;
+ it.getAge();
+ NopInterceptor di = new NopInterceptor();
+ pc.addAdvice(0, di);
+ assertEquals(0, di.getCount());
+ it.setAge(25);
+ assertEquals(25, it.getAge());
+ assertEquals(2, di.getCount());
+ }
+
+ public void testMethodPointcuts() {
+ ITestBean tb = (ITestBean) factory.getBean("pointcuts");
+ PointcutForVoid.reset();
+ assertTrue("No methods intercepted", PointcutForVoid.methodNames.isEmpty());
+ tb.getAge();
+ assertTrue("Not void: shouldn't have intercepted", PointcutForVoid.methodNames.isEmpty());
+ tb.setAge(1);
+ tb.getAge();
+ tb.setName("Tristan");
+ tb.toString();
+ assertEquals("Recorded wrong number of invocations", 2, PointcutForVoid.methodNames.size());
+ assertTrue(PointcutForVoid.methodNames.get(0).equals("setAge"));
+ assertTrue(PointcutForVoid.methodNames.get(1).equals("setName"));
+ }
+
+ public void testCanAddThrowsAdviceWithoutAdvisor() throws Throwable {
+ BeanFactory f = new XmlBeanFactory(new ClassPathResource("throwsAdvice.xml", getClass()));
+ ThrowsAdviceInterceptorTests.MyThrowsHandler th = (ThrowsAdviceInterceptorTests.MyThrowsHandler) f.getBean("throwsAdvice");
+ CountingBeforeAdvice cba = (CountingBeforeAdvice) f.getBean("countingBeforeAdvice");
+ assertEquals(0, cba.getCalls());
+ assertEquals(0, th.getCalls());
+ ThrowsAdviceInterceptorTests.IEcho echo = (ThrowsAdviceInterceptorTests.IEcho) f.getBean("throwsAdvised");
+ int i = 12;
+ echo.setA(i);
+ assertEquals(i, echo.getA());
+ assertEquals(2, cba.getCalls());
+ assertEquals(0, th.getCalls());
+ Exception expected = new Exception();
+ try {
+ echo.echoException(1, expected);
+ fail();
+ }
+ catch (Exception ex) {
+ assertEquals(expected, ex);
+ }
+ // No throws handler method: count should still be 0
+ assertEquals(0, th.getCalls());
+
+ // Handler knows how to handle this exception
+ expected = new ServletException();
+ try {
+ echo.echoException(1, expected);
+ fail();
+ }
+ catch (ServletException ex) {
+ assertEquals(expected, ex);
+ }
+ // One match
+ assertEquals(1, th.getCalls("servletException"));
+ }
+
+ // These two fail the whole bean factory
+ // TODO put in sep file to check quality of error message
+ /*
+ public void testNoInterceptorNamesWithoutTarget() {
+ try {
+ ITestBean tb = (ITestBean) factory.getBean("noInterceptorNamesWithoutTarget");
+ fail("Should require interceptor names");
+ }
+ catch (AopConfigException ex) {
+ // Ok
+ }
+ }
+
+ public void testNoInterceptorNamesWithTarget() {
+ ITestBean tb = (ITestBean) factory.getBean("noInterceptorNamesWithoutTarget");
+ }
+ */
+
+ public void testEmptyInterceptorNames() {
+ XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("invalidProxyFactory.xml", getClass()));
+ try {
+ ITestBean tb = (ITestBean) factory.getBean("emptyInterceptorNames");
+ fail("Interceptor names cannot be empty");
+ }
+ catch (BeanCreationException ex) {
+ // Ok
+ }
+ }
+
+ /**
+ * Globals must be followed by a target.
+ */
+ public void testGlobalsWithoutTarget() {
+ XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("invalidProxyFactory.xml", getClass()));
+ try {
+ ITestBean tb = (ITestBean) factory.getBean("globalsWithoutTarget");
+ fail("Should require target name");
+ }
+ catch (BeanCreationException ex) {
+ assertTrue(ex.getCause() instanceof AopConfigException);
+ }
+ }
+
+ /**
+ * Checks that globals get invoked,
+ * and that they can add aspect interfaces unavailable
+ * to other beans. These interfaces don't need
+ * to be included in proxiedInterface [].
+ */
+ public void testGlobalsCanAddAspectInterfaces() {
+ AddedGlobalInterface agi = (AddedGlobalInterface) factory.getBean("autoInvoker");
+ assertTrue(agi.globalsAdded() == -1);
+
+ ProxyFactoryBean pfb = (ProxyFactoryBean) factory.getBean("&validGlobals");
+ // Trigger lazy initialization.
+ pfb.getObject();
+ // 2 globals + 2 explicit
+ assertEquals("Have 2 globals and 2 explicit advisors", 3, pfb.getAdvisors().length);
+
+ ApplicationListener l = (ApplicationListener) factory.getBean("validGlobals");
+ agi = (AddedGlobalInterface) l;
+ assertTrue(agi.globalsAdded() == -1);
+
+ try {
+ agi = (AddedGlobalInterface) factory.getBean("test1");
+ fail("Aspect interface should't be implemeneted without globals");
+ }
+ catch (ClassCastException ex) {
+ }
+ }
+
+ public void testSerializableSingletonProxy() throws Exception {
+ BeanFactory bf = new XmlBeanFactory(new ClassPathResource("serializationTests.xml", getClass()));
+ Person p = (Person) bf.getBean("serializableSingleton");
+ assertSame("Should be a Singleton", p, bf.getBean("serializableSingleton"));
+ Person p2 = (Person) SerializationTestUtils.serializeAndDeserialize(p);
+ assertEquals(p, p2);
+ assertNotSame(p, p2);
+ assertEquals("serializableSingleton", p2.getName());
+
+ // Add unserializable advice
+ Advice nop = new NopInterceptor();
+ ((Advised) p).addAdvice(nop);
+ // Check it still works
+ assertEquals(p2.getName(), p2.getName());
+ assertFalse("Not serializable because an interceptor isn't serializable", SerializationTestUtils.isSerializable(p));
+
+ // Remove offending interceptor...
+ assertTrue(((Advised) p).removeAdvice(nop));
+ assertTrue("Serializable again because offending interceptor was removed", SerializationTestUtils.isSerializable(p));
+ }
+
+ public void testSerializablePrototypeProxy() throws Exception {
+ BeanFactory bf = new XmlBeanFactory(new ClassPathResource("serializationTests.xml", getClass()));
+ Person p = (Person) bf.getBean("serializablePrototype");
+ assertNotSame("Should not be a Singleton", p, bf.getBean("serializablePrototype"));
+ Person p2 = (Person) SerializationTestUtils.serializeAndDeserialize(p);
+ assertEquals(p, p2);
+ assertNotSame(p, p2);
+ assertEquals("serializablePrototype", p2.getName());
+ }
+
+ public void testSerializableSingletonProxyFactoryBean() throws Exception {
+ BeanFactory bf = new XmlBeanFactory(new ClassPathResource("serializationTests.xml", getClass()));
+ Person p = (Person) bf.getBean("serializableSingleton");
+ ProxyFactoryBean pfb = (ProxyFactoryBean) bf.getBean("&serializableSingleton");
+ ProxyFactoryBean pfb2 = (ProxyFactoryBean) SerializationTestUtils.serializeAndDeserialize(pfb);
+ Person p2 = (Person) pfb2.getObject();
+ assertEquals(p, p2);
+ assertNotSame(p, p2);
+ assertEquals("serializableSingleton", p2.getName());
+ }
+
+ public void testProxyNotSerializableBecauseOfAdvice() throws Exception {
+ BeanFactory bf = new XmlBeanFactory(new ClassPathResource("serializationTests.xml", getClass()));
+ Person p = (Person) bf.getBean("interceptorNotSerializableSingleton");
+ assertFalse("Not serializable because an interceptor isn't serializable", SerializationTestUtils.isSerializable(p));
+ }
+
+ public void testPrototypeAdvisor() {
+ BeanFactory bf = new XmlBeanFactory(new ClassPathResource("proxyFactoryTests.xml", getClass()));
+
+ ITestBean bean1 = (ITestBean) bf.getBean("prototypeTestBeanProxy");
+ ITestBean bean2 = (ITestBean) bf.getBean("prototypeTestBeanProxy");
+
+ bean1.setAge(3);
+ bean2.setAge(4);
+
+ assertEquals(3, bean1.getAge());
+ assertEquals(4, bean2.getAge());
+
+ ((Lockable) bean1).lock();
+
+ try {
+ bean1.setAge(5);
+ fail("expected LockedException");
+ }
+ catch (LockedException ex) {
+ // expected
+ }
+
+ try {
+ bean2.setAge(6);
+ }
+ catch (LockedException ex) {
+ fail("did not expect LockedException");
+ }
+ }
+
+ public void testPrototypeInterceptorSingletonTarget() {
+ BeanFactory bf = new XmlBeanFactory(new ClassPathResource("proxyFactoryTests.xml", getClass()));
+
+ ITestBean bean1 = (ITestBean) bf.getBean("prototypeTestBeanProxySingletonTarget");
+ ITestBean bean2 = (ITestBean) bf.getBean("prototypeTestBeanProxySingletonTarget");
+
+ bean1.setAge(1);
+ bean2.setAge(2);
+
+ assertEquals(2, bean1.getAge());
+
+ ((Lockable) bean1).lock();
+
+ try {
+ bean1.setAge(5);
+ fail("expected LockedException");
+ }
+ catch (LockedException ex) {
+ // expected
+ }
+
+ try {
+ bean2.setAge(6);
+ }
+ catch (LockedException ex) {
+ fail("did not expect LockedException");
+ }
+ }
+
+ /**
+ * Simple test of a ProxyFactoryBean that has an inner bean as target that specifies autowiring.
+ * Checks for correct use of getType() by bean factory.
+ */
+ public void testInnerBeanTargetUsingAutowiring() {
+ BeanFactory bf = new XmlBeanFactory(new ClassPathResource("proxyFactoryBeanAutowiringTests.xml", getClass()));
+ bf.getBean("testBean");
+ }
+
+ public void testFrozenFactoryBean() {
+ BeanFactory bf = new XmlBeanFactory(new ClassPathResource("frozenProxyFactoryBean.xml", getClass()));
+
+ Advised advised = (Advised)bf.getBean("frozen");
+ assertTrue("The proxy should be frozen", advised.isFrozen());
+ }
+
+ public void testDetectsInterfaces() throws Exception {
+ ProxyFactoryBean fb = new ProxyFactoryBean();
+ fb.setTarget(new TestBean());
+ fb.addAdvice(new DebugInterceptor());
+ fb.setBeanFactory(new DefaultListableBeanFactory());
+ ITestBean proxy = (ITestBean) fb.getObject();
+ assertTrue(AopUtils.isJdkDynamicProxy(proxy));
+ }
+ /**
+ * Fires only on void methods. Saves list of methods intercepted.
+ */
+ public static class PointcutForVoid extends DefaultPointcutAdvisor {
+
+ public static List methodNames = new LinkedList();
+
+ public static void reset() {
+ methodNames.clear();
+ }
+
+ public PointcutForVoid() {
+ setAdvice(new MethodInterceptor() {
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ methodNames.add(invocation.getMethod().getName());
+ return invocation.proceed();
+ }
+ });
+ setPointcut(new DynamicMethodMatcherPointcut() {
+ public boolean matches(Method m, Class targetClass, Object[] args) {
+ return m.getReturnType() == Void.TYPE;
+ }
+ });
+ }
+ }
+
+
+ /**
+ * Aspect interface
+ */
+ public interface AddedGlobalInterface {
+ int globalsAdded();
+ }
+
+
+ /**
+ * Use as a global interceptor. Checks that
+ * global interceptors can add aspect interfaces.
+ * NB: Add only via global interceptors in XML file.
+ */
+ public static class GlobalAspectInterfaceInterceptor implements IntroductionInterceptor {
+
+ public boolean implementsInterface(Class intf) {
+ return intf.equals(AddedGlobalInterface.class);
+ }
+
+ public Object invoke(MethodInvocation mi) throws Throwable {
+ if (mi.getMethod().getDeclaringClass().equals(AddedGlobalInterface.class)) {
+ return new Integer(-1);
+ }
+ return mi.proceed();
+ }
+ }
+
+
+ public static class GlobalIntroductionAdvice implements IntroductionAdvisor {
+
+ private IntroductionInterceptor gi = new GlobalAspectInterfaceInterceptor();
+
+ public ClassFilter getClassFilter() {
+ return ClassFilter.TRUE;
+ }
+
+ public Advice getAdvice() {
+ return this.gi;
+ }
+
+ public Class[] getInterfaces() {
+ return new Class[] { AddedGlobalInterface.class };
+ }
+
+ public boolean isPerInstance() {
+ return false;
+ }
+
+ public void validateInterfaces() {
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/ProxyFactoryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/ProxyFactoryTests.java
new file mode 100644
index 00000000000..af956815d59
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/ProxyFactoryTests.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.Advisor;
+import org.springframework.aop.interceptor.DebugInterceptor;
+import org.springframework.aop.interceptor.NopInterceptor;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.aop.support.DefaultIntroductionAdvisor;
+import org.springframework.aop.support.DefaultPointcutAdvisor;
+import org.springframework.beans.IOther;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.transaction.interceptor.TransactionInterceptor;
+
+/**
+ * Also tests AdvisedSupport and ProxyCreatorSupport superclasses.
+ *
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @since 14.05.2003
+ */
+public class ProxyFactoryTests extends TestCase {
+
+ public void testIndexOfMethods() {
+ TestBean target = new TestBean();
+ ProxyFactory pf = new ProxyFactory(target);
+ NopInterceptor nop = new NopInterceptor();
+ Advisor advisor = new DefaultPointcutAdvisor(new CountingBeforeAdvice());
+ Advised advised = (Advised) pf.getProxy();
+ // Can use advised and ProxyFactory interchangeably
+ advised.addAdvice(nop);
+ pf.addAdvisor(advisor);
+ assertEquals(-1, pf.indexOf(new NopInterceptor()));
+ assertEquals(0, pf.indexOf(nop));
+ assertEquals(1, pf.indexOf(advisor));
+ assertEquals(-1, advised.indexOf(new DefaultPointcutAdvisor(null)));
+ }
+
+ public void testRemoveAdvisorByReference() {
+ TestBean target = new TestBean();
+ ProxyFactory pf = new ProxyFactory(target);
+ NopInterceptor nop = new NopInterceptor();
+ CountingBeforeAdvice cba = new CountingBeforeAdvice();
+ Advisor advisor = new DefaultPointcutAdvisor(cba);
+ pf.addAdvice(nop);
+ pf.addAdvisor(advisor);
+ ITestBean proxied = (ITestBean) pf.getProxy();
+ proxied.setAge(5);
+ assertEquals(1, cba.getCalls());
+ assertEquals(1, nop.getCount());
+ assertTrue(pf.removeAdvisor(advisor));
+ assertEquals(5, proxied.getAge());
+ assertEquals(1, cba.getCalls());
+ assertEquals(2, nop.getCount());
+ assertFalse(pf.removeAdvisor(new DefaultPointcutAdvisor(null)));
+ }
+
+ public void testRemoveAdvisorByIndex() {
+ TestBean target = new TestBean();
+ ProxyFactory pf = new ProxyFactory(target);
+ NopInterceptor nop = new NopInterceptor();
+ CountingBeforeAdvice cba = new CountingBeforeAdvice();
+ Advisor advisor = new DefaultPointcutAdvisor(cba);
+ pf.addAdvice(nop);
+ pf.addAdvisor(advisor);
+ NopInterceptor nop2 = new NopInterceptor();
+ pf.addAdvice(nop2);
+ ITestBean proxied = (ITestBean) pf.getProxy();
+ proxied.setAge(5);
+ assertEquals(1, cba.getCalls());
+ assertEquals(1, nop.getCount());
+ assertEquals(1, nop2.getCount());
+ // Removes counting before advisor
+ pf.removeAdvisor(1);
+ assertEquals(5, proxied.getAge());
+ assertEquals(1, cba.getCalls());
+ assertEquals(2, nop.getCount());
+ assertEquals(2, nop2.getCount());
+ // Removes Nop1
+ pf.removeAdvisor(0);
+ assertEquals(5, proxied.getAge());
+ assertEquals(1, cba.getCalls());
+ assertEquals(2, nop.getCount());
+ assertEquals(3, nop2.getCount());
+
+ // Check out of bounds
+ try {
+ pf.removeAdvisor(-1);
+ }
+ catch (AopConfigException ex) {
+ // Ok
+ }
+
+ try {
+ pf.removeAdvisor(2);
+ }
+ catch (AopConfigException ex) {
+ // Ok
+ }
+
+ assertEquals(5, proxied.getAge());
+ assertEquals(4, nop2.getCount());
+ }
+
+ public void testReplaceAdvisor() {
+ TestBean target = new TestBean();
+ ProxyFactory pf = new ProxyFactory(target);
+ NopInterceptor nop = new NopInterceptor();
+ CountingBeforeAdvice cba1 = new CountingBeforeAdvice();
+ CountingBeforeAdvice cba2 = new CountingBeforeAdvice();
+ Advisor advisor1 = new DefaultPointcutAdvisor(cba1);
+ Advisor advisor2 = new DefaultPointcutAdvisor(cba2);
+ pf.addAdvisor(advisor1);
+ pf.addAdvice(nop);
+ ITestBean proxied = (ITestBean) pf.getProxy();
+ // Use the type cast feature
+ // Replace etc methods on advised should be same as on ProxyFactory
+ Advised advised = (Advised) proxied;
+ proxied.setAge(5);
+ assertEquals(1, cba1.getCalls());
+ assertEquals(0, cba2.getCalls());
+ assertEquals(1, nop.getCount());
+ assertFalse(advised.replaceAdvisor(new DefaultPointcutAdvisor(new NopInterceptor()), advisor2));
+ assertTrue(advised.replaceAdvisor(advisor1, advisor2));
+ assertEquals(advisor2, pf.getAdvisors()[0]);
+ assertEquals(5, proxied.getAge());
+ assertEquals(1, cba1.getCalls());
+ assertEquals(2, nop.getCount());
+ assertEquals(1, cba2.getCalls());
+ assertFalse(pf.replaceAdvisor(new DefaultPointcutAdvisor(null), advisor1));
+ }
+
+ public void testAddRepeatedInterface() {
+ TimeStamped tst = new TimeStamped() {
+ public long getTimeStamp() {
+ throw new UnsupportedOperationException("getTimeStamp");
+ }
+ };
+ ProxyFactory pf = new ProxyFactory(tst);
+ // We've already implicitly added this interface.
+ // This call should be ignored without error
+ pf.addInterface(TimeStamped.class);
+ // All cool
+ TimeStamped ts = (TimeStamped) pf.getProxy();
+ }
+
+ public void testGetsAllInterfaces() throws Exception {
+ // Extend to get new interface
+ class TestBeanSubclass extends TestBean implements Comparable {
+ public int compareTo(Object arg0) {
+ throw new UnsupportedOperationException("compareTo");
+ }
+ }
+ TestBeanSubclass raw = new TestBeanSubclass();
+ ProxyFactory factory = new ProxyFactory(raw);
+ assertEquals("Found correct number of interfaces", 5, factory.getProxiedInterfaces().length);
+ //System.out.println("Proxied interfaces are " + StringUtils.arrayToDelimitedString(factory.getProxiedInterfaces(), ","));
+ ITestBean tb = (ITestBean) factory.getProxy();
+ assertTrue("Picked up secondary interface", tb instanceof IOther);
+
+ raw.setAge(25);
+ assertTrue(tb.getAge() == raw.getAge());
+
+ long t = 555555L;
+ TimestampIntroductionInterceptor ti = new TimestampIntroductionInterceptor(t);
+
+ Class[] oldProxiedInterfaces = factory.getProxiedInterfaces();
+
+ factory.addAdvisor(0, new DefaultIntroductionAdvisor(ti, TimeStamped.class));
+
+ Class[] newProxiedInterfaces = factory.getProxiedInterfaces();
+ assertEquals("Advisor proxies one more interface after introduction", oldProxiedInterfaces.length + 1, newProxiedInterfaces.length);
+
+ TimeStamped ts = (TimeStamped) factory.getProxy();
+ assertTrue(ts.getTimeStamp() == t);
+ // Shouldn't fail;
+ ((IOther) ts).absquatulate();
+ }
+
+ public void testInterceptorInclusionMethods() {
+ NopInterceptor di = new NopInterceptor();
+ NopInterceptor diUnused = new NopInterceptor();
+ ProxyFactory factory = new ProxyFactory(new TestBean());
+ factory.addAdvice(0, di);
+ ITestBean tb = (ITestBean) factory.getProxy();
+ assertTrue(factory.adviceIncluded(di));
+ assertTrue(!factory.adviceIncluded(diUnused));
+ assertTrue(factory.countAdvicesOfType(NopInterceptor.class) == 1);
+ assertTrue(factory.countAdvicesOfType(TransactionInterceptor.class) == 0);
+
+ factory.addAdvice(0, diUnused);
+ assertTrue(factory.adviceIncluded(diUnused));
+ assertTrue(factory.countAdvicesOfType(NopInterceptor.class) == 2);
+ }
+
+ /**
+ * Should see effect immediately on behavior.
+ */
+ public void testCanAddAndRemoveAspectInterfacesOnSingleton() {
+ ProxyFactory config = new ProxyFactory(new TestBean());
+
+ assertFalse("Shouldn't implement TimeStamped before manipulation",
+ config.getProxy() instanceof TimeStamped);
+
+ long time = 666L;
+ TimestampIntroductionInterceptor ti = new TimestampIntroductionInterceptor();
+ ti.setTime(time);
+
+ // Add to front of interceptor chain
+ int oldCount = config.getAdvisors().length;
+ config.addAdvisor(0, new DefaultIntroductionAdvisor(ti, TimeStamped.class));
+
+ assertTrue(config.getAdvisors().length == oldCount + 1);
+
+ TimeStamped ts = (TimeStamped) config.getProxy();
+ assertTrue(ts.getTimeStamp() == time);
+
+ // Can remove
+ config.removeAdvice(ti);
+
+ assertTrue(config.getAdvisors().length == oldCount);
+
+ try {
+ // Existing reference will fail
+ ts.getTimeStamp();
+ fail("Existing object won't implement this interface any more");
+ }
+ catch (RuntimeException ex) {
+ }
+
+ assertFalse("Should no longer implement TimeStamped",
+ config.getProxy() instanceof TimeStamped);
+
+ // Now check non-effect of removing interceptor that isn't there
+ config.removeAdvice(new DebugInterceptor());
+
+ assertTrue(config.getAdvisors().length == oldCount);
+
+ ITestBean it = (ITestBean) ts;
+ DebugInterceptor debugInterceptor = new DebugInterceptor();
+ config.addAdvice(0, debugInterceptor);
+ it.getSpouse();
+ assertEquals(1, debugInterceptor.getCount());
+ config.removeAdvice(debugInterceptor);
+ it.getSpouse();
+ // not invoked again
+ assertTrue(debugInterceptor.getCount() == 1);
+ }
+
+ public void testProxyTargetClassWithInterfaceAsTarget() {
+ ProxyFactory pf = new ProxyFactory();
+ pf.setTargetClass(ITestBean.class);
+
+ Object proxy = pf.getProxy();
+ assertTrue("Proxy is a JDK proxy", AopUtils.isJdkDynamicProxy(proxy));
+ assertTrue(proxy instanceof ITestBean);
+ }
+
+ public void testProxyTargetClassWithConcreteClassAsTarget() {
+ ProxyFactory pf = new ProxyFactory();
+ pf.setTargetClass(TestBean.class);
+
+ Object proxy = pf.getProxy();
+ assertTrue("Proxy is a CGLIB proxy", AopUtils.isCglibProxy(proxy));
+ assertTrue(proxy instanceof TestBean);
+ }
+
+
+ public static class Concrete {
+
+ public void foo() {
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/TimeStamped.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/TimeStamped.java
new file mode 100644
index 00000000000..e514210ec17
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/TimeStamped.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+/**
+ * This interface can be implemented by cacheable objects or cache entries,
+ * to enable the freshness of objects to be checked.
+ *
+ * @author Rod Johnson
+ */
+public interface TimeStamped {
+
+ /**
+ * Return the timestamp for this object.
+ * @return long the timestamp for this object,
+ * as returned by System.currentTimeMillis()
+ */
+ long getTimeStamp();
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/TimestampIntroductionAdvisor.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/TimestampIntroductionAdvisor.java
new file mode 100644
index 00000000000..387d3818d36
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/TimestampIntroductionAdvisor.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+import org.springframework.aop.support.DelegatingIntroductionInterceptor;
+import org.springframework.aop.support.DefaultIntroductionAdvisor;
+
+/**
+ *
+ * @author Rod Johnson
+ */
+public class TimestampIntroductionAdvisor extends DefaultIntroductionAdvisor {
+
+ /**
+ * @param dii
+ */
+ public TimestampIntroductionAdvisor() {
+ super(new DelegatingIntroductionInterceptor(new TimestampIntroductionInterceptor()));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/TimestampIntroductionInterceptor.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/TimestampIntroductionInterceptor.java
new file mode 100644
index 00000000000..2584d2575c5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/TimestampIntroductionInterceptor.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+import org.springframework.aop.support.DelegatingIntroductionInterceptor;
+
+public class TimestampIntroductionInterceptor extends DelegatingIntroductionInterceptor
+ implements TimeStamped {
+
+ private long ts;
+
+ public TimestampIntroductionInterceptor() {
+ }
+
+ public TimestampIntroductionInterceptor(long ts) {
+ this.ts = ts;
+ }
+
+ public void setTime(long ts) {
+ this.ts = ts;
+ }
+
+ public long getTimeStamp() {
+ return ts;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/UnsupportedInterceptor.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/UnsupportedInterceptor.java
new file mode 100644
index 00000000000..7f3817c663c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/UnsupportedInterceptor.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+/**
+ *
+ * @author Rod Johnson
+ */
+public class UnsupportedInterceptor implements MethodInterceptor {
+
+ /**
+ * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
+ */
+ public Object invoke(MethodInvocation mi) throws Throwable {
+ throw new UnsupportedOperationException(mi.getMethod().getName());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/adapter/AdvisorAdapterRegistrationTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/adapter/AdvisorAdapterRegistrationTests.java
new file mode 100644
index 00000000000..63bdb88bed4
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/adapter/AdvisorAdapterRegistrationTests.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework.adapter;
+
+import junit.framework.*;
+
+import org.springframework.aop.*;
+import org.springframework.aop.support.*;
+import org.springframework.aop.framework.Advised;
+import org.springframework.beans.ITestBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * TestCase for AdvisorAdapterRegistrationManager mechanism.
+ *
+ * @author Dmitriy Kopylenko
+ */
+public class AdvisorAdapterRegistrationTests extends TestCase {
+
+ public AdvisorAdapterRegistrationTests(String name) {
+ super(name);
+ }
+
+ public void testAdvisorAdapterRegistrationManagerNotPresentInContext() {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("/org/springframework/aop/framework/adapter/withoutBPPContext.xml");
+ ITestBean tb = (ITestBean) ctx.getBean("testBean");
+ // just invoke any method to see if advice fired
+ try {
+ tb.getName();
+ fail("Should throw UnknownAdviceTypeException");
+ }
+ catch (UnknownAdviceTypeException ex) {
+ // expected
+ assertEquals(0, getAdviceImpl(tb).getInvocationCounter());
+ }
+ }
+
+ public void testAdvisorAdapterRegistrationManagerPresentInContext() {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("/org/springframework/aop/framework/adapter/withBPPContext.xml");
+ ITestBean tb = (ITestBean) ctx.getBean("testBean");
+ // just invoke any method to see if advice fired
+ try {
+ tb.getName();
+ assertEquals(1, getAdviceImpl(tb).getInvocationCounter());
+ }
+ catch (UnknownAdviceTypeException ex) {
+ fail("Should not throw UnknownAdviceTypeException");
+ }
+ }
+
+ private SimpleBeforeAdviceImpl getAdviceImpl(ITestBean tb) {
+ Advised advised = (Advised) tb;
+ Advisor advisor = advised.getAdvisors()[0];
+ return (SimpleBeforeAdviceImpl) advisor.getAdvice();
+ }
+
+ // temporary suite method to make tests work on JRockit!
+ // Alef knows more about this.
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.addTest(new AdvisorAdapterRegistrationTests("testAdvisorAdapterRegistrationManagerNotPresentInContext"));
+ suite.addTest(new AdvisorAdapterRegistrationTests("testAdvisorAdapterRegistrationManagerPresentInContext"));
+ return suite;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/adapter/ThrowsAdviceInterceptorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/adapter/ThrowsAdviceInterceptorTests.java
new file mode 100644
index 00000000000..176da331750
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/adapter/ThrowsAdviceInterceptorTests.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework.adapter;
+
+import java.lang.reflect.Method;
+import java.rmi.RemoteException;
+
+import javax.servlet.ServletException;
+import javax.transaction.TransactionRolledbackException;
+
+import junit.framework.TestCase;
+import org.aopalliance.intercept.MethodInvocation;
+import org.easymock.MockControl;
+
+import org.springframework.aop.ThrowsAdvice;
+import org.springframework.aop.framework.MethodCounter;
+
+/**
+ * @author Rod Johnson
+ */
+public class ThrowsAdviceInterceptorTests extends TestCase {
+
+ public void testNoHandlerMethods() {
+ Object o = new Object();
+ try {
+ new ThrowsAdviceInterceptor(o);
+ fail("Should require one handler method at least");
+ }
+ catch (IllegalArgumentException ex) {
+ // Ok
+ }
+ }
+
+ public void testNotInvoked() throws Throwable {
+ MyThrowsHandler th = new MyThrowsHandler();
+ ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th);
+ Object ret = new Object();
+ MockControl mc = MockControl.createControl(MethodInvocation.class);
+ MethodInvocation mi = (MethodInvocation) mc.getMock();
+ mi.proceed();
+ mc.setReturnValue(ret, 1);
+ mc.replay();
+ assertEquals(ret, ti.invoke(mi));
+ assertEquals(0, th.getCalls());
+ mc.verify();
+ }
+
+ public void testNoHandlerMethodForThrowable() throws Throwable {
+ MyThrowsHandler th = new MyThrowsHandler();
+ ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th);
+ assertEquals(2, ti.getHandlerMethodCount());
+ Exception ex = new Exception();
+ MockControl mc = MockControl.createControl(MethodInvocation.class);
+ MethodInvocation mi = (MethodInvocation) mc.getMock();
+ mi.proceed();
+ mc.setThrowable(ex);
+ mc.replay();
+ try {
+ ti.invoke(mi);
+ fail();
+ }
+ catch (Exception caught) {
+ assertEquals(ex, caught);
+ }
+ assertEquals(0, th.getCalls());
+ mc.verify();
+ }
+
+ public void testCorrectHandlerUsed() throws Throwable {
+ MyThrowsHandler th = new MyThrowsHandler();
+ ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th);
+ ServletException ex = new ServletException();
+ MockControl mc = MockControl.createControl(MethodInvocation.class);
+ MethodInvocation mi = (MethodInvocation) mc.getMock();
+ mi.getMethod();
+ mc.setReturnValue(Object.class.getMethod("hashCode", (Class[]) null), 1);
+ mi.getArguments();
+ mc.setReturnValue(null);
+ mi.getThis();
+ mc.setReturnValue(new Object());
+ mi.proceed();
+ mc.setThrowable(ex);
+ mc.replay();
+ try {
+ ti.invoke(mi);
+ fail();
+ }
+ catch (Exception caught) {
+ assertEquals(ex, caught);
+ }
+ assertEquals(1, th.getCalls());
+ assertEquals(1, th.getCalls("servletException"));
+ mc.verify();
+ }
+
+ public void testCorrectHandlerUsedForSubclass() throws Throwable {
+ MyThrowsHandler th = new MyThrowsHandler();
+ ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th);
+ // Extends RemoteException
+ TransactionRolledbackException ex = new TransactionRolledbackException();
+ MockControl mc = MockControl.createControl(MethodInvocation.class);
+ MethodInvocation mi = (MethodInvocation) mc.getMock();
+ mi.proceed();
+ mc.setThrowable(ex);
+ mc.replay();
+ try {
+ ti.invoke(mi);
+ fail();
+ }
+ catch (Exception caught) {
+ assertEquals(ex, caught);
+ }
+ assertEquals(1, th.getCalls());
+ assertEquals(1, th.getCalls("remoteException"));
+ mc.verify();
+ }
+
+ public void testHandlerMethodThrowsException() throws Throwable {
+ final Throwable t = new Throwable();
+ MyThrowsHandler th = new MyThrowsHandler() {
+ public void afterThrowing(RemoteException ex) throws Throwable {
+ super.afterThrowing(ex);
+ throw t;
+ }
+ };
+ ThrowsAdviceInterceptor ti = new ThrowsAdviceInterceptor(th);
+ // Extends RemoteException
+ TransactionRolledbackException ex = new TransactionRolledbackException();
+ MockControl mc = MockControl.createControl(MethodInvocation.class);
+ MethodInvocation mi = (MethodInvocation) mc.getMock();
+ mi.proceed();
+ mc.setThrowable(ex);
+ mc.replay();
+ try {
+ ti.invoke(mi);
+ fail();
+ }
+ catch (Throwable caught) {
+ assertEquals(t, caught);
+ }
+ assertEquals(1, th.getCalls());
+ assertEquals(1, th.getCalls("remoteException"));
+ mc.verify();
+ }
+
+ public static class MyThrowsHandler extends MethodCounter implements ThrowsAdvice {
+ // Full method signature
+ public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) {
+ count("servletException");
+ }
+ public void afterThrowing(RemoteException ex) throws Throwable {
+ count("remoteException");
+ }
+
+ /** Not valid, wrong number of arguments */
+ public void afterThrowing(Method m, Exception ex) throws Throwable {
+ throw new UnsupportedOperationException("Shouldn't be called");
+ }
+ }
+
+ public interface IEcho {
+ int echoException(int i, Throwable t) throws Throwable;
+ int getA();
+ void setA(int a);
+ }
+
+ public static class Echo implements IEcho {
+ private int a;
+
+ public int echoException(int i, Throwable t) throws Throwable {
+ if (t != null)
+ throw t;
+ return i;
+ }
+ public void setA(int a) {
+ this.a = a;
+ }
+ public int getA() {
+ return a;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/adapter/withBPPContext.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/adapter/withBPPContext.xml
new file mode 100644
index 00000000000..df51623facd
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/adapter/withBPPContext.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.springframework.beans.ITestBean
+ simpleBeforeAdviceAdvisor,testBeanTarget
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/adapter/withoutBPPContext.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/adapter/withoutBPPContext.xml
new file mode 100644
index 00000000000..d977ac4ee73
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/adapter/withoutBPPContext.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.springframework.beans.ITestBean
+ simpleBeforeAdviceAdvisor,testBeanTarget
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/AdvisorAutoProxyCreatorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/AdvisorAutoProxyCreatorTests.java
new file mode 100644
index 00000000000..731d1e7fc07
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/AdvisorAutoProxyCreatorTests.java
@@ -0,0 +1,343 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.framework.autoproxy;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.framework.Advised;
+import org.springframework.aop.framework.CountingBeforeAdvice;
+import org.springframework.aop.framework.Lockable;
+import org.springframework.aop.framework.MethodCounter;
+import org.springframework.aop.interceptor.NopInterceptor;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.aop.target.CommonsPoolTargetSource;
+import org.springframework.aop.target.LazyInitTargetSource;
+import org.springframework.aop.target.PrototypeTargetSource;
+import org.springframework.aop.target.ThreadLocalTargetSource;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.transaction.CallCountingTransactionManager;
+
+/**
+ * Tests for auto proxy creation by advisor recognition.
+ *
+ * @author Rod Johnson
+ */
+public class AdvisorAutoProxyCreatorTests extends TestCase {
+
+ private static final String ADVISOR_APC_BEAN_NAME = "aapc";
+
+ private static final String TXMANAGER_BEAN_NAME = "txManager";
+
+ /**
+ * Return a bean factory with attributes and EnterpriseServices configured.
+ */
+ protected BeanFactory getBeanFactory() throws IOException {
+ return new ClassPathXmlApplicationContext("/org/springframework/aop/framework/autoproxy/advisorAutoProxyCreator.xml");
+ }
+
+ public void testDefaultExclusionPrefix() throws Exception {
+ DefaultAdvisorAutoProxyCreator aapc = (DefaultAdvisorAutoProxyCreator) getBeanFactory().getBean(ADVISOR_APC_BEAN_NAME);
+ assertEquals(ADVISOR_APC_BEAN_NAME + DefaultAdvisorAutoProxyCreator.SEPARATOR, aapc.getAdvisorBeanNamePrefix());
+ assertFalse(aapc.isUsePrefix());
+ }
+
+ /**
+ * If no pointcuts match (no attrs) there should be proxying.
+ */
+ public void testNoProxy() throws Exception {
+ BeanFactory bf = getBeanFactory();
+ Object o = bf.getBean("noSetters");
+ assertFalse(AopUtils.isAopProxy(o));
+ }
+
+ public void testTxIsProxied() throws Exception {
+ BeanFactory bf = getBeanFactory();
+ ITestBean test = (ITestBean) bf.getBean("test");
+ assertTrue(AopUtils.isAopProxy(test));
+ }
+
+ public void testRegexpApplied() throws Exception {
+ BeanFactory bf = getBeanFactory();
+ ITestBean test = (ITestBean) bf.getBean("test");
+ MethodCounter counter = (MethodCounter) bf.getBean("countingAdvice");
+ assertEquals(0, counter.getCalls());
+ test.getName();
+ assertEquals(1, counter.getCalls());
+ }
+
+ /**
+ * Check that we can provide a common interceptor that will
+ * appear in the chain before "specific" interceptors,
+ * which are sourced from matching advisors
+ */
+ public void testCommonInterceptorAndAdvisor() throws Exception {
+ BeanFactory bf = new ClassPathXmlApplicationContext("/org/springframework/aop/framework/autoproxy/advisorAutoProxyCreatorWithCommonInterceptors.xml");
+ ITestBean test1 = (ITestBean) bf.getBean("test1");
+ assertTrue(AopUtils.isAopProxy(test1));
+
+ Lockable lockable1 = (Lockable) test1;
+ NopInterceptor nop = (NopInterceptor) bf.getBean("nopInterceptor");
+ assertEquals(0, nop.getCount());
+
+ ITestBean test2 = (ITestBean) bf.getBean("test2");
+ Lockable lockable2 = (Lockable) test2;
+
+ // Locking should be independent; nop is shared
+ assertFalse(lockable1.locked());
+ assertFalse(lockable2.locked());
+ // equals 2 calls on shared nop, because it's first
+ // and sees calls against the Lockable interface introduced
+ // by the specific advisor
+ assertEquals(2, nop.getCount());
+ lockable1.lock();
+ assertTrue(lockable1.locked());
+ assertFalse(lockable2.locked());
+ assertEquals(5, nop.getCount());
+ }
+
+ /**
+ * We have custom TargetSourceCreators but there's no match, and
+ * hence no proxying, for this bean
+ */
+ public void testCustomTargetSourceNoMatch() throws Exception {
+ BeanFactory bf = new ClassPathXmlApplicationContext("/org/springframework/aop/framework/autoproxy/customTargetSource.xml");
+ ITestBean test = (ITestBean) bf.getBean("test");
+ assertFalse(AopUtils.isAopProxy(test));
+ assertEquals("Rod", test.getName());
+ assertEquals("Kerry", test.getSpouse().getName());
+ }
+
+ public void testCustomPrototypeTargetSource() throws Exception {
+ CountingTestBean.count = 0;
+ BeanFactory bf = new ClassPathXmlApplicationContext("/org/springframework/aop/framework/autoproxy/customTargetSource.xml");
+ ITestBean test = (ITestBean) bf.getBean("prototypeTest");
+ assertTrue(AopUtils.isAopProxy(test));
+ Advised advised = (Advised) test;
+ assertTrue(advised.getTargetSource() instanceof PrototypeTargetSource);
+ assertEquals("Rod", test.getName());
+ // Check that references survived prototype creation
+ assertEquals("Kerry", test.getSpouse().getName());
+ assertEquals("Only 2 CountingTestBeans instantiated", 2, CountingTestBean.count);
+ CountingTestBean.count = 0;
+ }
+
+ public void testLazyInitTargetSource() throws Exception {
+ CountingTestBean.count = 0;
+ BeanFactory bf = new ClassPathXmlApplicationContext("/org/springframework/aop/framework/autoproxy/customTargetSource.xml");
+ ITestBean test = (ITestBean) bf.getBean("lazyInitTest");
+ assertTrue(AopUtils.isAopProxy(test));
+ Advised advised = (Advised) test;
+ assertTrue(advised.getTargetSource() instanceof LazyInitTargetSource);
+ assertEquals("No CountingTestBean instantiated yet", 0, CountingTestBean.count);
+ assertEquals("Rod", test.getName());
+ assertEquals("Kerry", test.getSpouse().getName());
+ assertEquals("Only 1 CountingTestBean instantiated", 1, CountingTestBean.count);
+ CountingTestBean.count = 0;
+ }
+
+ public void testQuickTargetSourceCreator() throws Exception {
+ ClassPathXmlApplicationContext bf =
+ new ClassPathXmlApplicationContext("/org/springframework/aop/framework/autoproxy/quickTargetSource.xml");
+ ITestBean test = (ITestBean) bf.getBean("test");
+ assertFalse(AopUtils.isAopProxy(test));
+ assertEquals("Rod", test.getName());
+ // Check that references survived pooling
+ assertEquals("Kerry", test.getSpouse().getName());
+
+ // Now test the pooled one
+ test = (ITestBean) bf.getBean(":test");
+ assertTrue(AopUtils.isAopProxy(test));
+ Advised advised = (Advised) test;
+ assertTrue(advised.getTargetSource() instanceof CommonsPoolTargetSource);
+ assertEquals("Rod", test.getName());
+ // Check that references survived pooling
+ assertEquals("Kerry", test.getSpouse().getName());
+
+ // Now test the ThreadLocal one
+ test = (ITestBean) bf.getBean("%test");
+ assertTrue(AopUtils.isAopProxy(test));
+ advised = (Advised) test;
+ assertTrue(advised.getTargetSource() instanceof ThreadLocalTargetSource);
+ assertEquals("Rod", test.getName());
+ // Check that references survived pooling
+ assertEquals("Kerry", test.getSpouse().getName());
+
+ // Now test the Prototype TargetSource
+ test = (ITestBean) bf.getBean("!test");
+ assertTrue(AopUtils.isAopProxy(test));
+ advised = (Advised) test;
+ assertTrue(advised.getTargetSource() instanceof PrototypeTargetSource);
+ assertEquals("Rod", test.getName());
+ // Check that references survived pooling
+ assertEquals("Kerry", test.getSpouse().getName());
+
+
+ ITestBean test2 = (ITestBean) bf.getBean("!test");
+ assertFalse("Prototypes cannot be the same object", test == test2);
+ assertEquals("Rod", test2.getName());
+ assertEquals("Kerry", test2.getSpouse().getName());
+ bf.close();
+ }
+
+ /*
+ public void testIntroductionIsProxied() throws Exception {
+ BeanFactory bf = getBeanFactory();
+ Object modifiable = bf.getBean("modifiable1");
+ // We can tell it's a CGLIB proxy by looking at the class name
+ System.out.println(modifiable.getClass().getName());
+ assertFalse(modifiable.getClass().getName().equals(ModifiableTestBean.class.getName()));
+ }
+ */
+
+ public void testTransactionAttributeOnMethod() throws Exception {
+ BeanFactory bf = getBeanFactory();
+ ITestBean test = (ITestBean) bf.getBean("test");
+
+ CallCountingTransactionManager txMan = (CallCountingTransactionManager) bf.getBean(TXMANAGER_BEAN_NAME);
+ OrderedTxCheckAdvisor txc = (OrderedTxCheckAdvisor) bf.getBean("orderedBeforeTransaction");
+ assertEquals(0, txc.getCountingBeforeAdvice().getCalls());
+
+ assertEquals(0, txMan.commits);
+ assertEquals("Initial value was correct", 4, test.getAge());
+ int newAge = 5;
+ test.setAge(newAge);
+ assertEquals(1, txc.getCountingBeforeAdvice().getCalls());
+
+ assertEquals("New value set correctly", newAge, test.getAge());
+ assertEquals("Transaction counts match", 1, txMan.commits);
+ }
+
+ /**
+ * Should not roll back on servlet exception.
+ */
+ public void testRollbackRulesOnMethodCauseRollback() throws Exception {
+ BeanFactory bf = getBeanFactory();
+ Rollback rb = (Rollback) bf.getBean("rollback");
+
+ CallCountingTransactionManager txMan = (CallCountingTransactionManager) bf.getBean(TXMANAGER_BEAN_NAME);
+ OrderedTxCheckAdvisor txc = (OrderedTxCheckAdvisor) bf.getBean("orderedBeforeTransaction");
+ assertEquals(0, txc.getCountingBeforeAdvice().getCalls());
+
+ assertEquals(0, txMan.commits);
+ rb.echoException(null);
+ // Fires only on setters
+ assertEquals(0, txc.getCountingBeforeAdvice().getCalls());
+ assertEquals("Transaction counts match", 1, txMan.commits);
+
+ assertEquals(0, txMan.rollbacks);
+ Exception ex = new Exception();
+ try {
+ rb.echoException(ex);
+ }
+ catch (Exception actual) {
+ assertEquals(ex, actual);
+ }
+ assertEquals("Transaction counts match", 1, txMan.rollbacks);
+ }
+
+ public void testRollbackRulesOnMethodPreventRollback() throws Exception {
+ BeanFactory bf = getBeanFactory();
+ Rollback rb = (Rollback) bf.getBean("rollback");
+
+ CallCountingTransactionManager txMan = (CallCountingTransactionManager) bf.getBean(TXMANAGER_BEAN_NAME);
+
+ assertEquals(0, txMan.commits);
+ // Should NOT roll back on ServletException
+ try {
+ rb.echoException(new ServletException());
+ }
+ catch (ServletException ex) {
+
+ }
+ assertEquals("Transaction counts match", 1, txMan.commits);
+ }
+
+ public void testProgrammaticRollback() throws Exception {
+ BeanFactory bf = getBeanFactory();
+
+ Object bean = bf.getBean(TXMANAGER_BEAN_NAME);
+ assertTrue(bean instanceof CallCountingTransactionManager);
+ CallCountingTransactionManager txMan = (CallCountingTransactionManager) bf.getBean(TXMANAGER_BEAN_NAME);
+
+ Rollback rb = (Rollback) bf.getBean("rollback");
+ assertEquals(0, txMan.commits);
+ rb.rollbackOnly(false);
+ assertEquals("Transaction counts match", 1, txMan.commits);
+ assertEquals(0, txMan.rollbacks);
+ // Will cause rollback only
+ rb.rollbackOnly(true);
+ assertEquals(1, txMan.rollbacks);
+ }
+
+ public void testWithOptimizedProxy() throws Exception {
+ BeanFactory beanFactory = new ClassPathXmlApplicationContext("org/springframework/aop/framework/autoproxy/optimizedAutoProxyCreator.xml");
+
+ ITestBean testBean = (ITestBean) beanFactory.getBean("optimizedTestBean");
+ assertTrue(AopUtils.isAopProxy(testBean));
+
+ CountingBeforeAdvice beforeAdvice = (CountingBeforeAdvice) beanFactory.getBean("countingAdvice");
+
+ testBean.setAge(23);
+ testBean.getAge();
+
+ assertEquals("Incorrect number of calls to proxy", 2, beforeAdvice.getCalls());
+ }
+
+
+ /**
+ * Tests an introduction pointcut. This is a prototype, so that it can add
+ * a Modifiable mixin. Tests that the autoproxy infrastructure can create
+ * advised objects with independent interceptor instances.
+ * The Modifiable behaviour of each instance of TestBean should be distinct.
+ */
+ /*
+ public void testIntroductionViaPrototype() throws Exception {
+ BeanFactory bf = getBeanFactory();
+
+ Object o = bf.getBean("modifiable1");
+ ITestBean modifiable1 = (ITestBean) bf.getBean("modifiable1");
+ ITestBean modifiable2 = (ITestBean) bf.getBean("modifiable2");
+
+ Advised pc = (Advised) modifiable1;
+ System.err.println(pc.toProxyConfigString());
+
+ // For convenience only
+ Modifiable mod1 = (Modifiable) modifiable1;
+ Modifiable mod2 = (Modifiable) modifiable2;
+
+ assertFalse(mod1.isModified());
+ assertFalse(mod2.isModified());
+
+ int newAge = 33;
+ modifiable1.setAge(newAge);
+ assertTrue(mod1.isModified());
+ // Changes to one shouldn't have affected the other
+ assertFalse("Instances of prototype introduction pointcut don't seem distinct", mod2.isModified());
+ mod1.acceptChanges();
+ assertFalse(mod1.isModified());
+ assertEquals(modifiable1.getAge(), newAge);
+ assertFalse(mod1.isModified());
+ }
+ */
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/AutoProxyCreatorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/AutoProxyCreatorTests.java
new file mode 100644
index 00000000000..8c98a02adea
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/AutoProxyCreatorTests.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.framework.autoproxy;
+
+import java.lang.reflect.Proxy;
+
+import junit.framework.TestCase;
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+import org.springframework.aop.TargetSource;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.IndexedTestBean;
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.DummyFactory;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.config.BeanDefinitionHolder;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.context.MessageSource;
+import org.springframework.context.support.StaticApplicationContext;
+import org.springframework.context.support.StaticMessageSource;
+
+/**
+ * @author Juergen Hoeller
+ * @since 09.12.2003
+ */
+public class AutoProxyCreatorTests extends TestCase {
+
+ public void testBeanNameAutoProxyCreator() {
+ StaticApplicationContext sac = new StaticApplicationContext();
+ sac.registerSingleton("testInterceptor", TestInterceptor.class);
+
+ RootBeanDefinition proxyCreator = new RootBeanDefinition(BeanNameAutoProxyCreator.class);
+ proxyCreator.getPropertyValues().addPropertyValue("interceptorNames", "testInterceptor");
+ proxyCreator.getPropertyValues().addPropertyValue("beanNames", "singletonToBeProxied,innerBean,singletonFactoryToBeProxied");
+ sac.getDefaultListableBeanFactory().registerBeanDefinition("beanNameAutoProxyCreator", proxyCreator);
+
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, RootBeanDefinition.AUTOWIRE_BY_TYPE);
+ RootBeanDefinition innerBean = new RootBeanDefinition(TestBean.class);
+ bd.getPropertyValues().addPropertyValue("spouse", new BeanDefinitionHolder(innerBean, "innerBean"));
+ sac.getDefaultListableBeanFactory().registerBeanDefinition("singletonToBeProxied", bd);
+
+ sac.registerSingleton("singletonFactoryToBeProxied", DummyFactory.class);
+ sac.registerSingleton("autowiredIndexedTestBean", IndexedTestBean.class);
+
+ sac.refresh();
+
+ MessageSource messageSource = (MessageSource) sac.getBean("messageSource");
+ ITestBean singletonToBeProxied = (ITestBean) sac.getBean("singletonToBeProxied");
+ assertFalse(Proxy.isProxyClass(messageSource.getClass()));
+ assertTrue(Proxy.isProxyClass(singletonToBeProxied.getClass()));
+ assertTrue(Proxy.isProxyClass(singletonToBeProxied.getSpouse().getClass()));
+
+ // test whether autowiring succeeded with auto proxy creation
+ assertEquals(sac.getBean("autowiredIndexedTestBean"), singletonToBeProxied.getNestedIndexedBean());
+
+ TestInterceptor ti = (TestInterceptor) sac.getBean("testInterceptor");
+ // already 2: getSpouse + getNestedIndexedBean calls above
+ assertEquals(2, ti.nrOfInvocations);
+ singletonToBeProxied.getName();
+ singletonToBeProxied.getSpouse().getName();
+ assertEquals(5, ti.nrOfInvocations);
+
+ ITestBean tb = (ITestBean) sac.getBean("singletonFactoryToBeProxied");
+ assertTrue(AopUtils.isJdkDynamicProxy(tb));
+ assertEquals(5, ti.nrOfInvocations);
+ tb.getAge();
+ assertEquals(6, ti.nrOfInvocations);
+
+ ITestBean tb2 = (ITestBean) sac.getBean("singletonFactoryToBeProxied");
+ assertSame(tb, tb2);
+ assertEquals(6, ti.nrOfInvocations);
+ tb2.getAge();
+ assertEquals(7, ti.nrOfInvocations);
+ }
+
+ public void testBeanNameAutoProxyCreatorWithFactoryBeanProxy() {
+ StaticApplicationContext sac = new StaticApplicationContext();
+ sac.registerSingleton("testInterceptor", TestInterceptor.class);
+
+ RootBeanDefinition proxyCreator = new RootBeanDefinition(BeanNameAutoProxyCreator.class);
+ proxyCreator.getPropertyValues().addPropertyValue("interceptorNames", "testInterceptor");
+ proxyCreator.getPropertyValues().addPropertyValue("beanNames", "singletonToBeProxied,&singletonFactoryToBeProxied");
+ sac.getDefaultListableBeanFactory().registerBeanDefinition("beanNameAutoProxyCreator", proxyCreator);
+
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
+ sac.getDefaultListableBeanFactory().registerBeanDefinition("singletonToBeProxied", bd);
+
+ sac.registerSingleton("singletonFactoryToBeProxied", DummyFactory.class);
+
+ sac.refresh();
+
+ ITestBean singletonToBeProxied = (ITestBean) sac.getBean("singletonToBeProxied");
+ assertTrue(Proxy.isProxyClass(singletonToBeProxied.getClass()));
+
+ TestInterceptor ti = (TestInterceptor) sac.getBean("testInterceptor");
+ assertEquals(0, ti.nrOfInvocations);
+ singletonToBeProxied.getName();
+ assertEquals(1, ti.nrOfInvocations);
+
+ FactoryBean factory = (FactoryBean) sac.getBean("&singletonFactoryToBeProxied");
+ assertTrue(Proxy.isProxyClass(factory.getClass()));
+ TestBean tb = (TestBean) sac.getBean("singletonFactoryToBeProxied");
+ assertFalse(AopUtils.isAopProxy(tb));
+ assertEquals(3, ti.nrOfInvocations);
+ tb.getAge();
+ assertEquals(3, ti.nrOfInvocations);
+ }
+
+ public void testCustomAutoProxyCreator() {
+ StaticApplicationContext sac = new StaticApplicationContext();
+ sac.registerSingleton("testAutoProxyCreator", TestAutoProxyCreator.class);
+ sac.registerSingleton("singletonNoInterceptor", TestBean.class);
+ sac.registerSingleton("singletonToBeProxied", TestBean.class);
+ sac.registerPrototype("prototypeToBeProxied", TestBean.class);
+ sac.refresh();
+
+ MessageSource messageSource = (MessageSource) sac.getBean("messageSource");
+ ITestBean singletonNoInterceptor = (ITestBean) sac.getBean("singletonNoInterceptor");
+ ITestBean singletonToBeProxied = (ITestBean) sac.getBean("singletonToBeProxied");
+ ITestBean prototypeToBeProxied = (ITestBean) sac.getBean("prototypeToBeProxied");
+ assertFalse(AopUtils.isCglibProxy(messageSource));
+ assertTrue(AopUtils.isCglibProxy(singletonNoInterceptor));
+ assertTrue(AopUtils.isCglibProxy(singletonToBeProxied));
+ assertTrue(AopUtils.isCglibProxy(prototypeToBeProxied));
+
+ TestAutoProxyCreator tapc = (TestAutoProxyCreator) sac.getBean("testAutoProxyCreator");
+ assertEquals(0, tapc.testInterceptor.nrOfInvocations);
+ singletonNoInterceptor.getName();
+ assertEquals(0, tapc.testInterceptor.nrOfInvocations);
+ singletonToBeProxied.getAge();
+ assertEquals(1, tapc.testInterceptor.nrOfInvocations);
+ prototypeToBeProxied.getSpouse();
+ assertEquals(2, tapc.testInterceptor.nrOfInvocations);
+ }
+
+ public void testAutoProxyCreatorWithFactoryBean() {
+ StaticApplicationContext sac = new StaticApplicationContext();
+ sac.registerSingleton("testAutoProxyCreator", TestAutoProxyCreator.class);
+ sac.registerSingleton("singletonFactoryToBeProxied", DummyFactory.class);
+ sac.refresh();
+
+ TestAutoProxyCreator tapc = (TestAutoProxyCreator) sac.getBean("testAutoProxyCreator");
+ tapc.testInterceptor.nrOfInvocations = 0;
+
+ FactoryBean factory = (FactoryBean) sac.getBean("&singletonFactoryToBeProxied");
+ assertTrue(AopUtils.isCglibProxy(factory));
+
+ TestBean tb = (TestBean) sac.getBean("singletonFactoryToBeProxied");
+ assertTrue(AopUtils.isCglibProxy(tb));
+ assertEquals(2, tapc.testInterceptor.nrOfInvocations);
+ tb.getAge();
+ assertEquals(3, tapc.testInterceptor.nrOfInvocations);
+ }
+
+ public void testAutoProxyCreatorWithFactoryBeanAndPrototype() {
+ StaticApplicationContext sac = new StaticApplicationContext();
+ sac.registerSingleton("testAutoProxyCreator", TestAutoProxyCreator.class);
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("singleton", "false");
+ sac.registerSingleton("prototypeFactoryToBeProxied", DummyFactory.class, pvs);
+
+ sac.refresh();
+
+ TestAutoProxyCreator tapc = (TestAutoProxyCreator) sac.getBean("testAutoProxyCreator");
+ tapc.testInterceptor.nrOfInvocations = 0;
+
+ FactoryBean prototypeFactory = (FactoryBean) sac.getBean("&prototypeFactoryToBeProxied");
+ assertTrue(AopUtils.isCglibProxy(prototypeFactory));
+ TestBean tb = (TestBean) sac.getBean("prototypeFactoryToBeProxied");
+ assertTrue(AopUtils.isCglibProxy(tb));
+
+ assertEquals(2, tapc.testInterceptor.nrOfInvocations);
+ tb.getAge();
+ assertEquals(3, tapc.testInterceptor.nrOfInvocations);
+ }
+
+ public void testAutoProxyCreatorWithFactoryBeanAndProxyObjectOnly() {
+ StaticApplicationContext sac = new StaticApplicationContext();
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("proxyFactoryBean", "false");
+ sac.registerSingleton("testAutoProxyCreator", TestAutoProxyCreator.class, pvs);
+
+ sac.registerSingleton("singletonFactoryToBeProxied", DummyFactory.class);
+
+ sac.refresh();
+
+ TestAutoProxyCreator tapc = (TestAutoProxyCreator) sac.getBean("testAutoProxyCreator");
+ tapc.testInterceptor.nrOfInvocations = 0;
+
+ FactoryBean factory = (FactoryBean) sac.getBean("&singletonFactoryToBeProxied");
+ assertFalse(AopUtils.isAopProxy(factory));
+
+ TestBean tb = (TestBean) sac.getBean("singletonFactoryToBeProxied");
+ assertTrue(AopUtils.isCglibProxy(tb));
+ assertEquals(0, tapc.testInterceptor.nrOfInvocations);
+ tb.getAge();
+ assertEquals(1, tapc.testInterceptor.nrOfInvocations);
+
+ TestBean tb2 = (TestBean) sac.getBean("singletonFactoryToBeProxied");
+ assertSame(tb, tb2);
+ assertEquals(1, tapc.testInterceptor.nrOfInvocations);
+ tb2.getAge();
+ assertEquals(2, tapc.testInterceptor.nrOfInvocations);
+ }
+
+ public void testAutoProxyCreatorWithFactoryBeanAndProxyFactoryBeanOnly() {
+ StaticApplicationContext sac = new StaticApplicationContext();
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("proxyObject", "false");
+ sac.registerSingleton("testAutoProxyCreator", TestAutoProxyCreator.class, pvs);
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("singleton", "false");
+ sac.registerSingleton("prototypeFactoryToBeProxied", DummyFactory.class, pvs);
+
+ sac.refresh();
+
+ TestAutoProxyCreator tapc = (TestAutoProxyCreator) sac.getBean("testAutoProxyCreator");
+ tapc.testInterceptor.nrOfInvocations = 0;
+
+ FactoryBean prototypeFactory = (FactoryBean) sac.getBean("&prototypeFactoryToBeProxied");
+ assertTrue(AopUtils.isCglibProxy(prototypeFactory));
+ TestBean tb = (TestBean) sac.getBean("prototypeFactoryToBeProxied");
+ assertFalse(AopUtils.isCglibProxy(tb));
+
+ assertEquals(2, tapc.testInterceptor.nrOfInvocations);
+ tb.getAge();
+ assertEquals(2, tapc.testInterceptor.nrOfInvocations);
+ }
+
+
+ public static class TestAutoProxyCreator extends AbstractAutoProxyCreator {
+
+ private boolean proxyFactoryBean = true;
+
+ private boolean proxyObject = true;
+
+ public TestInterceptor testInterceptor = new TestInterceptor();
+
+ public TestAutoProxyCreator() {
+ setProxyTargetClass(true);
+ setOrder(0);
+ }
+
+ public void setProxyFactoryBean(boolean proxyFactoryBean) {
+ this.proxyFactoryBean = proxyFactoryBean;
+ }
+
+ public void setProxyObject(boolean proxyObject) {
+ this.proxyObject = proxyObject;
+ }
+
+ protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String name, TargetSource customTargetSource) {
+ if (StaticMessageSource.class.equals(beanClass)) {
+ return DO_NOT_PROXY;
+ }
+ else if (name.endsWith("ToBeProxied")) {
+ boolean isFactoryBean = FactoryBean.class.isAssignableFrom(beanClass);
+ if ((this.proxyFactoryBean && isFactoryBean) || (this.proxyObject && !isFactoryBean)) {
+ return new Object[] {this.testInterceptor};
+ }
+ else {
+ return DO_NOT_PROXY;
+ }
+ }
+ else {
+ return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
+ }
+ }
+ }
+
+
+ /**
+ * Interceptor that counts the number of non-finalize method calls.
+ */
+ public static class TestInterceptor implements MethodInterceptor {
+
+ public int nrOfInvocations = 0;
+
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ if (!invocation.getMethod().getName().equals("finalize")) {
+ this.nrOfInvocations++;
+ }
+ return invocation.proceed();
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/BeanNameAutoProxyCreatorInitTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/BeanNameAutoProxyCreatorInitTests.java
new file mode 100644
index 00000000000..8553eefd363
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/BeanNameAutoProxyCreatorInitTests.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.framework.autoproxy;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * @author Juergen Hoeller
+ * @author Dave Syer
+ */
+public class BeanNameAutoProxyCreatorInitTests extends TestCase {
+
+ public void testIgnoreAdvisorThatIsCurrentlyCreation() {
+ ClassPathXmlApplicationContext ctx =
+ new ClassPathXmlApplicationContext("beanNameAutoProxyCreatorInitTests.xml", getClass());
+ TestBean bean = (TestBean) ctx.getBean("bean");
+ bean.setName("foo");
+ assertEquals("foo", bean.getName());
+ try {
+ bean.setName(null);
+ fail("Expected IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/BeanNameAutoProxyCreatorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/BeanNameAutoProxyCreatorTests.java
new file mode 100644
index 00000000000..7bb145c73b7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/BeanNameAutoProxyCreatorTests.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.framework.autoproxy;
+
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.framework.Advised;
+import org.springframework.aop.framework.CountingBeforeAdvice;
+import org.springframework.aop.framework.Lockable;
+import org.springframework.aop.framework.LockedException;
+import org.springframework.aop.framework.TimeStamped;
+import org.springframework.aop.interceptor.NopInterceptor;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * @author Rod Johnson
+ * @author Rob Harrop
+ */
+public class BeanNameAutoProxyCreatorTests extends TestCase {
+
+ private BeanFactory beanFactory;
+
+ protected void setUp() throws IOException {
+ // Note that we need an ApplicationContext, not just a BeanFactory,
+ // for post-processing and hence auto-proxying to work.
+ this.beanFactory = new ClassPathXmlApplicationContext("beanNameAutoProxyCreatorTests.xml", getClass());
+ }
+
+ public void testNoProxy() {
+ TestBean tb = (TestBean) beanFactory.getBean("noproxy");
+ assertFalse(AopUtils.isAopProxy(tb));
+ assertEquals("noproxy", tb.getName());
+ }
+
+ public void testJdkProxyWithExactNameMatch() {
+ ITestBean tb = (ITestBean) beanFactory.getBean("onlyJdk");
+ jdkAssertions(tb, 1);
+ assertEquals("onlyJdk", tb.getName());
+ }
+
+ public void testJdkProxyWithDoubleProxying() {
+ ITestBean tb = (ITestBean) beanFactory.getBean("doubleJdk");
+ jdkAssertions(tb, 2);
+ assertEquals("doubleJdk", tb.getName());
+ }
+
+ public void testJdkIntroduction() {
+ ITestBean tb = (ITestBean) beanFactory.getBean("introductionUsingJdk");
+ NopInterceptor nop = (NopInterceptor) beanFactory.getBean("introductionNopInterceptor");
+ assertEquals(0, nop.getCount());
+ assertTrue(AopUtils.isJdkDynamicProxy(tb));
+ int age = 5;
+ tb.setAge(age);
+ assertEquals(age, tb.getAge());
+ assertTrue("Introduction was made", tb instanceof TimeStamped);
+ assertEquals(0, ((TimeStamped) tb).getTimeStamp());
+ assertEquals(3, nop.getCount());
+ assertEquals("introductionUsingJdk", tb.getName());
+
+ ITestBean tb2 = (ITestBean) beanFactory.getBean("second-introductionUsingJdk");
+
+ // Check two per-instance mixins were distinct
+ Lockable lockable1 = (Lockable) tb;
+ Lockable lockable2 = (Lockable) tb2;
+ assertFalse(lockable1.locked());
+ assertFalse(lockable2.locked());
+ tb.setAge(65);
+ assertEquals(65, tb.getAge());
+ lockable1.lock();
+ assertTrue(lockable1.locked());
+ // Shouldn't affect second
+ assertFalse(lockable2.locked());
+ // Can still mod second object
+ tb2.setAge(12);
+ // But can't mod first
+ try {
+ tb.setAge(6);
+ fail("Mixin should have locked this object");
+ }
+ catch (LockedException ex) {
+ // Ok
+ }
+ }
+
+ public void testJdkIntroductionAppliesToCreatedObjectsNotFactoryBean() {
+ ITestBean tb = (ITestBean) beanFactory.getBean("factory-introductionUsingJdk");
+ NopInterceptor nop = (NopInterceptor) beanFactory.getBean("introductionNopInterceptor");
+ assertEquals("NOP should not have done any work yet", 0, nop.getCount());
+ assertTrue(AopUtils.isJdkDynamicProxy(tb));
+ int age = 5;
+ tb.setAge(age);
+ assertEquals(age, tb.getAge());
+ assertTrue("Introduction was made", tb instanceof TimeStamped);
+ assertEquals(0, ((TimeStamped) tb).getTimeStamp());
+ assertEquals(3, nop.getCount());
+
+ ITestBean tb2 = (ITestBean) beanFactory.getBean("second-introductionUsingJdk");
+
+ // Check two per-instance mixins were distinct
+ Lockable lockable1 = (Lockable) tb;
+ Lockable lockable2 = (Lockable) tb2;
+ assertFalse(lockable1.locked());
+ assertFalse(lockable2.locked());
+ tb.setAge(65);
+ assertEquals(65, tb.getAge());
+ lockable1.lock();
+ assertTrue(lockable1.locked());
+ // Shouldn't affect second
+ assertFalse(lockable2.locked());
+ // Can still mod second object
+ tb2.setAge(12);
+ // But can't mod first
+ try {
+ tb.setAge(6);
+ fail("Mixin should have locked this object");
+ }
+ catch (LockedException ex) {
+ // Ok
+ }
+ }
+
+ public void testJdkProxyWithWildcardMatch() {
+ ITestBean tb = (ITestBean) beanFactory.getBean("jdk1");
+ jdkAssertions(tb, 1);
+ assertEquals("jdk1", tb.getName());
+ }
+
+ public void testCglibProxyWithWildcardMatch() {
+ TestBean tb = (TestBean) beanFactory.getBean("cglib1");
+ cglibAssertions(tb);
+ assertEquals("cglib1", tb.getName());
+ }
+
+ public void testWithFrozenProxy() {
+ ITestBean testBean = (ITestBean) beanFactory.getBean("frozenBean");
+ assertTrue(((Advised)testBean).isFrozen());
+ }
+
+ private void jdkAssertions(ITestBean tb, int nopInterceptorCount) {
+ NopInterceptor nop = (NopInterceptor) beanFactory.getBean("nopInterceptor");
+ assertEquals(0, nop.getCount());
+ assertTrue(AopUtils.isJdkDynamicProxy(tb));
+ int age = 5;
+ tb.setAge(age);
+ assertEquals(age, tb.getAge());
+ assertEquals(2 * nopInterceptorCount, nop.getCount());
+ }
+
+ /**
+ * Also has counting before advice.
+ */
+ private void cglibAssertions(TestBean tb) {
+ CountingBeforeAdvice cba = (CountingBeforeAdvice) beanFactory.getBean("countingBeforeAdvice");
+ NopInterceptor nop = (NopInterceptor) beanFactory.getBean("nopInterceptor");
+ assertEquals(0, cba.getCalls());
+ assertEquals(0, nop.getCount());
+ assertTrue(AopUtils.isCglibProxy(tb));
+ int age = 5;
+ tb.setAge(age);
+ assertEquals(age, tb.getAge());
+ assertEquals(2, nop.getCount());
+ assertEquals(2, cba.getCalls());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/CountingTestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/CountingTestBean.java
new file mode 100644
index 00000000000..bd377aed847
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/CountingTestBean.java
@@ -0,0 +1,37 @@
+/*
+ * $Id: CountingTestBean.java,v 1.2 2005/03/25 09:28:17 jhoeller Exp $
+ */
+
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework.autoproxy;
+
+import org.springframework.beans.TestBean;
+
+/**
+ * @author Juergen Hoeller
+ * @since 15.03.2005
+ */
+public class CountingTestBean extends TestBean {
+
+ public static int count = 0;
+
+ public CountingTestBean() {
+ count++;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/CreatesTestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/CreatesTestBean.java
new file mode 100644
index 00000000000..f95da4b0620
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/CreatesTestBean.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework.autoproxy;
+
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.FactoryBean;
+
+/**
+ *
+ * @author Rod Johnson
+ */
+public class CreatesTestBean implements FactoryBean {
+
+ /**
+ * @see org.springframework.beans.factory.FactoryBean#getObject()
+ */
+ public Object getObject() throws Exception {
+ return new TestBean();
+ }
+
+ /**
+ * @see org.springframework.beans.factory.FactoryBean#getObjectType()
+ */
+ public Class getObjectType() {
+ return TestBean.class;
+ }
+
+ /**
+ * @see org.springframework.beans.factory.FactoryBean#isSingleton()
+ */
+ public boolean isSingleton() {
+ return true;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/NeverMatchAdvisor.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/NeverMatchAdvisor.java
new file mode 100644
index 00000000000..83377a8b712
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/NeverMatchAdvisor.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework.autoproxy;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+import org.springframework.aop.interceptor.NopInterceptor;
+import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
+
+/**
+ *
+ * @author Rod Johnson
+ */
+public class NeverMatchAdvisor extends StaticMethodMatcherPointcutAdvisor {
+
+ public NeverMatchAdvisor() {
+ super(new NopInterceptor());
+ }
+
+ /**
+ * This method is solely to allow us to create a mixture of dependencies in
+ * the bean definitions. The dependencies don't have any meaning, and don't
+ * do anything.
+ */
+ public void setDependencies(List l) {
+
+ }
+
+ /**
+ * @see org.springframework.aop.MethodMatcher#matches(java.lang.reflect.Method, java.lang.Class)
+ */
+ public boolean matches(Method m, Class targetClass) {
+ //System.err.println("NeverMAtch test");
+ return false;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/NoSetters.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/NoSetters.java
new file mode 100644
index 00000000000..5ecd63cc928
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/NoSetters.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework.autoproxy;
+
+/**
+ *
+ * @author Rod Johnson
+ */
+public class NoSetters {
+
+ public void A() {
+
+ }
+
+ public int getB() {
+ return -1;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/NullChecker.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/NullChecker.java
new file mode 100644
index 00000000000..343bf82b224
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/NullChecker.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.framework.autoproxy;
+
+import java.lang.reflect.Method;
+
+import org.springframework.aop.MethodBeforeAdvice;
+
+/**
+ * @author Dave Syer
+ */
+public class NullChecker implements MethodBeforeAdvice {
+
+ public void before(Method method, Object[] args, Object target) throws Throwable {
+ check(args);
+ }
+
+ private void check(Object[] args) {
+ for (int i = 0; i < args.length; i++) {
+ if (args[i] == null) {
+ throw new IllegalArgumentException("Null argument at position " + i);
+ }
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/OrderedTxCheckAdvisor.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/OrderedTxCheckAdvisor.java
new file mode 100644
index 00000000000..aa0c134ceb0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/OrderedTxCheckAdvisor.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.framework.autoproxy;
+
+import java.lang.reflect.Method;
+
+import org.springframework.aop.framework.CountingBeforeAdvice;
+import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.transaction.NoTransactionException;
+import org.springframework.transaction.interceptor.TransactionInterceptor;
+
+/**
+ * Before advisor that allow us to manipulate ordering to check
+ * that superclass sorting works correctly.
+ *
+ *
It doesn't actually do anything except count
+ * method invocations and check for presence of transaction context.
+ * Matches setters.
+ *
+ * @author Rod Johnson
+ */
+public class OrderedTxCheckAdvisor extends StaticMethodMatcherPointcutAdvisor implements InitializingBean {
+
+ /**
+ * Should we insist on the presence of a transaction attribute or refuse to accept one?
+ */
+ private boolean requireTransactionContext = false;
+
+
+ public void setRequireTransactionContext(boolean requireTransactionContext) {
+ this.requireTransactionContext = requireTransactionContext;
+ }
+
+ public boolean isRequireTransactionContext() {
+ return requireTransactionContext;
+ }
+
+
+ public CountingBeforeAdvice getCountingBeforeAdvice() {
+ return (CountingBeforeAdvice) getAdvice();
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ setAdvice(new TxCountingBeforeAdvice());
+ }
+
+ public boolean matches(Method method, Class targetClass) {
+ return method.getName().startsWith("setAge");
+ }
+
+
+ private class TxCountingBeforeAdvice extends CountingBeforeAdvice {
+
+ public void before(Method method, Object[] args, Object target) throws Throwable {
+ // do transaction checks
+ if (requireTransactionContext) {
+ TransactionInterceptor.currentTransactionStatus();
+ }
+ else {
+ try {
+ TransactionInterceptor.currentTransactionStatus();
+ throw new RuntimeException("Shouldn't have a transaction");
+ }
+ catch (NoTransactionException ex) {
+ // this is Ok
+ }
+ }
+ super.before(method, args, target);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/Rollback.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/Rollback.java
new file mode 100644
index 00000000000..3b9caa59d80
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/Rollback.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework.autoproxy;
+
+import org.springframework.transaction.interceptor.TransactionInterceptor;
+
+
+
+/**
+ * @org.springframework.enterpriseservices.Pooling (size=10)
+ * @org.springframework.transaction.interceptor.DefaultTransaction ( timeout=-1 )
+ */
+public class Rollback {
+
+ /**
+ * Inherits transaction attribute.
+ * Illustrates programmatic rollback.
+ * @param rollbackOnly
+ */
+ public void rollbackOnly(boolean rollbackOnly) {
+ if (rollbackOnly) {
+ setRollbackOnly();
+ }
+ }
+
+ /**
+ * Extracted in a protected method to facilitate testing
+ */
+ protected void setRollbackOnly() {
+ TransactionInterceptor.currentTransactionStatus().setRollbackOnly();
+ }
+
+ /**
+ * @org.springframework.transaction.interceptor.RuleBasedTransaction ( timeout=-1 )
+ * @org.springframework.transaction.interceptor.RollbackRule ( "java.lang.Exception" )
+ * @org.springframework.transaction.interceptor.NoRollbackRule ( "ServletException" )
+ */
+ public void echoException(Exception ex) throws Exception {
+ if (ex != null)
+ throw ex;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/SelectivePrototypeTargetSourceCreator.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/SelectivePrototypeTargetSourceCreator.java
new file mode 100644
index 00000000000..cf8b2ddc63e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/SelectivePrototypeTargetSourceCreator.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.framework.autoproxy;
+
+import org.springframework.aop.framework.autoproxy.target.AbstractBeanFactoryBasedTargetSourceCreator;
+import org.springframework.aop.target.AbstractBeanFactoryBasedTargetSource;
+import org.springframework.aop.target.PrototypeTargetSource;
+
+/**
+ * Overrides generic PrototypeTargetSourceCreator to create a prototype only for beans
+ * with names beginning with "prototype".
+ *
+ * @author Rod Johnson
+ */
+public class SelectivePrototypeTargetSourceCreator extends AbstractBeanFactoryBasedTargetSourceCreator {
+
+ protected AbstractBeanFactoryBasedTargetSource createBeanFactoryBasedTargetSource(
+ Class beanClass, String beanName) {
+ if (!beanName.startsWith("prototype")) {
+ return null;
+ }
+ return new PrototypeTargetSource();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/advisorAutoProxyCreator.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/advisorAutoProxyCreator.xml
new file mode 100644
index 00000000000..a685b944529
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/advisorAutoProxyCreator.xml
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+
+ Matches all Advisors in the factory: we don't use a prefix
+
+
+
+
+
+
+ 9
+ false
+
+
+
+ 11
+ true
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+ PROPAGATION_REQUIRED
+ PROPAGATION_REQUIRED
+ PROPAGATION_REQUIRED,+javax.servlet.ServletException,-java.lang.Exception
+
+
+
+
+
+
+
+
+
+
+
+ 10
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.springframework.beans.ITestBean.getName
+
+
+
+
+
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/advisorAutoProxyCreatorWithCommonInterceptors.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/advisorAutoProxyCreatorWithCommonInterceptors.xml
new file mode 100644
index 00000000000..d24029bbf4b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/advisorAutoProxyCreatorWithCommonInterceptors.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+ Matches all Advisors in the factory: we don't use a prefix
+
+
+
+
+
+
+ nopInterceptor
+
+
+
+
+
+
+
+
+
+ 4
+
+
+
+ 4
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/beanNameAutoProxyCreatorInitTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/beanNameAutoProxyCreatorInitTests.xml
new file mode 100644
index 00000000000..53d945697e8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/beanNameAutoProxyCreatorInitTests.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ .*\.set[a-zA-Z]*(.*)
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/beanNameAutoProxyCreatorTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/beanNameAutoProxyCreatorTests.xml
new file mode 100644
index 00000000000..0eb5a4e870e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/beanNameAutoProxyCreatorTests.xml
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Automatically proxies using JDK dynamic proxies
+
+ jdk*,onlyJdk,doubleJdk
+
+
+ nopInterceptor
+
+
+
+
+
+
+
+
+
+
+
+
+ cglib*
+
+
+
+ Use the inherited ProxyConfig property to force CGLIB proxying
+ true
+
+
+ Interceptors and Advisors to apply automatically
+
+ nopInterceptor
+ countingBeforeAdvice
+
+
+
+
+
+
+ Illustrates a JDK introduction
+
+ *introductionUsingJdk
+
+
+ introductionNopInterceptor
+ timestampIntroduction
+ lockableAdvisor
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ introductionUsingJdk
+
+
+
+ second-introductionUsingJdk
+
+
+
+
+
+
+
+ jdk1
+
+
+
+
+
+
+
+ cglib1
+
+
+
+ onlyJdk
+
+
+
+ doubleJdk
+
+
+
+ noproxy
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/customTargetSource.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/customTargetSource.xml
new file mode 100644
index 00000000000..2585661234f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/customTargetSource.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Rod
+
+
+
+
+ Rod
+
+
+
+
+ Rod
+
+
+
+
+ Kerry
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/optimizedAutoProxyCreator.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/optimizedAutoProxyCreator.xml
new file mode 100644
index 00000000000..aa771d402f0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/optimizedAutoProxyCreator.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ .*beans.I?TestBean.*
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/quickTargetSource.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/quickTargetSource.xml
new file mode 100644
index 00000000000..949ad7cab9e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/autoproxy/quickTargetSource.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Rod
+
+
+
+
+ Kerry
+
+
+
+
+ Rod
+
+
+
+
+
+ Rod
+
+
+
+
+
+ Rod
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/frozenProxyFactoryBean.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/frozenProxyFactoryBean.xml
new file mode 100644
index 00000000000..8b5b7bf70e7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/frozenProxyFactoryBean.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+ custom
+ 666
+
+
+
+
+
+
+
+ org.springframework.beans.ITestBean
+
+
+ debugInterceptor
+ true
+ true
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/innerBeanTarget.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/innerBeanTarget.xml
new file mode 100644
index 00000000000..f36964b41a0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/innerBeanTarget.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ innerBeanTarget
+
+
+
+
+ nopInterceptor
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/invalidProxyFactory.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/invalidProxyFactory.xml
new file mode 100644
index 00000000000..de65fec0fe1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/invalidProxyFactory.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+ org.springframework.beans.ITestBean
+
+
+
+
+
+ org.springframework.beans.ITestBean
+ global*
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/prototypeTarget.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/prototypeTarget.xml
new file mode 100644
index 00000000000..21d1eedb408
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/prototypeTarget.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+ org.springframework.aop.framework.PrototypeTargetTests$TestBean
+
+
+ false
+
+
+
+ testInterceptor
+ testBeanTarget
+
+
+
+
+
+
+ org.springframework.aop.framework.PrototypeTargetTests$TestBean
+
+
+ true
+
+
+
+ testInterceptor
+ testBeanTarget
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/prototypeTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/prototypeTests.xml
new file mode 100644
index 00000000000..33332243157
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/prototypeTests.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+ 10
+
+
+
+ 10
+
+
+
+
+
+ debugInterceptor,test
+
+
+
+ debugInterceptor,prototypeTarget
+ false
+
+
+
+ debugInterceptor,prototypeTarget
+ false
+
+ true
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/proxyFactoryBeanAutowiringTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/proxyFactoryBeanAutowiringTests.xml
new file mode 100644
index 00000000000..b732d7af434
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/proxyFactoryBeanAutowiringTests.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/proxyFactoryDoubleTargetSourceTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/proxyFactoryDoubleTargetSourceTests.xml
new file mode 100644
index 00000000000..0784675bb99
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/proxyFactoryDoubleTargetSourceTests.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+ Eve
+
+
+
+
+
+ Adam
+
+
+
+
+
+
+
+
+
+
+
+ org.springframework.beans.ITestBean
+
+ countingBeforeAdvice,adamTargetSource
+
+
+
+
+
+
+ org.springframework.beans.ITestBean
+
+ adam
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/proxyFactoryTargetSourceNotLastTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/proxyFactoryTargetSourceNotLastTests.xml
new file mode 100644
index 00000000000..b1b19721255
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/proxyFactoryTargetSourceNotLastTests.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+ Adam
+
+
+
+
+
+
+ org.springframework.beans.ITestBean
+
+ adam,countingBeforeAdvice
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/proxyFactoryTargetSourceTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/proxyFactoryTargetSourceTests.xml
new file mode 100644
index 00000000000..c5e48cbbbae
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/proxyFactoryTargetSourceTests.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+ Adam
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nopInterceptor,targetSource
+
+
+
+
+
+
+
+ org.springframework.beans.ITestBean
+ nopInterceptor,unsupportedInterceptor
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/proxyFactoryTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/proxyFactoryTests.xml
new file mode 100644
index 00000000000..09e68277731
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/proxyFactoryTests.xml
@@ -0,0 +1,171 @@
+
+
+
+
+
+
+
+ custom
+ 666
+
+
+
+
+
+ org.springframework.beans.ITestBean
+
+ debugInterceptor
+
+
+
+
+
+
+ org.springframework.beans.ITestBean
+
+
+ global*,test
+
+
+
+
+
+
+ org.springframework.beans.ITestBean
+
+
+ false
+ test
+
+
+
+
+
+ org.springframework.beans.ITestBean
+
+
+ false
+ test
+
+
+
+ true
+
+ debugInterceptor
+
+
+
+ true
+ false
+ test
+
+
+
+ true
+ testCircleTarget1
+
+
+
+ custom
+ 666
+
+
+
+
+ true
+ testCircleTarget2
+
+
+
+ custom
+ 666
+
+
+
+
+ org.springframework.beans.ITestBean
+ pointcutForVoid
+ test
+
+
+
+
+
+
+
+
+ org.springframework.context.ApplicationListener
+ debugInterceptor,global*,target2
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.springframework.beans.ITestBean
+ false
+
+
+ prototypeLockMixinAdvisor
+ prototypeTestBean
+
+
+
+
+
+
+
+
+
+ org.springframework.beans.ITestBean
+ org.springframework.aop.framework.Lockable
+
+
+ false
+
+
+
+ prototypeLockMixinInterceptor
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/serializationTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/serializationTests.xml
new file mode 100644
index 00000000000..aa12d497b12
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/serializationTests.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+ serializableNopInterceptor
+ org.springframework.beans.Person
+
+
+ serializableSingleton
+
+
+
+
+
+ serializablePrototype
+
+
+
+ serializableNopInterceptor,prototypeTarget
+ org.springframework.beans.Person
+ false
+
+
+
+ nopInterceptor
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/throwsAdvice.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/throwsAdvice.xml
new file mode 100644
index 00000000000..5185ae39299
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/throwsAdvice.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ countingBeforeAdvice,nopInterceptor,throwsAdvice,target
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/withDependencyChecking.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/withDependencyChecking.xml
new file mode 100644
index 00000000000..1994ce20287
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/framework/withDependencyChecking.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/ConcurrencyThrottleInterceptorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/ConcurrencyThrottleInterceptorTests.java
new file mode 100644
index 00000000000..bcb15ce6654
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/ConcurrencyThrottleInterceptorTests.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.interceptor;
+
+import junit.framework.TestCase;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.aop.framework.Advised;
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.beans.DerivedTestBean;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.util.SerializationTestUtils;
+
+/**
+ * @author Juergen Hoeller
+ * @since 06.04.2004
+ */
+public class ConcurrencyThrottleInterceptorTests extends TestCase {
+
+ protected static final Log logger = LogFactory.getLog(ConcurrencyThrottleInterceptorTests.class);
+
+ public static final int NR_OF_THREADS = 100;
+
+ public static final int NR_OF_ITERATIONS = 1000;
+
+
+ public void testSerializable() throws Exception {
+ DerivedTestBean tb = new DerivedTestBean();
+ ProxyFactory proxyFactory = new ProxyFactory();
+ proxyFactory.setInterfaces(new Class[] {ITestBean.class});
+ ConcurrencyThrottleInterceptor cti = new ConcurrencyThrottleInterceptor();
+ proxyFactory.addAdvice(cti);
+ proxyFactory.setTarget(tb);
+ ITestBean proxy = (ITestBean) proxyFactory.getProxy();
+ proxy.getAge();
+
+ ITestBean serializedProxy = (ITestBean) SerializationTestUtils.serializeAndDeserialize(proxy);
+ Advised advised = (Advised) serializedProxy;
+ ConcurrencyThrottleInterceptor serializedCti =
+ (ConcurrencyThrottleInterceptor) advised.getAdvisors()[0].getAdvice();
+ assertEquals(cti.getConcurrencyLimit(), serializedCti.getConcurrencyLimit());
+ serializedProxy.getAge();
+ }
+
+ public void testMultipleThreadsWithLimit1() {
+ testMultipleThreads(1);
+ }
+
+ public void testMultipleThreadsWithLimit10() {
+ testMultipleThreads(10);
+ }
+
+ private void testMultipleThreads(int concurrencyLimit) {
+ TestBean tb = new TestBean();
+ ProxyFactory proxyFactory = new ProxyFactory();
+ proxyFactory.setInterfaces(new Class[] {ITestBean.class});
+ ConcurrencyThrottleInterceptor cti = new ConcurrencyThrottleInterceptor();
+ cti.setConcurrencyLimit(concurrencyLimit);
+ proxyFactory.addAdvice(cti);
+ proxyFactory.setTarget(tb);
+ ITestBean proxy = (ITestBean) proxyFactory.getProxy();
+
+ Thread[] threads = new Thread[NR_OF_THREADS];
+ for (int i = 0; i < NR_OF_THREADS; i++) {
+ threads[i] = new ConcurrencyThread(proxy, null);
+ threads[i].start();
+ }
+ for (int i = 0; i < NR_OF_THREADS / 10; i++) {
+ try {
+ Thread.sleep(5);
+ }
+ catch (InterruptedException ex) {
+ ex.printStackTrace();
+ }
+ threads[i] = new ConcurrencyThread(proxy,
+ i % 2 == 0 ? (Throwable) new OutOfMemoryError() : (Throwable) new IllegalStateException());
+ threads[i].start();
+ }
+ for (int i = 0; i < NR_OF_THREADS; i++) {
+ try {
+ threads[i].join();
+ }
+ catch (InterruptedException ex) {
+ ex.printStackTrace();
+ }
+ }
+ }
+
+
+ private static class ConcurrencyThread extends Thread {
+
+ private ITestBean proxy;
+ private Throwable ex;
+
+ public ConcurrencyThread(ITestBean proxy, Throwable ex) {
+ this.proxy = proxy;
+ this.ex = ex;
+ }
+
+ public void run() {
+ if (this.ex != null) {
+ try {
+ this.proxy.exceptional(this.ex);
+ }
+ catch (RuntimeException ex) {
+ if (ex == this.ex) {
+ logger.debug("Expected exception thrown", ex);
+ }
+ else {
+ // should never happen
+ ex.printStackTrace();
+ }
+ }
+ catch (Error err) {
+ if (err == this.ex) {
+ logger.debug("Expected exception thrown", err);
+ }
+ else {
+ // should never happen
+ ex.printStackTrace();
+ }
+ }
+ catch (Throwable ex) {
+ // should never happen
+ ex.printStackTrace();
+ }
+ }
+ else {
+ for (int i = 0; i < NR_OF_ITERATIONS; i++) {
+ this.proxy.getName();
+ }
+ }
+ logger.debug("finished");
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/CustomizableTraceInterceptorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/CustomizableTraceInterceptorTests.java
new file mode 100644
index 00000000000..9ad18025fc8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/CustomizableTraceInterceptorTests.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.aop.interceptor;
+
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+import org.aopalliance.intercept.MethodInvocation;
+import org.apache.commons.logging.Log;
+import org.easymock.MockControl;
+
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Rob Harrop
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class CustomizableTraceInterceptorTests extends TestCase {
+
+ public void testSetEmptyEnterMessage() {
+ new AssertThrows(IllegalArgumentException.class, "Must not be able to set empty enter message") {
+ public void test() throws Exception {
+ new CustomizableTraceInterceptor().setEnterMessage("");
+ }
+ }.runTest();
+ }
+
+ public void testSetEnterMessageWithReturnValuePlaceholder() {
+ new AssertThrows(IllegalArgumentException.class, "Must not be able to set enter message with return value placeholder") {
+ public void test() throws Exception {
+ new CustomizableTraceInterceptor().setEnterMessage(CustomizableTraceInterceptor.PLACEHOLDER_RETURN_VALUE);
+ }
+ }.runTest();
+ }
+
+ public void testSetEnterMessageWithExceptionPlaceholder() {
+ new AssertThrows(IllegalArgumentException.class, "Must not be able to set enter message with exception placeholder") {
+ public void test() throws Exception {
+ new CustomizableTraceInterceptor().setEnterMessage(CustomizableTraceInterceptor.PLACEHOLDER_EXCEPTION);
+ }
+ }.runTest();
+ }
+
+ public void testSetEnterMessageWithInvocationTimePlaceholder() {
+ new AssertThrows(IllegalArgumentException.class, "Must not be able to set enter message with invocation time placeholder") {
+ public void test() throws Exception {
+ new CustomizableTraceInterceptor().setEnterMessage(CustomizableTraceInterceptor.PLACEHOLDER_INVOCATION_TIME);
+ }
+ }.runTest();
+ }
+
+ public void testSetEmptyExitMessage() {
+ new AssertThrows(IllegalArgumentException.class, "Must not be able to set empty exit message") {
+ public void test() throws Exception {
+ new CustomizableTraceInterceptor().setExitMessage("");
+ }
+ }.runTest();
+ }
+
+ public void testSetExitMessageWithExceptionPlaceholder() {
+ new AssertThrows(IllegalArgumentException.class, "Must not be able to set exit message with exception placeholder") {
+ public void test() throws Exception {
+ new CustomizableTraceInterceptor().setExitMessage(CustomizableTraceInterceptor.PLACEHOLDER_EXCEPTION);
+ }
+ }.runTest();
+ }
+
+ public void testSetEmptyExceptionMessage() {
+ new AssertThrows(IllegalArgumentException.class, "Must not be able to set empty exception message") {
+ public void test() throws Exception {
+ new CustomizableTraceInterceptor().setExceptionMessage("");
+ }
+ }.runTest();
+ }
+
+ public void testSetExceptionMethodWithReturnValuePlaceholder() {
+ new AssertThrows(IllegalArgumentException.class, "Must not be able to set exception message with return value placeholder") {
+ public void test() throws Exception {
+ new CustomizableTraceInterceptor().setExceptionMessage(CustomizableTraceInterceptor.PLACEHOLDER_RETURN_VALUE);
+ }
+ }.runTest();
+ }
+
+ public void testSunnyDayPathLogsCorrectly() throws Throwable {
+ MockControl mockLog = MockControl.createControl(Log.class);
+ Log log = (Log) mockLog.getMock();
+
+ MockControl mockMethodInvocation = MockControl.createControl(MethodInvocation.class);
+ MethodInvocation methodInvocation = (MethodInvocation) mockMethodInvocation.getMock();
+
+ Method toString = String.class.getMethod("toString", new Class[]{});
+
+ log.isTraceEnabled();
+ mockLog.setReturnValue(true);
+ methodInvocation.getMethod();
+ mockMethodInvocation.setReturnValue(toString, 4);
+ methodInvocation.getThis();
+ mockMethodInvocation.setReturnValue(this, 2);
+ log.trace("Some tracing output");
+ mockLog.setMatcher(MockControl.ALWAYS_MATCHER);
+ methodInvocation.proceed();
+ mockMethodInvocation.setReturnValue(null);
+ log.trace("Some more tracing output");
+ mockLog.setMatcher(MockControl.ALWAYS_MATCHER);
+ mockLog.setVoidCallable();
+
+ mockMethodInvocation.replay();
+ mockLog.replay();
+
+ CustomizableTraceInterceptor interceptor = new StubCustomizableTraceInterceptor(log);
+ interceptor.invoke(methodInvocation);
+
+ mockLog.verify();
+ mockMethodInvocation.verify();
+ }
+
+ public void testExceptionPathLogsCorrectly() throws Throwable {
+ MockControl mockLog = MockControl.createControl(Log.class);
+ Log log = (Log) mockLog.getMock();
+
+ MockControl mockMethodInvocation = MockControl.createControl(MethodInvocation.class);
+ MethodInvocation methodInvocation = (MethodInvocation) mockMethodInvocation.getMock();
+
+ Method toString = String.class.getMethod("toString", new Class[]{});
+
+ log.isTraceEnabled();
+ mockLog.setReturnValue(true);
+ methodInvocation.getMethod();
+ mockMethodInvocation.setReturnValue(toString, 4);
+ methodInvocation.getThis();
+ mockMethodInvocation.setReturnValue(this, 2);
+ log.trace("Some tracing output");
+ mockLog.setMatcher(MockControl.ALWAYS_MATCHER);
+ methodInvocation.proceed();
+ IllegalArgumentException exception = new IllegalArgumentException();
+ mockMethodInvocation.setThrowable(exception);
+ log.trace("Some more tracing output", exception);
+ mockLog.setMatcher(MockControl.ALWAYS_MATCHER);
+ mockLog.setVoidCallable();
+
+ mockMethodInvocation.replay();
+ mockLog.replay();
+
+ CustomizableTraceInterceptor interceptor = new StubCustomizableTraceInterceptor(log);
+ try {
+ interceptor.invoke(methodInvocation);
+ fail("Must have propagated the IllegalArgumentException.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ mockLog.verify();
+ mockMethodInvocation.verify();
+ }
+
+ public void testSunnyDayPathLogsCorrectlyWithPrettyMuchAllPlaceholdersMatching() throws Throwable {
+ MockControl mockLog = MockControl.createControl(Log.class);
+ Log log = (Log) mockLog.getMock();
+
+ MockControl mockMethodInvocation = MockControl.createControl(MethodInvocation.class);
+ MethodInvocation methodInvocation = (MethodInvocation) mockMethodInvocation.getMock();
+
+ Method toString = String.class.getMethod("toString", new Class[0]);
+ Object[] arguments = new Object[]{"$ One \\$", new Long(2)};
+
+ log.isTraceEnabled();
+ mockLog.setReturnValue(true);
+ methodInvocation.getMethod();
+ mockMethodInvocation.setReturnValue(toString, 7);
+ methodInvocation.getThis();
+ mockMethodInvocation.setReturnValue(this, 2);
+ methodInvocation.getArguments();
+ mockMethodInvocation.setReturnValue(arguments, 2);
+ log.trace("Some tracing output");
+ mockLog.setMatcher(MockControl.ALWAYS_MATCHER);
+ methodInvocation.proceed();
+ mockMethodInvocation.setReturnValue("Hello!");
+ log.trace("Some more tracing output");
+ mockLog.setMatcher(MockControl.ALWAYS_MATCHER);
+ mockLog.setVoidCallable();
+
+ mockMethodInvocation.replay();
+ mockLog.replay();
+
+ CustomizableTraceInterceptor interceptor = new StubCustomizableTraceInterceptor(log);
+ interceptor.setEnterMessage(new StringBuffer().append("Entering the '").append(CustomizableTraceInterceptor.PLACEHOLDER_METHOD_NAME).append("' method of the [").append(CustomizableTraceInterceptor.PLACEHOLDER_TARGET_CLASS_NAME).append("] class with the following args (").append(CustomizableTraceInterceptor.PLACEHOLDER_ARGUMENTS).append(") and arg types (").append(CustomizableTraceInterceptor.PLACEHOLDER_ARGUMENT_TYPES).append(").").toString());
+ interceptor.setExitMessage(new StringBuffer().append("Exiting the '").append(CustomizableTraceInterceptor.PLACEHOLDER_METHOD_NAME).append("' method of the [").append(CustomizableTraceInterceptor.PLACEHOLDER_TARGET_CLASS_SHORT_NAME).append("] class with the following args (").append(CustomizableTraceInterceptor.PLACEHOLDER_ARGUMENTS).append(") and arg types (").append(CustomizableTraceInterceptor.PLACEHOLDER_ARGUMENT_TYPES).append("), returning '").append(CustomizableTraceInterceptor.PLACEHOLDER_RETURN_VALUE).append("' and taking '").append(CustomizableTraceInterceptor.PLACEHOLDER_INVOCATION_TIME).append("' this long.").toString());
+ interceptor.invoke(methodInvocation);
+
+ mockLog.verify();
+ mockMethodInvocation.verify();
+ }
+
+
+ private static class StubCustomizableTraceInterceptor extends CustomizableTraceInterceptor {
+
+ private final Log log;
+
+ public StubCustomizableTraceInterceptor(Log log) {
+ super.setUseDynamicLogger(false);
+ this.log = log;
+ }
+
+ protected Log getLoggerForInvocation(MethodInvocation invocation) {
+ return this.log;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/DebugInterceptorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/DebugInterceptorTests.java
new file mode 100644
index 00000000000..596602a17f8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/DebugInterceptorTests.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.interceptor;
+
+import junit.framework.TestCase;
+import org.aopalliance.intercept.MethodInvocation;
+import org.apache.commons.logging.Log;
+import org.easymock.MockControl;
+
+/**
+ * Unit tests for the {@link DebugInterceptor} class.
+ *
+ * @author Rick Evans
+ */
+public final class DebugInterceptorTests extends TestCase {
+
+ public void testSunnyDayPathLogsCorrectly() throws Throwable {
+ MockControl mockLog = MockControl.createControl(Log.class);
+ final Log log = (Log) mockLog.getMock();
+
+ MockControl mockMethodInvocation = MockControl.createControl(MethodInvocation.class);
+ MethodInvocation methodInvocation = (MethodInvocation) mockMethodInvocation.getMock();
+
+ log.isTraceEnabled();
+ mockLog.setReturnValue(true);
+ log.trace("Some tracing output");
+ mockLog.setMatcher(MockControl.ALWAYS_MATCHER);
+ methodInvocation.proceed();
+ mockMethodInvocation.setReturnValue(null);
+ log.trace("Some more tracing output");
+ mockLog.setMatcher(MockControl.ALWAYS_MATCHER);
+ mockLog.setVoidCallable();
+
+ mockMethodInvocation.replay();
+ mockLog.replay();
+
+ DebugInterceptor interceptor = new StubDebugInterceptor(log);
+ interceptor.invoke(methodInvocation);
+ checkCallCountTotal(interceptor);
+
+ mockLog.verify();
+ mockMethodInvocation.verify();
+ }
+
+ public void testExceptionPathStillLogsCorrectly() throws Throwable {
+ MockControl mockLog = MockControl.createControl(Log.class);
+ final Log log = (Log) mockLog.getMock();
+
+ MockControl mockMethodInvocation = MockControl.createControl(MethodInvocation.class);
+ final MethodInvocation methodInvocation = (MethodInvocation) mockMethodInvocation.getMock();
+
+ log.isTraceEnabled();
+ mockLog.setReturnValue(true);
+ log.trace("Some tracing output");
+ mockLog.setMatcher(MockControl.ALWAYS_MATCHER);
+ methodInvocation.proceed();
+ IllegalArgumentException exception = new IllegalArgumentException();
+ mockMethodInvocation.setThrowable(exception);
+ log.trace("Some more tracing output", exception);
+ mockLog.setMatcher(MockControl.ALWAYS_MATCHER);
+ mockLog.setVoidCallable();
+
+ mockMethodInvocation.replay();
+ mockLog.replay();
+
+ DebugInterceptor interceptor = new StubDebugInterceptor(log);
+ try {
+ interceptor.invoke(methodInvocation);
+ fail("Must have propagated the IllegalArgumentException.");
+ } catch (IllegalArgumentException expected) {
+ }
+ checkCallCountTotal(interceptor);
+
+ mockLog.verify();
+ mockMethodInvocation.verify();
+ }
+
+ private void checkCallCountTotal(DebugInterceptor interceptor) {
+ assertEquals("Intercepted call count not being incremented correctly", 1, interceptor.getCount());
+ }
+
+
+ private static final class StubDebugInterceptor extends DebugInterceptor {
+
+ private final Log log;
+
+
+ public StubDebugInterceptor(Log log) {
+ super(true);
+ this.log = log;
+ }
+
+
+ protected Log getLoggerForInvocation(MethodInvocation invocation) {
+ return log;
+ }
+
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/ExposeBeanNameAdvisorsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/ExposeBeanNameAdvisorsTests.java
new file mode 100644
index 00000000000..f635917cfda
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/ExposeBeanNameAdvisorsTests.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.interceptor;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.NamedBean;
+
+/**
+ *
+ * @author Rod Johnson
+ *
+ */
+public class ExposeBeanNameAdvisorsTests extends TestCase {
+
+ private class RequiresBeanNameBoundTestBean extends TestBean {
+ private final String beanName;
+
+ public RequiresBeanNameBoundTestBean(String beanName) {
+ this.beanName = beanName;
+ }
+
+ public int getAge() {
+ assertEquals(beanName, ExposeBeanNameAdvisors.getBeanName());
+ return super.getAge();
+ }
+ }
+
+ public void testNoIntroduction() {
+ String beanName = "foo";
+ TestBean target = new RequiresBeanNameBoundTestBean(beanName);
+ ProxyFactory pf = new ProxyFactory(target);
+ pf.addAdvisor(ExposeInvocationInterceptor.ADVISOR);
+ pf.addAdvisor(ExposeBeanNameAdvisors.createAdvisorWithoutIntroduction(beanName));
+ ITestBean proxy = (ITestBean) pf.getProxy();
+
+ assertFalse("No introduction", proxy instanceof NamedBean);
+ // Requires binding
+ proxy.getAge();
+ }
+
+ public void testWithIntroduction() {
+ String beanName = "foo";
+ TestBean target = new RequiresBeanNameBoundTestBean(beanName);
+ ProxyFactory pf = new ProxyFactory(target);
+ pf.addAdvisor(ExposeInvocationInterceptor.ADVISOR);
+ pf.addAdvisor(ExposeBeanNameAdvisors.createAdvisorIntroducingNamedBean(beanName));
+ ITestBean proxy = (ITestBean) pf.getProxy();
+
+ assertTrue("Introduction was made", proxy instanceof NamedBean);
+ // Requires binding
+ proxy.getAge();
+
+ NamedBean nb = (NamedBean) proxy;
+ assertEquals("Name returned correctly", beanName, nb.getBeanName());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/ExposeInvocationInterceptorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/ExposeInvocationInterceptorTests.java
new file mode 100644
index 00000000000..ca0f294a4fa
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/ExposeInvocationInterceptorTests.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.interceptor;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.ITestBean;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * Non-XML tests are in AbstractAopProxyTests
+ * @author Rod Johnson
+ */
+public class ExposeInvocationInterceptorTests extends TestCase {
+
+ public void testXmlConfig() {
+ ClassPathXmlApplicationContext xac = new ClassPathXmlApplicationContext("org/springframework/aop/interceptor/exposeInvocation.xml");
+ ITestBean tb = (ITestBean) xac.getBean("proxy");
+ String name= "tony";
+ tb.setName(name);
+ // Fires context checks
+ assertEquals(name, tb.getName());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/NopInterceptor.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/NopInterceptor.java
new file mode 100644
index 00000000000..6bbbc4ff174
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/NopInterceptor.java
@@ -0,0 +1,58 @@
+
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.interceptor;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+/**
+ * Trivial interceptor that can be introduced in a chain to display it.
+ *
+ * @author Rod Johnson
+ */
+public class NopInterceptor implements MethodInterceptor {
+
+ private int count;
+
+ /**
+ * @see org.aopalliance.intercept.MethodInterceptor#invoke(MethodInvocation)
+ */
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ increment();
+ return invocation.proceed();
+ }
+
+ public int getCount() {
+ return this.count;
+ }
+
+ protected void increment() {
+ ++count;
+ }
+
+ public boolean equals(Object other) {
+ if (!(other instanceof NopInterceptor)) {
+ return false;
+ }
+ if (this == other) {
+ return true;
+ }
+ return this.count == ((NopInterceptor) other).count;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/PerformanceMonitorInterceptorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/PerformanceMonitorInterceptorTests.java
new file mode 100644
index 00000000000..352aa345c48
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/PerformanceMonitorInterceptorTests.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.interceptor;
+
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+import org.aopalliance.intercept.MethodInvocation;
+import org.apache.commons.logging.Log;
+import org.easymock.MockControl;
+
+/**
+ * @author Rob Harrop
+ * @author Rick Evans
+ */
+public class PerformanceMonitorInterceptorTests extends TestCase {
+
+ public void testSuffixAndPrefixAssignment() {
+ PerformanceMonitorInterceptor interceptor = new PerformanceMonitorInterceptor();
+
+ assertNotNull(interceptor.getPrefix());
+ assertNotNull(interceptor.getSuffix());
+
+ interceptor.setPrefix(null);
+ interceptor.setSuffix(null);
+
+ assertNotNull(interceptor.getPrefix());
+ assertNotNull(interceptor.getSuffix());
+ }
+
+ public void testSunnyDayPathLogsPerformanceMetricsCorrectly() throws Throwable {
+ MockControl mockLog = MockControl.createControl(Log.class);
+ Log log = (Log) mockLog.getMock();
+
+ MockControl mockMethodInvocation = MockControl.createControl(MethodInvocation.class);
+ MethodInvocation methodInvocation = (MethodInvocation) mockMethodInvocation.getMock();
+
+ Method toString = String.class.getMethod("toString", new Class[0]);
+
+ methodInvocation.getMethod();
+ mockMethodInvocation.setReturnValue(toString);
+ methodInvocation.proceed();
+ mockMethodInvocation.setReturnValue(null);
+ log.trace("Some performance metric");
+ mockLog.setMatcher(MockControl.ALWAYS_MATCHER);
+ mockLog.setVoidCallable();
+
+ mockMethodInvocation.replay();
+ mockLog.replay();
+
+ PerformanceMonitorInterceptor interceptor = new PerformanceMonitorInterceptor(true);
+ interceptor.invokeUnderTrace(methodInvocation, log);
+
+ mockLog.verify();
+ mockMethodInvocation.verify();
+ }
+
+ public void testExceptionPathStillLogsPerformanceMetricsCorrectly() throws Throwable {
+ MockControl mockLog = MockControl.createControl(Log.class);
+ Log log = (Log) mockLog.getMock();
+
+ MockControl mockMethodInvocation = MockControl.createControl(MethodInvocation.class);
+ MethodInvocation methodInvocation = (MethodInvocation) mockMethodInvocation.getMock();
+
+ Method toString = String.class.getMethod("toString", new Class[0]);
+
+ methodInvocation.getMethod();
+ mockMethodInvocation.setReturnValue(toString);
+ methodInvocation.proceed();
+ mockMethodInvocation.setThrowable(new IllegalArgumentException());
+ log.trace("Some performance metric");
+ mockLog.setMatcher(MockControl.ALWAYS_MATCHER);
+ mockLog.setVoidCallable();
+
+ mockMethodInvocation.replay();
+ mockLog.replay();
+
+ PerformanceMonitorInterceptor interceptor = new PerformanceMonitorInterceptor(true);
+ try {
+ interceptor.invokeUnderTrace(methodInvocation, log);
+ fail("Must have propagated the IllegalArgumentException.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ mockLog.verify();
+ mockMethodInvocation.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/SerializableNopInterceptor.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/SerializableNopInterceptor.java
new file mode 100644
index 00000000000..328f6cf9b2f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/SerializableNopInterceptor.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.interceptor;
+
+import java.io.Serializable;
+
+
+/**
+ * Subclass of NopInterceptor that is serializable and
+ * can be used to test proxy serialization.
+ *
+ * @author Rod Johnson
+ */
+public class SerializableNopInterceptor extends NopInterceptor implements Serializable {
+
+ /**
+ * We must override this field and the related methods as
+ * otherwise count won't be serialized from the non-serializable
+ * NopInterceptor superclass.
+ */
+ private int count;
+
+ public int getCount() {
+ return this.count;
+ }
+
+ protected void increment() {
+ ++count;
+ }
+
+}
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/SideEffectBean.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/SideEffectBean.java
new file mode 100644
index 00000000000..ee6c95a658b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/SideEffectBean.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.interceptor;
+
+/**
+ * Bean that changes state on a business invocation, so that
+ * we can check whether it's been invoked
+ * @author Rod Johnson
+ */
+public class SideEffectBean {
+
+ private int count;
+
+ public void setCount(int count) {
+ this.count = count;
+ }
+
+ public int getCount() {
+ return this.count;
+ }
+
+ public void doWork() {
+ ++count;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/SimpleTraceInterceptorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/SimpleTraceInterceptorTests.java
new file mode 100644
index 00000000000..8a963bfc65e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/SimpleTraceInterceptorTests.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.interceptor;
+
+import junit.framework.TestCase;
+import org.aopalliance.intercept.MethodInvocation;
+import org.apache.commons.logging.Log;
+import org.easymock.MockControl;
+
+import java.lang.reflect.Method;
+
+/**
+ * Unit tests for the {@link SimpleTraceInterceptor} class.
+ *
+ * @author Rick Evans
+ */
+public final class SimpleTraceInterceptorTests extends TestCase {
+
+ public void testSunnyDayPathLogsCorrectly() throws Throwable {
+ MockControl mockLog = MockControl.createControl(Log.class);
+ Log log = (Log) mockLog.getMock();
+
+ MockControl mockMethodInvocation = MockControl.createControl(MethodInvocation.class);
+ MethodInvocation methodInvocation = (MethodInvocation) mockMethodInvocation.getMock();
+
+ Method toString = String.class.getMethod("toString", new Class[]{});
+
+ methodInvocation.getMethod();
+ mockMethodInvocation.setReturnValue(toString);
+ methodInvocation.getThis();
+ mockMethodInvocation.setReturnValue(this);
+ log.trace("Some tracing output");
+ mockLog.setMatcher(MockControl.ALWAYS_MATCHER);
+ methodInvocation.proceed();
+ mockMethodInvocation.setReturnValue(null);
+ log.trace("Some more tracing output");
+ mockLog.setMatcher(MockControl.ALWAYS_MATCHER);
+ mockLog.setVoidCallable();
+
+ mockMethodInvocation.replay();
+ mockLog.replay();
+
+ SimpleTraceInterceptor interceptor = new SimpleTraceInterceptor(true);
+ interceptor.invokeUnderTrace(methodInvocation, log);
+
+ mockLog.verify();
+ mockMethodInvocation.verify();
+ }
+
+ public void testExceptionPathStillLogsCorrectly() throws Throwable {
+ MockControl mockLog = MockControl.createControl(Log.class);
+ final Log log = (Log) mockLog.getMock();
+
+ MockControl mockMethodInvocation = MockControl.createControl(MethodInvocation.class);
+ final MethodInvocation methodInvocation = (MethodInvocation) mockMethodInvocation.getMock();
+
+ Method toString = String.class.getMethod("toString", new Class[]{});
+
+ methodInvocation.getMethod();
+ mockMethodInvocation.setReturnValue(toString);
+ methodInvocation.getThis();
+ mockMethodInvocation.setReturnValue(this);
+ log.trace("Some tracing output");
+ mockLog.setMatcher(MockControl.ALWAYS_MATCHER);
+ methodInvocation.proceed();
+ IllegalArgumentException exception = new IllegalArgumentException();
+ mockMethodInvocation.setThrowable(exception);
+ log.trace("Some more tracing output", exception);
+ mockLog.setMatcher(MockControl.ALWAYS_MATCHER);
+ mockLog.setVoidCallable();
+
+ mockMethodInvocation.replay();
+ mockLog.replay();
+
+ final SimpleTraceInterceptor interceptor = new SimpleTraceInterceptor(true);
+
+ try {
+ interceptor.invokeUnderTrace(methodInvocation, log);
+ fail("Must have propagated the IllegalArgumentException.");
+ } catch (IllegalArgumentException expected) {
+ }
+
+ mockLog.verify();
+ mockMethodInvocation.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/exposeInvocation.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/exposeInvocation.xml
new file mode 100644
index 00000000000..a44795f043a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/interceptor/exposeInvocation.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+ org.springframework.aop.interceptor.ExposeInvocationInterceptor
+
+ INSTANCE
+
+
+
+
+
+
+
+
+
+ exposeInvocation,countingBeforeAdvice,nopInterceptor
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/DefaultScopedObjectTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/DefaultScopedObjectTests.java
new file mode 100644
index 00000000000..c05fa15dc97
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/DefaultScopedObjectTests.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.scope;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.test.AssertThrows;
+
+/**
+ * Unit tests for the {@link DefaultScopedObject} class.
+ *
+ * @author Rick Evans
+ */
+public final class DefaultScopedObjectTests extends TestCase {
+
+ private static final String GOOD_BEAN_NAME = "foo";
+
+
+ public void testCtorWithNullBeanFactory() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new DefaultScopedObject(null, GOOD_BEAN_NAME);
+ }
+ }.runTest();
+ }
+
+ public void testCtorWithNullTargetBeanName() throws Exception {
+ testBadTargetBeanName(null);
+ }
+
+ public void testCtorWithEmptyTargetBeanName() throws Exception {
+ testBadTargetBeanName("");
+ }
+
+ public void testCtorWithJustWhitespacedTargetBeanName() throws Exception {
+ testBadTargetBeanName(" ");
+ }
+
+
+ private static void testBadTargetBeanName(final String badTargetBeanName) {
+ MockControl mock = MockControl.createControl(ConfigurableBeanFactory.class);
+ final ConfigurableBeanFactory factory = (ConfigurableBeanFactory) mock.getMock();
+ mock.replay();
+
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new DefaultScopedObject(factory, badTargetBeanName);
+ }
+ }.runTest();
+
+ mock.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/ScopedProxyAutowireTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/ScopedProxyAutowireTests.java
new file mode 100644
index 00000000000..925ddcc3f7a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/ScopedProxyAutowireTests.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.scope;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Mark Fisher
+ */
+public class ScopedProxyAutowireTests extends TestCase {
+
+ public void testScopedProxyInheritsAutowireCandidateFalse() {
+ XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("scopedAutowireFalse.xml", getClass()));
+ TestBean autowired = (TestBean) bf.getBean("autowired");
+ TestBean unscoped = (TestBean) bf.getBean("unscoped");
+ assertSame(unscoped, autowired.getChild());
+ }
+
+ public void testScopedProxyReplacesAutowireCandidateTrue() {
+ XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("scopedAutowireTrue.xml", getClass()));
+ TestBean autowired = (TestBean) bf.getBean("autowired");
+ TestBean scoped = (TestBean) bf.getBean("scoped");
+ assertSame(scoped, autowired.getChild());
+ }
+
+
+ public static class TestBean {
+
+ private TestBean child;
+
+ public void setChild(TestBean child) {
+ this.child = child;
+ }
+
+ public TestBean getChild() {
+ return this.child;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/ScopedProxyTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/ScopedProxyTests.java
new file mode 100644
index 00000000000..54515872534
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/ScopedProxyTests.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.aop.scope;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.support.AopUtils;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.config.SimpleMapScope;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.context.support.GenericApplicationContext;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class ScopedProxyTests extends TestCase {
+
+ /* SPR-2108 */
+ public void testProxyAssignable() throws Exception {
+ XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("scopedMap.xml", getClass()));
+ Object baseMap = bf.getBean("singletonMap");
+ assertTrue(baseMap instanceof Map);
+ }
+
+ public void testSimpleProxy() throws Exception {
+ XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("scopedMap.xml", getClass()));
+ Object simpleMap = bf.getBean("simpleMap");
+ assertTrue(simpleMap instanceof Map);
+ assertTrue(simpleMap instanceof HashMap);
+ }
+
+ public void testScopedOverride() throws Exception {
+ GenericApplicationContext ctx = new GenericApplicationContext();
+ new XmlBeanDefinitionReader(ctx).loadBeanDefinitions(new ClassPathResource("scopedOverride.xml", getClass()));
+ SimpleMapScope scope = new SimpleMapScope();
+ ctx.getBeanFactory().registerScope("request", scope);
+ ctx.refresh();
+
+ ITestBean bean = (ITestBean) ctx.getBean("testBean");
+ assertEquals("male", bean.getName());
+ assertEquals(99, bean.getAge());
+
+ assertTrue(scope.getMap().containsKey("scopedTarget.testBean"));
+ assertEquals(TestBean.class, scope.getMap().get("scopedTarget.testBean").getClass());
+ }
+
+ public void testJdkScopedProxy() throws Exception {
+ XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("scopedTestBean.xml", getClass()));
+ SimpleMapScope scope = new SimpleMapScope();
+ bf.registerScope("request", scope);
+
+ ITestBean bean = (ITestBean) bf.getBean("testBean");
+ assertNotNull(bean);
+ assertTrue(AopUtils.isJdkDynamicProxy(bean));
+ assertTrue(bean instanceof ScopedObject);
+ ScopedObject scoped = (ScopedObject) bean;
+ assertEquals(TestBean.class, scoped.getTargetObject().getClass());
+
+ assertTrue(scope.getMap().containsKey("testBeanTarget"));
+ assertEquals(TestBean.class, scope.getMap().get("testBeanTarget").getClass());
+ }
+
+ public void testCglibScopedProxy() {
+ XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("scopedList.xml", getClass()));
+ SimpleMapScope scope = new SimpleMapScope();
+ bf.registerScope("request", scope);
+
+ TestBean tb = (TestBean) bf.getBean("testBean");
+ assertTrue(AopUtils.isCglibProxy(tb.getFriends()));
+ assertTrue(tb.getFriends() instanceof ScopedObject);
+ ScopedObject scoped = (ScopedObject) tb.getFriends();
+ assertEquals(ArrayList.class, scoped.getTargetObject().getClass());
+
+ assertTrue(scope.getMap().containsKey("scopedTarget.scopedList"));
+ assertEquals(ArrayList.class, scope.getMap().get("scopedTarget.scopedList").getClass());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/scopedAutowireFalse.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/scopedAutowireFalse.xml
new file mode 100644
index 00000000000..feecab3e9cf
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/scopedAutowireFalse.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/scopedAutowireTrue.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/scopedAutowireTrue.xml
new file mode 100644
index 00000000000..445b50d064b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/scopedAutowireTrue.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/scopedList.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/scopedList.xml
new file mode 100644
index 00000000000..5ff806cb6f0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/scopedList.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/scopedMap.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/scopedMap.xml
new file mode 100644
index 00000000000..0c69a3f9cc1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/scopedMap.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/scopedOverride.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/scopedOverride.xml
new file mode 100644
index 00000000000..63f19fe2637
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/scopedOverride.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/scopedTestBean.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/scopedTestBean.xml
new file mode 100644
index 00000000000..0560e78b721
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/scope/scopedTestBean.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/support/AbstractRegexpMethodPointcutTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/AbstractRegexpMethodPointcutTests.java
new file mode 100644
index 00000000000..75d4af6d2e4
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/AbstractRegexpMethodPointcutTests.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.aop.support;
+
+import javax.servlet.ServletException;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+import org.springframework.util.SerializationTestUtils;
+
+/**
+ * @author Rod Johnson
+ * @author Dmitriy Kopylenko
+ */
+public abstract class AbstractRegexpMethodPointcutTests extends TestCase {
+
+ private AbstractRegexpMethodPointcut rpc;
+
+ protected void setUp() {
+ rpc = getRegexpMethodPointcut();
+ }
+
+ protected abstract AbstractRegexpMethodPointcut getRegexpMethodPointcut();
+
+ public void testNoPatternSupplied() throws Exception {
+ noPatternSuppliedTests(rpc);
+ }
+
+ public void testSerializationWithNoPatternSupplied() throws Exception {
+ rpc = (AbstractRegexpMethodPointcut) SerializationTestUtils.serializeAndDeserialize(rpc);
+ noPatternSuppliedTests(rpc);
+ }
+
+ protected void noPatternSuppliedTests(AbstractRegexpMethodPointcut rpc) throws Exception {
+ assertFalse(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), String.class));
+ assertFalse(rpc.matches(Object.class.getMethod("wait", (Class[]) null), Object.class));
+ assertEquals(0, rpc.getPatterns().length);
+ }
+
+ public void testExactMatch() throws Exception {
+ rpc.setPattern("java.lang.Object.hashCode");
+ exactMatchTests(rpc);
+ rpc = (AbstractRegexpMethodPointcut) SerializationTestUtils.serializeAndDeserialize(rpc);
+ exactMatchTests(rpc);
+ }
+
+ protected void exactMatchTests(AbstractRegexpMethodPointcut rpc) throws Exception {
+ // assumes rpc.setPattern("java.lang.Object.hashCode");
+ assertTrue(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), String.class));
+ assertTrue(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), Object.class));
+ assertFalse(rpc.matches(Object.class.getMethod("wait", (Class[]) null), Object.class));
+ }
+
+ public void testSpecificMatch() throws Exception {
+ rpc.setPattern("java.lang.String.hashCode");
+ assertTrue(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), String.class));
+ assertFalse(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), Object.class));
+ }
+
+ public void testWildcard() throws Exception {
+ rpc.setPattern(".*Object.hashCode");
+ assertTrue(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), Object.class));
+ assertFalse(rpc.matches(Object.class.getMethod("wait", (Class[]) null), Object.class));
+ }
+
+ public void testWildcardForOneClass() throws Exception {
+ rpc.setPattern("java.lang.Object.*");
+ assertTrue(rpc.matches(Object.class.getMethod("hashCode", (Class[]) null), String.class));
+ assertTrue(rpc.matches(Object.class.getMethod("wait", (Class[]) null), String.class));
+ }
+
+ public void testMatchesObjectClass() throws Exception {
+ rpc.setPattern("java.lang.Object.*");
+ assertTrue(rpc.matches(Exception.class.getMethod("hashCode", (Class[]) null), ServletException.class));
+ // Doesn't match a method from Throwable
+ assertFalse(rpc.matches(Exception.class.getMethod("getMessage", (Class[]) null), Exception.class));
+ }
+
+ public void testWithExclusion() throws Exception {
+ this.rpc.setPattern(".*get.*");
+ this.rpc.setExcludedPattern(".*Age.*");
+ assertTrue(this.rpc.matches(TestBean.class.getMethod("getName", null), TestBean.class));
+ assertFalse(this.rpc.matches(TestBean.class.getMethod("getAge", null), TestBean.class));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/support/AopUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/AopUtilsTests.java
new file mode 100644
index 00000000000..f8130f465d1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/AopUtilsTests.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.support;
+
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.ClassFilter;
+import org.springframework.aop.MethodMatcher;
+import org.springframework.aop.Pointcut;
+import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
+import org.springframework.aop.interceptor.NopInterceptor;
+import org.springframework.aop.target.EmptyTargetSource;
+import org.springframework.beans.TestBean;
+import org.springframework.util.SerializationTestUtils;
+
+/**
+ * @author Rod Johnson
+ */
+public class AopUtilsTests extends TestCase {
+
+ public void testPointcutCanNeverApply() {
+ class TestPointcut extends StaticMethodMatcherPointcut {
+ public boolean matches(Method method, Class clazzy) {
+ return false;
+ }
+ }
+
+ Pointcut no = new TestPointcut();
+ assertFalse(AopUtils.canApply(no, Object.class));
+ }
+
+ public void testPointcutAlwaysApplies() {
+ assertTrue(AopUtils.canApply(new DefaultPointcutAdvisor(new NopInterceptor()), Object.class));
+ assertTrue(AopUtils.canApply(new DefaultPointcutAdvisor(new NopInterceptor()), TestBean.class));
+ }
+
+ public void testPointcutAppliesToOneMethodOnObject() {
+ class TestPointcut extends StaticMethodMatcherPointcut {
+ public boolean matches(Method method, Class clazz) {
+ return method.getName().equals("hashCode");
+ }
+ }
+
+ Pointcut pc = new TestPointcut();
+
+ // will return true if we're not proxying interfaces
+ assertTrue(AopUtils.canApply(pc, Object.class));
+ }
+
+ /**
+ * Test that when we serialize and deserialize various canonical instances
+ * of AOP classes, they return the same instance, not a new instance
+ * that's subverted the singleton construction limitation.
+ */
+ public void testCanonicalFrameworkClassesStillCanonicalOnDeserialization() throws Exception {
+ assertSame(MethodMatcher.TRUE, SerializationTestUtils.serializeAndDeserialize(MethodMatcher.TRUE));
+ assertSame(ClassFilter.TRUE, SerializationTestUtils.serializeAndDeserialize(ClassFilter.TRUE));
+ assertSame(Pointcut.TRUE, SerializationTestUtils.serializeAndDeserialize(Pointcut.TRUE));
+ assertSame(EmptyTargetSource.INSTANCE, SerializationTestUtils.serializeAndDeserialize(EmptyTargetSource.INSTANCE));
+ assertSame(Pointcuts.SETTERS, SerializationTestUtils.serializeAndDeserialize(Pointcuts.SETTERS));
+ assertSame(Pointcuts.GETTERS, SerializationTestUtils.serializeAndDeserialize(Pointcuts.GETTERS));
+ assertSame(ExposeInvocationInterceptor.INSTANCE,
+ SerializationTestUtils.serializeAndDeserialize(ExposeInvocationInterceptor.INSTANCE));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/support/ClassFiltersTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/ClassFiltersTests.java
new file mode 100644
index 00000000000..a6d61f85439
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/ClassFiltersTests.java
@@ -0,0 +1,57 @@
+
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.support;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.ClassFilter;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.core.NestedRuntimeException;
+
+/**
+ * @author Rod Johnson
+ */
+public class ClassFiltersTests extends TestCase {
+
+ private ClassFilter exceptionFilter = new RootClassFilter(Exception.class);
+
+ private ClassFilter itbFilter = new RootClassFilter(ITestBean.class);
+
+ private ClassFilter hasRootCauseFilter = new RootClassFilter(NestedRuntimeException.class);
+
+ public void testUnion() {
+ assertTrue(exceptionFilter.matches(RuntimeException.class));
+ assertFalse(exceptionFilter.matches(TestBean.class));
+ assertFalse(itbFilter.matches(Exception.class));
+ assertTrue(itbFilter.matches(TestBean.class));
+ ClassFilter union = ClassFilters.union(exceptionFilter, itbFilter);
+ assertTrue(union.matches(RuntimeException.class));
+ assertTrue(union.matches(TestBean.class));
+ }
+
+ public void testIntersection() {
+ assertTrue(exceptionFilter.matches(RuntimeException.class));
+ assertTrue(hasRootCauseFilter.matches(NestedRuntimeException.class));
+ ClassFilter intersection = ClassFilters.intersection(exceptionFilter, hasRootCauseFilter);
+ assertFalse(intersection.matches(RuntimeException.class));
+ assertFalse(intersection.matches(TestBean.class));
+ assertTrue(intersection.matches(NestedRuntimeException.class));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/support/ComposablePointcutTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/ComposablePointcutTests.java
new file mode 100644
index 00000000000..d73d642bcae
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/ComposablePointcutTests.java
@@ -0,0 +1,145 @@
+
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.support;
+
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.ClassFilter;
+import org.springframework.aop.MethodMatcher;
+import org.springframework.aop.Pointcut;
+import org.springframework.beans.TestBean;
+import org.springframework.core.NestedRuntimeException;
+
+/**
+ * @author Rod Johnson
+ */
+public class ComposablePointcutTests extends TestCase {
+
+ public static MethodMatcher GETTER_METHOD_MATCHER = new StaticMethodMatcher() {
+ public boolean matches(Method m, Class targetClass) {
+ return m.getName().startsWith("get");
+ }
+ };
+
+ public static MethodMatcher GET_AGE_METHOD_MATCHER = new StaticMethodMatcher() {
+ public boolean matches(Method m, Class targetClass) {
+ return m.getName().equals("getAge");
+ }
+ };
+
+ public static MethodMatcher ABSQUATULATE_METHOD_MATCHER = new StaticMethodMatcher() {
+ public boolean matches(Method m, Class targetClass) {
+ return m.getName().equals("absquatulate");
+ }
+ };
+
+ public static MethodMatcher SETTER_METHOD_MATCHER = new StaticMethodMatcher() {
+ public boolean matches(Method m, Class targetClass) {
+ return m.getName().startsWith("set");
+ }
+ };
+
+ public void testMatchAll() throws NoSuchMethodException {
+ Pointcut pc = new ComposablePointcut();
+ assertTrue(pc.getClassFilter().matches(Object.class));
+ assertTrue(pc.getMethodMatcher().matches(Object.class.getMethod("hashCode", (Class[]) null), Exception.class));
+ }
+
+ public void testFilterByClass() throws NoSuchMethodException {
+ ComposablePointcut pc = new ComposablePointcut();
+
+ assertTrue(pc.getClassFilter().matches(Object.class));
+
+ ClassFilter cf = new RootClassFilter(Exception.class);
+ pc.intersection(cf);
+ assertFalse(pc.getClassFilter().matches(Object.class));
+ assertTrue(pc.getClassFilter().matches(Exception.class));
+ pc.intersection(new RootClassFilter(NestedRuntimeException.class));
+ assertFalse(pc.getClassFilter().matches(Exception.class));
+ assertTrue(pc.getClassFilter().matches(NestedRuntimeException.class));
+ assertFalse(pc.getClassFilter().matches(String.class));
+ pc.union(new RootClassFilter(String.class));
+ assertFalse(pc.getClassFilter().matches(Exception.class));
+ assertTrue(pc.getClassFilter().matches(String.class));
+ assertTrue(pc.getClassFilter().matches(NestedRuntimeException.class));
+ }
+
+ public void testUnionMethodMatcher() {
+ // Matches the getAge() method in any class
+ ComposablePointcut pc = new ComposablePointcut(ClassFilter.TRUE, GET_AGE_METHOD_MATCHER);
+ assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class, null));
+ assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class, null));
+ assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class, null));
+
+ pc.union(GETTER_METHOD_MATCHER);
+ // Should now match all getter methods
+ assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class, null));
+ assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class, null));
+ assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class, null));
+
+ pc.union(ABSQUATULATE_METHOD_MATCHER);
+ // Should now match absquatulate() as well
+ assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class, null));
+ assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class, null));
+ assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class, null));
+ // But it doesn't match everything
+ assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_SET_AGE, TestBean.class, null));
+ }
+
+ public void testIntersectionMethodMatcher() {
+ ComposablePointcut pc = new ComposablePointcut();
+ assertTrue(pc.getMethodMatcher().matches(PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class));
+ assertTrue(pc.getMethodMatcher().matches(PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class));
+ assertTrue(pc.getMethodMatcher().matches(PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class));
+ pc.intersection(GETTER_METHOD_MATCHER);
+ assertFalse(pc.getMethodMatcher().matches(PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class));
+ assertTrue(pc.getMethodMatcher().matches(PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class));
+ assertTrue(pc.getMethodMatcher().matches(PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class));
+ pc.intersection(GET_AGE_METHOD_MATCHER);
+ // Use the Pointcuts matches method
+ assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_ABSQUATULATE, TestBean.class, null));
+ assertTrue(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_AGE, TestBean.class, null));
+ assertFalse(Pointcuts.matches(pc, PointcutsTests.TEST_BEAN_GET_NAME, TestBean.class, null));
+ }
+
+ public void testEqualsAndHashCode() throws Exception {
+ ComposablePointcut pc1 = new ComposablePointcut();
+ ComposablePointcut pc2 = new ComposablePointcut();
+
+ assertEquals(pc1, pc2);
+ assertEquals(pc1.hashCode(), pc2.hashCode());
+
+ pc1.intersection(GETTER_METHOD_MATCHER);
+
+ assertFalse(pc1.equals(pc2));
+ assertFalse(pc1.hashCode() == pc2.hashCode());
+
+ pc2.intersection(GETTER_METHOD_MATCHER);
+
+ assertEquals(pc1, pc2);
+ assertEquals(pc1.hashCode(), pc2.hashCode());
+
+ pc1.union(GET_AGE_METHOD_MATCHER);
+ pc2.union(GET_AGE_METHOD_MATCHER);
+
+ assertEquals(pc1, pc2);
+ assertEquals(pc1.hashCode(), pc2.hashCode());
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/support/ControlFlowPointcutTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/ControlFlowPointcutTests.java
new file mode 100644
index 00000000000..100cab23725
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/ControlFlowPointcutTests.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.support;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.Pointcut;
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.aop.interceptor.NopInterceptor;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+
+/**
+ *
+ * @author Rod Johnson
+ */
+public class ControlFlowPointcutTests extends TestCase {
+
+ public ControlFlowPointcutTests(String s) {
+ super(s);
+ }
+
+ public void testMatches() {
+ TestBean target = new TestBean();
+ target.setAge(27);
+ NopInterceptor nop = new NopInterceptor();
+ ControlFlowPointcut cflow = new ControlFlowPointcut(One.class, "getAge");
+ ProxyFactory pf = new ProxyFactory(target);
+ ITestBean proxied = (ITestBean) pf.getProxy();
+ pf.addAdvisor(new DefaultPointcutAdvisor(cflow, nop));
+
+ // Not advised, not under One
+ assertEquals(target.getAge(), proxied.getAge());
+ assertEquals(0, nop.getCount());
+
+ // Will be advised
+ assertEquals(target.getAge(), new One().getAge(proxied));
+ assertEquals(1, nop.getCount());
+
+ // Won't be advised
+ assertEquals(target.getAge(), new One().nomatch(proxied));
+ assertEquals(1, nop.getCount());
+ assertEquals(3, cflow.getEvaluations());
+ }
+
+ /**
+ * Check that we can use a cflow pointcut only in conjunction with
+ * a static pointcut: e.g. all setter methods that are invoked under
+ * a particular class. This greatly reduces the number of calls
+ * to the cflow pointcut, meaning that it's not so prohibitively
+ * expensive.
+ */
+ public void testSelectiveApplication() {
+ TestBean target = new TestBean();
+ target.setAge(27);
+ NopInterceptor nop = new NopInterceptor();
+ ControlFlowPointcut cflow = new ControlFlowPointcut(One.class);
+ Pointcut settersUnderOne = Pointcuts.intersection(Pointcuts.SETTERS, cflow);
+ ProxyFactory pf = new ProxyFactory(target);
+ ITestBean proxied = (ITestBean) pf.getProxy();
+ pf.addAdvisor(new DefaultPointcutAdvisor(settersUnderOne, nop));
+
+ // Not advised, not under One
+ target.setAge(16);
+ assertEquals(0, nop.getCount());
+
+ // Not advised; under One but not a setter
+ assertEquals(16, new One().getAge(proxied));
+ assertEquals(0, nop.getCount());
+
+ // Won't be advised
+ new One().set(proxied);
+ assertEquals(1, nop.getCount());
+
+ // We saved most evaluations
+ assertEquals(1, cflow.getEvaluations());
+ }
+
+ public void testEqualsAndHashCode() throws Exception {
+ assertEquals(new ControlFlowPointcut(One.class), new ControlFlowPointcut(One.class));
+ assertEquals(new ControlFlowPointcut(One.class, "getAge"), new ControlFlowPointcut(One.class, "getAge"));
+ assertFalse(new ControlFlowPointcut(One.class, "getAge").equals(new ControlFlowPointcut(One.class)));
+ assertEquals(new ControlFlowPointcut(One.class).hashCode(), new ControlFlowPointcut(One.class).hashCode());
+ assertEquals(new ControlFlowPointcut(One.class, "getAge").hashCode(), new ControlFlowPointcut(One.class, "getAge").hashCode());
+ assertFalse(new ControlFlowPointcut(One.class, "getAge").hashCode() == new ControlFlowPointcut(One.class).hashCode());
+ }
+
+ public class One {
+ int getAge(ITestBean proxied) {
+ return proxied.getAge();
+ }
+ int nomatch(ITestBean proxied) {
+ return proxied.getAge();
+ }
+ void set(ITestBean proxied) {
+ proxied.setAge(5);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/support/DelegatingIntroductionInterceptorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/DelegatingIntroductionInterceptorTests.java
new file mode 100644
index 00000000000..8b042bf6426
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/DelegatingIntroductionInterceptorTests.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.support;
+
+import java.io.Serializable;
+
+import junit.framework.TestCase;
+import org.aopalliance.intercept.MethodInterceptor;
+import org.easymock.MockControl;
+
+import org.springframework.aop.IntroductionAdvisor;
+import org.springframework.aop.IntroductionInterceptor;
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.aop.framework.TimeStamped;
+import org.springframework.aop.interceptor.SerializableNopInterceptor;
+import org.springframework.beans.INestedTestBean;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.NestedTestBean;
+import org.springframework.beans.Person;
+import org.springframework.beans.SerializablePerson;
+import org.springframework.beans.TestBean;
+import org.springframework.util.SerializationTestUtils;
+
+/**
+ * @author Rod Johnson
+ * @since 13.05.2003
+ */
+public class DelegatingIntroductionInterceptorTests extends TestCase {
+
+ public void testNullTarget() throws Exception {
+ try {
+ IntroductionInterceptor ii = new DelegatingIntroductionInterceptor(null);
+ fail("Shouldn't accept null target");
+ }
+ catch (IllegalArgumentException ex) {
+ // OK
+ }
+ }
+
+ public void testIntroductionInterceptorWithDelegation() throws Exception {
+ TestBean raw = new TestBean();
+ assertTrue(! (raw instanceof TimeStamped));
+ ProxyFactory factory = new ProxyFactory(raw);
+
+ MockControl tsControl = MockControl.createControl(TimeStamped.class);
+ TimeStamped ts = (TimeStamped) tsControl.getMock();
+ ts.getTimeStamp();
+ long timestamp = 111L;
+ tsControl.setReturnValue(timestamp, 1);
+ tsControl.replay();
+
+ factory.addAdvisor(0, new DefaultIntroductionAdvisor(new DelegatingIntroductionInterceptor(ts)));
+
+ TimeStamped tsp = (TimeStamped) factory.getProxy();
+ assertTrue(tsp.getTimeStamp() == timestamp);
+
+ tsControl.verify();
+ }
+
+ public void testIntroductionInterceptorWithInterfaceHierarchy() throws Exception {
+ TestBean raw = new TestBean();
+ assertTrue(! (raw instanceof SubTimeStamped));
+ ProxyFactory factory = new ProxyFactory(raw);
+
+ MockControl tsControl = MockControl.createControl(SubTimeStamped.class);
+ SubTimeStamped ts = (SubTimeStamped) tsControl.getMock();
+ ts.getTimeStamp();
+ long timestamp = 111L;
+ tsControl.setReturnValue(timestamp, 1);
+ tsControl.replay();
+
+ factory.addAdvisor(0, new DefaultIntroductionAdvisor(new DelegatingIntroductionInterceptor(ts), SubTimeStamped.class));
+
+ SubTimeStamped tsp = (SubTimeStamped) factory.getProxy();
+ assertTrue(tsp.getTimeStamp() == timestamp);
+
+ tsControl.verify();
+ }
+
+ public void testIntroductionInterceptorWithSuperInterface() throws Exception {
+ TestBean raw = new TestBean();
+ assertTrue(! (raw instanceof TimeStamped));
+ ProxyFactory factory = new ProxyFactory(raw);
+
+ MockControl tsControl = MockControl.createControl(SubTimeStamped.class);
+ SubTimeStamped ts = (SubTimeStamped) tsControl.getMock();
+ ts.getTimeStamp();
+ long timestamp = 111L;
+ tsControl.setReturnValue(timestamp, 1);
+ tsControl.replay();
+
+ factory.addAdvisor(0, new DefaultIntroductionAdvisor(new DelegatingIntroductionInterceptor(ts), TimeStamped.class));
+
+ TimeStamped tsp = (TimeStamped) factory.getProxy();
+ assertTrue(!(tsp instanceof SubTimeStamped));
+ assertTrue(tsp.getTimeStamp() == timestamp);
+
+ tsControl.verify();
+ }
+
+ public void testAutomaticInterfaceRecognitionInDelegate() throws Exception {
+ final long t = 1001L;
+ class Tester implements TimeStamped, ITester {
+ public void foo() throws Exception {
+ }
+ public long getTimeStamp() {
+ return t;
+ }
+ }
+
+ DelegatingIntroductionInterceptor ii = new DelegatingIntroductionInterceptor(new Tester());
+
+ TestBean target = new TestBean();
+
+ ProxyFactory pf = new ProxyFactory(target);
+ pf.addAdvisor(0, new DefaultIntroductionAdvisor(ii));
+
+ //assertTrue(Arrays.binarySearch(pf.getProxiedInterfaces(), TimeStamped.class) != -1);
+ TimeStamped ts = (TimeStamped) pf.getProxy();
+
+ assertTrue(ts.getTimeStamp() == t);
+ ((ITester) ts).foo();
+
+ ((ITestBean) ts).getAge();
+ }
+
+
+ public void testAutomaticInterfaceRecognitionInSubclass() throws Exception {
+ final long t = 1001L;
+ class TestII extends DelegatingIntroductionInterceptor implements TimeStamped, ITester {
+ public void foo() throws Exception {
+ }
+ public long getTimeStamp() {
+ return t;
+ }
+ }
+
+ DelegatingIntroductionInterceptor ii = new TestII();
+
+ TestBean target = new TestBean();
+
+ ProxyFactory pf = new ProxyFactory(target);
+ IntroductionAdvisor ia = new DefaultIntroductionAdvisor(ii);
+ assertTrue(ia.isPerInstance());
+ pf.addAdvisor(0, ia);
+
+ //assertTrue(Arrays.binarySearch(pf.getProxiedInterfaces(), TimeStamped.class) != -1);
+ TimeStamped ts = (TimeStamped) pf.getProxy();
+
+ assertTrue(ts instanceof TimeStamped);
+ // Shoulnd't proxy framework interfaces
+ assertTrue(!(ts instanceof MethodInterceptor));
+ assertTrue(!(ts instanceof IntroductionInterceptor));
+
+ assertTrue(ts.getTimeStamp() == t);
+ ((ITester) ts).foo();
+ ((ITestBean) ts).getAge();
+
+ // Test removal
+ ii.suppressInterface(TimeStamped.class);
+ // Note that we need to construct a new proxy factory,
+ // or suppress the interface on the proxy factory
+ pf = new ProxyFactory(target);
+ pf.addAdvisor(0, new DefaultIntroductionAdvisor(ii));
+ Object o = pf.getProxy();
+ assertTrue(!(o instanceof TimeStamped));
+ }
+
+ public void testIntroductionInterceptorDoesntReplaceToString() throws Exception {
+ TestBean raw = new TestBean();
+ assertTrue(! (raw instanceof TimeStamped));
+ ProxyFactory factory = new ProxyFactory(raw);
+
+ TimeStamped ts = new SerializableTimeStamped(0);
+
+ factory.addAdvisor(0, new DefaultIntroductionAdvisor(new DelegatingIntroductionInterceptor(ts) {
+ public String toString() {
+ throw new UnsupportedOperationException("Shouldn't be invoked");
+ }
+ }));
+
+ TimeStamped tsp = (TimeStamped) factory.getProxy();
+ assertEquals(0, tsp.getTimeStamp());
+
+ assertEquals(raw.toString(), tsp.toString());
+ }
+
+ public void testDelegateReturnsThisIsMassagedToReturnProxy() {
+ NestedTestBean target = new NestedTestBean();
+ String company = "Interface21";
+ target.setCompany(company);
+ TestBean delegate = new TestBean() {
+ public ITestBean getSpouse() {
+ return this;
+ }
+ };
+ ProxyFactory pf = new ProxyFactory(target);
+ pf.addAdvice(new DelegatingIntroductionInterceptor(delegate));
+ INestedTestBean proxy = (INestedTestBean) pf.getProxy();
+
+ assertEquals(company, proxy.getCompany());
+ ITestBean introduction = (ITestBean) proxy;
+ assertSame("Introduced method returning delegate returns proxy", introduction, introduction.getSpouse());
+ assertTrue("Introduced method returning delegate returns proxy", AopUtils.isAopProxy(introduction.getSpouse()));
+ }
+
+ public void testSerializableDelegatingIntroductionInterceptorSerializable() throws Exception {
+ SerializablePerson serializableTarget = new SerializablePerson();
+ String name = "Tony";
+ serializableTarget.setName("Tony");
+
+ ProxyFactory factory = new ProxyFactory(serializableTarget);
+ factory.addInterface(Person.class);
+ long time = 1000;
+ TimeStamped ts = new SerializableTimeStamped(time);
+
+ factory.addAdvisor(new DefaultIntroductionAdvisor(new DelegatingIntroductionInterceptor(ts)));
+ factory.addAdvice(new SerializableNopInterceptor());
+
+ Person p = (Person) factory.getProxy();
+
+ assertEquals(name, p.getName());
+ assertEquals(time, ((TimeStamped) p).getTimeStamp());
+
+ Person p1 = (Person) SerializationTestUtils.serializeAndDeserialize(p);
+ assertEquals(name, p1.getName());
+ assertEquals(time, ((TimeStamped) p1).getTimeStamp());
+ }
+
+// public void testDelegatingIntroductionInterceptorDoesntMakeNonserializableSerializable() throws Exception {
+// // Target is NOT serialiable
+// TestBean raw = new TestBean();
+// ProxyFactory factory = new ProxyFactory(raw);
+// factory.addInterface(Person.class);
+// long time = 1000;
+// TimeStamped ts = new SerializableTimeStamped(time);
+//
+// factory.addAdvisor(new DefaultIntroductionAdvisor(new DelegatingIntroductionInterceptor(ts)));
+// Object proxy = factory.getProxy();
+//
+// assertFalse(proxy instanceof Serializable);
+// }
+
+ // Test when target implements the interface: should get interceptor by preference.
+ public void testIntroductionMasksTargetImplementation() throws Exception {
+ final long t = 1001L;
+ class TestII extends DelegatingIntroductionInterceptor implements TimeStamped {
+ public long getTimeStamp() {
+ return t;
+ }
+ }
+
+ DelegatingIntroductionInterceptor ii = new TestII();
+
+ // != t
+ TestBean target = new TargetClass(t + 1);
+
+ ProxyFactory pf = new ProxyFactory(target);
+ pf.addAdvisor(0, new DefaultIntroductionAdvisor(ii));
+
+ TimeStamped ts = (TimeStamped) pf.getProxy();
+ // From introduction interceptor, not target
+ assertTrue(ts.getTimeStamp() == t);
+ }
+
+
+ private static class SerializableTimeStamped implements TimeStamped, Serializable {
+
+ private final long ts;
+
+ public SerializableTimeStamped(long ts) {
+ this.ts = ts;
+ }
+
+ public long getTimeStamp() {
+ return ts;
+ }
+ }
+
+
+ public static class TargetClass extends TestBean implements TimeStamped {
+
+ long t;
+
+ public TargetClass(long t) {
+ this.t = t;
+ }
+
+ public long getTimeStamp() {
+ return t;
+ }
+ }
+
+
+ public interface ITester {
+
+ void foo() throws Exception;
+ }
+
+
+ private static interface SubTimeStamped extends TimeStamped {
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/support/JdkRegexpMethodPointcutTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/JdkRegexpMethodPointcutTests.java
new file mode 100644
index 00000000000..a8d9aa20f2f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/JdkRegexpMethodPointcutTests.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.support;
+
+/**
+ * @author Dmitriy Kopylenko
+ */
+public class JdkRegexpMethodPointcutTests extends AbstractRegexpMethodPointcutTests {
+
+ protected AbstractRegexpMethodPointcut getRegexpMethodPointcut() {
+ return new JdkRegexpMethodPointcut();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/support/MethodMatchersTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/MethodMatchersTests.java
new file mode 100644
index 00000000000..8693653cad1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/MethodMatchersTests.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.support;
+
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.MethodMatcher;
+import org.springframework.beans.IOther;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.util.SerializationTestUtils;
+
+/**
+ * $Id: MethodMatchersTests.java,v 1.7 2005/03/25 09:28:18 jhoeller Exp $
+ */
+public class MethodMatchersTests extends TestCase {
+
+ private final Method EXCEPTION_GETMESSAGE;
+
+ private final Method ITESTBEAN_SETAGE;
+
+ private final Method ITESTBEAN_GETAGE;
+
+ private final Method IOTHER_ABSQUATULATE;
+
+ public MethodMatchersTests() throws Exception {
+ EXCEPTION_GETMESSAGE = Exception.class.getMethod("getMessage", (Class[]) null);
+ ITESTBEAN_GETAGE = ITestBean.class.getMethod("getAge", (Class[]) null);
+ ITESTBEAN_SETAGE = ITestBean.class.getMethod("setAge", new Class[] { int.class });
+ IOTHER_ABSQUATULATE = IOther.class.getMethod("absquatulate", (Class[]) null);
+ }
+
+ public void testDefaultMatchesAll() throws Exception {
+ MethodMatcher defaultMm = MethodMatcher.TRUE;
+ assertTrue(defaultMm.matches(EXCEPTION_GETMESSAGE, Exception.class));
+ assertTrue(defaultMm.matches(ITESTBEAN_SETAGE, TestBean.class));
+ }
+
+ public void testMethodMatcherTrueSerializable() throws Exception {
+ assertSame(SerializationTestUtils.serializeAndDeserialize(MethodMatcher.TRUE), MethodMatcher.TRUE);
+ }
+
+ public void testSingle() throws Exception {
+ MethodMatcher defaultMm = MethodMatcher.TRUE;
+ assertTrue(defaultMm.matches(EXCEPTION_GETMESSAGE, Exception.class));
+ assertTrue(defaultMm.matches(ITESTBEAN_SETAGE, TestBean.class));
+ defaultMm = MethodMatchers.intersection(defaultMm, new StartsWithMatcher("get"));
+
+ assertTrue(defaultMm.matches(EXCEPTION_GETMESSAGE, Exception.class));
+ assertFalse(defaultMm.matches(ITESTBEAN_SETAGE, TestBean.class));
+ }
+
+
+ public void testDynamicAndStaticMethodMatcherIntersection() throws Exception {
+ MethodMatcher mm1 = MethodMatcher.TRUE;
+ MethodMatcher mm2 = new TestDynamicMethodMatcherWhichMatches();
+ MethodMatcher intersection = MethodMatchers.intersection(mm1, mm2);
+ assertTrue("Intersection is a dynamic matcher", intersection.isRuntime());
+ assertTrue("2Matched setAge method", intersection.matches(ITESTBEAN_SETAGE, TestBean.class));
+ assertTrue("3Matched setAge method", intersection.matches(ITESTBEAN_SETAGE, TestBean.class, new Object[] { new Integer(5) }));
+ // Knock out dynamic part
+ intersection = MethodMatchers.intersection(intersection, new TestDynamicMethodMatcherWhichDoesNotMatch());
+ assertTrue("Intersection is a dynamic matcher", intersection.isRuntime());
+ assertTrue("2Matched setAge method", intersection.matches(ITESTBEAN_SETAGE, TestBean.class));
+ assertFalse("3 - not Matched setAge method", intersection.matches(ITESTBEAN_SETAGE, TestBean.class, new Object[] { new Integer(5) }));
+ }
+
+ public void testStaticMethodMatcherUnion() throws Exception {
+ MethodMatcher getterMatcher = new StartsWithMatcher("get");
+ MethodMatcher setterMatcher = new StartsWithMatcher("set");
+ MethodMatcher union = MethodMatchers.union(getterMatcher, setterMatcher);
+
+ assertFalse("Union is a static matcher", union.isRuntime());
+ assertTrue("Matched setAge method", union.matches(ITESTBEAN_SETAGE, TestBean.class));
+ assertTrue("Matched getAge method", union.matches(ITESTBEAN_GETAGE, TestBean.class));
+ assertFalse("Didn't matched absquatulate method", union.matches(IOTHER_ABSQUATULATE, TestBean.class));
+
+ }
+
+
+ public static class StartsWithMatcher extends StaticMethodMatcher {
+ private String prefix;
+ public StartsWithMatcher(String s) {
+ this.prefix = s;
+ }
+ public boolean matches(Method m, Class targetClass) {
+ return m.getName().startsWith(prefix);
+ }
+ }
+
+
+ private static class TestDynamicMethodMatcherWhichMatches extends DynamicMethodMatcher {
+ public boolean matches(Method m, Class targetClass, Object[] args) {
+ return true;
+ }
+ }
+
+ private static class TestDynamicMethodMatcherWhichDoesNotMatch extends DynamicMethodMatcher {
+ public boolean matches(Method m, Class targetClass, Object[] args) {
+ return false;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/support/NameMatchMethodPointcutTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/NameMatchMethodPointcutTests.java
new file mode 100644
index 00000000000..409fda76759
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/NameMatchMethodPointcutTests.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.support;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.framework.Advised;
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.aop.interceptor.NopInterceptor;
+import org.springframework.aop.interceptor.SerializableNopInterceptor;
+import org.springframework.beans.Person;
+import org.springframework.beans.SerializablePerson;
+import org.springframework.util.SerializationTestUtils;
+
+/**
+ *
+ * @author Rod Johnson
+ */
+public class NameMatchMethodPointcutTests extends TestCase {
+
+ protected NameMatchMethodPointcut pc;
+
+ protected Person proxied;
+
+ protected SerializableNopInterceptor nop;
+
+ public NameMatchMethodPointcutTests(String s) {
+ super(s);
+ }
+
+ /**
+ * Create an empty pointcut, populating instance variables.
+ * @see junit.framework.TestCase#setUp()
+ */
+ protected void setUp() {
+ ProxyFactory pf = new ProxyFactory(new SerializablePerson());
+ nop = new SerializableNopInterceptor();
+ pc = new NameMatchMethodPointcut();
+ pf.addAdvisor(new DefaultPointcutAdvisor(pc, nop));
+ proxied = (Person) pf.getProxy();
+ }
+
+ public void testMatchingOnly() {
+ // Can't do exact matching through isMatch
+ assertTrue(pc.isMatch("echo", "ech*"));
+ assertTrue(pc.isMatch("setName", "setN*"));
+ assertTrue(pc.isMatch("setName", "set*"));
+ assertFalse(pc.isMatch("getName", "set*"));
+ assertFalse(pc.isMatch("setName", "set"));
+ assertTrue(pc.isMatch("testing", "*ing"));
+ }
+
+ public void testEmpty() throws Throwable {
+ assertEquals(0, nop.getCount());
+ proxied.getName();
+ proxied.setName("");
+ proxied.echo(null);
+ assertEquals(0, nop.getCount());
+ }
+
+
+ public void testMatchOneMethod() throws Throwable {
+ pc.addMethodName("echo");
+ pc.addMethodName("set*");
+ assertEquals(0, nop.getCount());
+ proxied.getName();
+ proxied.getName();
+ assertEquals(0, nop.getCount());
+ proxied.echo(null);
+ assertEquals(1, nop.getCount());
+
+ proxied.setName("");
+ assertEquals(2, nop.getCount());
+ proxied.setAge(25);
+ assertEquals(25, proxied.getAge());
+ assertEquals(3, nop.getCount());
+ }
+
+ public void testSets() throws Throwable {
+ pc.setMappedNames(new String[] { "set*", "echo" });
+ assertEquals(0, nop.getCount());
+ proxied.getName();
+ proxied.setName("");
+ assertEquals(1, nop.getCount());
+ proxied.echo(null);
+ assertEquals(2, nop.getCount());
+ }
+
+ public void testSerializable() throws Throwable {
+ testSets();
+ // Count is now 2
+ Person p2 = (Person) SerializationTestUtils.serializeAndDeserialize(proxied);
+ NopInterceptor nop2 = (NopInterceptor) ((Advised) p2).getAdvisors()[0].getAdvice();
+ p2.getName();
+ assertEquals(2, nop2.getCount());
+ p2.echo(null);
+ assertEquals(3, nop2.getCount());
+ }
+
+ public void testEqualsAndHashCode() throws Exception {
+ NameMatchMethodPointcut pc1 = new NameMatchMethodPointcut();
+ NameMatchMethodPointcut pc2 = new NameMatchMethodPointcut();
+
+ String foo = "foo";
+
+ assertEquals(pc1, pc2);
+ assertEquals(pc1.hashCode(), pc2.hashCode());
+
+ pc1.setMappedName(foo);
+ assertFalse(pc1.equals(pc2));
+ assertTrue(pc1.hashCode() != pc2.hashCode());
+
+ pc2.setMappedName(foo);
+ assertEquals(pc1, pc2);
+ assertEquals(pc1.hashCode(), pc2.hashCode());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/support/PointcutsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/PointcutsTests.java
new file mode 100644
index 00000000000..115903240c6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/PointcutsTests.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.support;
+
+import java.lang.reflect.Method;
+
+import org.springframework.aop.ClassFilter;
+import org.springframework.aop.Pointcut;
+import org.springframework.beans.TestBean;
+
+import junit.framework.TestCase;
+
+/**
+ *
+ * @author Rod Johnson
+ */
+public class PointcutsTests extends TestCase {
+
+ public static Method TEST_BEAN_SET_AGE;
+ public static Method TEST_BEAN_GET_AGE;
+ public static Method TEST_BEAN_GET_NAME;
+ public static Method TEST_BEAN_ABSQUATULATE;
+
+ static {
+ try {
+ TEST_BEAN_SET_AGE = TestBean.class.getMethod("setAge", new Class[] { int.class });
+ TEST_BEAN_GET_AGE = TestBean.class.getMethod("getAge", (Class[]) null);
+ TEST_BEAN_GET_NAME = TestBean.class.getMethod("getName", (Class[]) null);
+ TEST_BEAN_ABSQUATULATE = TestBean.class.getMethod("absquatulate", (Class[]) null);
+ }
+ catch (Exception ex) {
+ throw new RuntimeException("Shouldn't happen: error in test suite");
+ }
+ }
+
+ /**
+ * Matches only TestBean class, not subclasses
+ */
+ public static Pointcut allTestBeanMethodsPointcut = new StaticMethodMatcherPointcut() {
+ public ClassFilter getClassFilter() {
+ return new ClassFilter() {
+ public boolean matches(Class clazz) {
+ return clazz.equals(TestBean.class);
+ }
+ };
+ }
+
+ public boolean matches(Method m, Class targetClass) {
+ return true;
+ }
+ };
+
+ public static Pointcut allClassSetterPointcut = Pointcuts.SETTERS;
+
+ // Subclass used for matching
+ public static class MyTestBean extends TestBean {
+ }
+
+ public static Pointcut myTestBeanSetterPointcut = new StaticMethodMatcherPointcut() {
+ public ClassFilter getClassFilter() {
+ return new RootClassFilter(MyTestBean.class);
+ }
+
+ public boolean matches(Method m, Class targetClass) {
+ return m.getName().startsWith("set");
+ }
+ };
+
+ // Will match MyTestBeanSubclass
+ public static Pointcut myTestBeanGetterPointcut = new StaticMethodMatcherPointcut() {
+ public ClassFilter getClassFilter() {
+ return new RootClassFilter(MyTestBean.class);
+ }
+
+ public boolean matches(Method m, Class targetClass) {
+ return m.getName().startsWith("get");
+ }
+ };
+
+ // Still more specific class
+ public static class MyTestBeanSubclass extends MyTestBean {
+ }
+
+ public static Pointcut myTestBeanSubclassGetterPointcut = new StaticMethodMatcherPointcut() {
+ public ClassFilter getClassFilter() {
+ return new RootClassFilter(MyTestBeanSubclass.class);
+ }
+
+ public boolean matches(Method m, Class targetClass) {
+ return m.getName().startsWith("get");
+ }
+ };
+
+ public static Pointcut allClassGetterPointcut = Pointcuts.GETTERS;
+
+ public static Pointcut allClassGetAgePointcut = new NameMatchMethodPointcut().addMethodName("getAge");
+
+ public static Pointcut allClassGetNamePointcut = new NameMatchMethodPointcut().addMethodName("getName");
+
+
+ public PointcutsTests(String s) {
+ super(s);
+ }
+
+ public void testTrue() {
+ assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
+ assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_GET_AGE, TestBean.class, null));
+ assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
+ assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
+ assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_GET_AGE, TestBean.class, null));
+ assertTrue(Pointcuts.matches(Pointcut.TRUE, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
+ }
+
+ public void testMatches() {
+ assertTrue(Pointcuts.matches(allClassSetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
+ assertFalse(Pointcuts.matches(allClassSetterPointcut, TEST_BEAN_GET_AGE, TestBean.class, null));
+ assertFalse(Pointcuts.matches(allClassSetterPointcut, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
+ assertFalse(Pointcuts.matches(allClassGetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
+ assertTrue(Pointcuts.matches(allClassGetterPointcut, TEST_BEAN_GET_AGE, TestBean.class, null));
+ assertFalse(Pointcuts.matches(allClassGetterPointcut, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
+ }
+
+ /**
+ * Should match all setters and getters on any class
+ */
+ public void testUnionOfSettersAndGetters() {
+ Pointcut union = Pointcuts.union(allClassGetterPointcut, allClassSetterPointcut);
+ assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
+ assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class, null));
+ assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
+ }
+
+ public void testUnionOfSpecificGetters() {
+ Pointcut union = Pointcuts.union(allClassGetAgePointcut, allClassGetNamePointcut);
+ assertFalse(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
+ assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class, null));
+ assertFalse(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_NAME, TestBean.class, null));
+ assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_NAME, TestBean.class, null));
+ assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
+
+ // Union with all setters
+ union = Pointcuts.union(union, allClassSetterPointcut);
+ assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
+ assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class, null));
+ assertFalse(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_NAME, TestBean.class, null));
+ assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_NAME, TestBean.class, null));
+ assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
+
+ assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
+ }
+
+ /**
+ * Tests vertical composition. First pointcut matches all setters.
+ * Second one matches all getters in the MyTestBean class. TestBean getters shouldn't pass.
+ */
+ public void testUnionOfAllSettersAndSubclassSetters() {
+ assertFalse(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
+ assertTrue(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_SET_AGE, MyTestBean.class, new Object[] { new Integer(6)}));
+ assertFalse(Pointcuts.matches(myTestBeanSetterPointcut, TEST_BEAN_GET_AGE, TestBean.class, null));
+
+ Pointcut union = Pointcuts.union(myTestBeanSetterPointcut, allClassGetterPointcut);
+ assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class, null));
+ assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, MyTestBean.class, null));
+ // Still doesn't match superclass setter
+ assertTrue(Pointcuts.matches(union, TEST_BEAN_SET_AGE, MyTestBean.class, new Object[] { new Integer(6)}));
+ assertFalse(Pointcuts.matches(union, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
+ }
+
+ /**
+ * Intersection should be MyTestBean getAge() only:
+ * it's the union of allClassGetAge and subclass getters
+ */
+ public void testIntersectionOfSpecificGettersAndSubclassGetters() {
+ assertTrue(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_AGE, TestBean.class, null));
+ assertTrue(Pointcuts.matches(allClassGetAgePointcut, TEST_BEAN_GET_AGE, MyTestBean.class, null));
+ assertFalse(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_NAME, TestBean.class, null));
+ assertFalse(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_AGE, TestBean.class, null));
+ assertTrue(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_NAME, MyTestBean.class, null));
+ assertTrue(Pointcuts.matches(myTestBeanGetterPointcut, TEST_BEAN_GET_AGE, MyTestBean.class, null));
+
+ Pointcut intersection = Pointcuts.intersection(allClassGetAgePointcut, myTestBeanGetterPointcut);
+ assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, TestBean.class, null));
+ assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, TestBean.class, null));
+ assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBean.class, null));
+ assertTrue(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBean.class, null));
+ // Matches subclass of MyTestBean
+ assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBeanSubclass.class, null));
+ assertTrue(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBeanSubclass.class, null));
+
+ // Now intersection with MyTestBeanSubclass getters should eliminate MyTestBean target
+ intersection = Pointcuts.intersection(intersection, myTestBeanSubclassGetterPointcut);
+ assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, TestBean.class, null));
+ assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, TestBean.class, null));
+ assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBean.class, null));
+ assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBean.class, null));
+ // Still matches subclass of MyTestBean
+ assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_NAME, MyTestBeanSubclass.class, null));
+ assertTrue(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, MyTestBeanSubclass.class, null));
+
+ // Now union with all TestBean methods
+ Pointcut union = Pointcuts.union(intersection, allTestBeanMethodsPointcut);
+ assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_NAME, TestBean.class, null));
+ assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, TestBean.class, null));
+ assertFalse(Pointcuts.matches(union, TEST_BEAN_GET_NAME, MyTestBean.class, null));
+ assertFalse(Pointcuts.matches(union, TEST_BEAN_GET_AGE, MyTestBean.class, null));
+ // Still matches subclass of MyTestBean
+ assertFalse(Pointcuts.matches(union, TEST_BEAN_GET_NAME, MyTestBeanSubclass.class, null));
+ assertTrue(Pointcuts.matches(union, TEST_BEAN_GET_AGE, MyTestBeanSubclass.class, null));
+
+ assertTrue(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
+ assertFalse(Pointcuts.matches(union, TEST_BEAN_ABSQUATULATE, MyTestBean.class, null));
+ }
+
+
+ /**
+ * The intersection of these two pointcuts leaves nothing.
+ */
+ public void testSimpleIntersection() {
+ Pointcut intersection = Pointcuts.intersection(allClassGetterPointcut, allClassSetterPointcut);
+ assertFalse(Pointcuts.matches(intersection, TEST_BEAN_SET_AGE, TestBean.class, new Object[] { new Integer(6)}));
+ assertFalse(Pointcuts.matches(intersection, TEST_BEAN_GET_AGE, TestBean.class, null));
+ assertFalse(Pointcuts.matches(intersection, TEST_BEAN_ABSQUATULATE, TestBean.class, null));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/support/RegexpMethodPointcutAdvisorIntegrationTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/RegexpMethodPointcutAdvisorIntegrationTests.java
new file mode 100644
index 00000000000..08b86911375
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/RegexpMethodPointcutAdvisorIntegrationTests.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.support;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.framework.Advised;
+import org.springframework.aop.interceptor.NopInterceptor;
+import org.springframework.aop.interceptor.SerializableNopInterceptor;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.Person;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.util.SerializationTestUtils;
+
+/**
+ * @author Rod Johnson
+ */
+public class RegexpMethodPointcutAdvisorIntegrationTests extends TestCase {
+
+ public void testSinglePattern() throws Throwable {
+ BeanFactory bf = new ClassPathXmlApplicationContext("org/springframework/aop/support/regexpSetterTests.xml");
+ ITestBean advised = (ITestBean) bf.getBean("settersAdvised");
+ // Interceptor behind regexp advisor
+ NopInterceptor nop = (NopInterceptor) bf.getBean("nopInterceptor");
+ assertEquals(0, nop.getCount());
+
+ int newAge = 12;
+ // Not advised
+ advised.exceptional(null);
+ assertEquals(0, nop.getCount());
+ advised.setAge(newAge);
+ assertEquals(newAge, advised.getAge());
+ // Only setter fired
+ assertEquals(1, nop.getCount());
+ }
+
+ public void testMultiplePatterns() throws Throwable {
+ BeanFactory bf = new ClassPathXmlApplicationContext("org/springframework/aop/support/regexpSetterTests.xml");
+ // This is a CGLIB proxy, so we can proxy it to the target class
+ TestBean advised = (TestBean) bf.getBean("settersAndAbsquatulateAdvised");
+ // Interceptor behind regexp advisor
+ NopInterceptor nop = (NopInterceptor) bf.getBean("nopInterceptor");
+ assertEquals(0, nop.getCount());
+
+ int newAge = 12;
+ // Not advised
+ advised.exceptional(null);
+ assertEquals(0, nop.getCount());
+
+ // This is proxied
+ advised.absquatulate();
+ assertEquals(1, nop.getCount());
+ advised.setAge(newAge);
+ assertEquals(newAge, advised.getAge());
+ // Only setter fired
+ assertEquals(2, nop.getCount());
+ }
+
+ public void testSerialization() throws Throwable {
+ BeanFactory bf = new ClassPathXmlApplicationContext("org/springframework/aop/support/regexpSetterTests.xml");
+ // This is a CGLIB proxy, so we can proxy it to the target class
+ Person p = (Person) bf.getBean("serializableSettersAdvised");
+ // Interceptor behind regexp advisor
+ NopInterceptor nop = (NopInterceptor) bf.getBean("nopInterceptor");
+ assertEquals(0, nop.getCount());
+
+ int newAge = 12;
+ // Not advised
+ assertEquals(0, p.getAge());
+ assertEquals(0, nop.getCount());
+
+ // This is proxied
+ p.setAge(newAge);
+ assertEquals(1, nop.getCount());
+ p.setAge(newAge);
+ assertEquals(newAge, p.getAge());
+ // Only setter fired
+ assertEquals(2, nop.getCount());
+
+ // Serialize and continue...
+ p = (Person) SerializationTestUtils.serializeAndDeserialize(p);
+ assertEquals(newAge, p.getAge());
+ // Remembers count, but we need to get a new reference to nop...
+ nop = (SerializableNopInterceptor) ((Advised) p).getAdvisors()[0].getAdvice();
+ assertEquals(2, nop.getCount());
+ assertEquals("serializableSettersAdvised", p.getName());
+ p.setAge(newAge + 1);
+ assertEquals(3, nop.getCount());
+ assertEquals(newAge + 1, p.getAge());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/support/regexpSetterTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/regexpSetterTests.xml
new file mode 100644
index 00000000000..2d14f2dc0cd
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/support/regexpSetterTests.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+ custom
+ 666
+
+
+
+
+
+
+
+
+ .*set.*
+
+
+
+
+
+ org.springframework.beans.ITestBean
+
+ settersAdvisor
+
+
+
+ org.springframework.beans.Person
+
+
+ serializableSettersAdvised
+
+
+ settersAdvisor
+
+
+
+
+
+
+
+ .*get.*
+ .*absquatulate
+
+
+
+
+
+ org.springframework.beans.ITestBean
+
+ true
+
+ settersAndAbsquatulateAdvisor
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/target/CommonsPoolTargetSourceProxyTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/CommonsPoolTargetSourceProxyTests.java
new file mode 100644
index 00000000000..8675a3ab8b3
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/CommonsPoolTargetSourceProxyTests.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.target;
+
+import junit.framework.TestCase;
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.ITestBean;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.aop.support.AopUtils;
+
+/**
+ * @author Rob Harrop
+ * @since 2.0
+ */
+public class CommonsPoolTargetSourceProxyTests extends TestCase {
+
+ public void testProxy() throws Exception {
+ DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
+ reader.loadBeanDefinitions(new ClassPathResource("commonsPoolProxyTests.xml", getClass()));
+ beanFactory.preInstantiateSingletons();
+ ITestBean bean = (ITestBean)beanFactory.getBean("testBean");
+ assertTrue(AopUtils.isAopProxy(bean));
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/target/CommonsPoolTargetSourceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/CommonsPoolTargetSourceTests.java
new file mode 100644
index 00000000000..68b47605feb
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/CommonsPoolTargetSourceTests.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.target;
+
+import java.util.NoSuchElementException;
+
+import junit.framework.TestCase;
+import org.apache.commons.pool.impl.GenericObjectPool;
+
+import org.springframework.aop.framework.Advised;
+import org.springframework.aop.interceptor.SideEffectBean;
+import org.springframework.beans.Person;
+import org.springframework.beans.SerializablePerson;
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.context.support.StaticApplicationContext;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.util.SerializationTestUtils;
+
+/**
+ * Tests for pooling invoker interceptor.
+ * TODO: need to make these tests stronger: it's hard to
+ * make too many assumptions about a pool.
+ *
+ * @author Rod Johnson
+ * @author Rob Harrop
+ */
+public class CommonsPoolTargetSourceTests extends TestCase {
+
+ /**
+ * Initial count value set in bean factory XML
+ */
+ private static final int INITIAL_COUNT = 10;
+
+ private XmlBeanFactory beanFactory;
+
+ protected void setUp() throws Exception {
+ this.beanFactory = new XmlBeanFactory(new ClassPathResource("commonsPoolTests.xml", getClass()));
+ }
+
+ /**
+ * We must simulate container shutdown, which should clear threads.
+ */
+ protected void tearDown() {
+ // Will call pool.close()
+ this.beanFactory.destroySingletons();
+ }
+
+ private void testFunctionality(String name) {
+ SideEffectBean pooled = (SideEffectBean) beanFactory.getBean(name);
+ assertEquals(INITIAL_COUNT, pooled.getCount());
+ pooled.doWork();
+ assertEquals(INITIAL_COUNT + 1, pooled.getCount());
+
+ pooled = (SideEffectBean) beanFactory.getBean(name);
+ // Just check that it works--we can't make assumptions
+ // about the count
+ pooled.doWork();
+ //assertEquals(INITIAL_COUNT + 1, apartment.getCount() );
+ }
+
+ public void testFunctionality() {
+ testFunctionality("pooled");
+ }
+
+ public void testFunctionalityWithNoInterceptors() {
+ testFunctionality("pooledNoInterceptors");
+ }
+
+ public void testConfigMixin() {
+ SideEffectBean pooled = (SideEffectBean) beanFactory.getBean("pooledWithMixin");
+ assertEquals(INITIAL_COUNT, pooled.getCount());
+ PoolingConfig conf = (PoolingConfig) beanFactory.getBean("pooledWithMixin");
+ // TODO one invocation from setup
+ //assertEquals(1, conf.getInvocations());
+ pooled.doWork();
+ // assertEquals("No objects active", 0, conf.getActive());
+ assertEquals("Correct target source", 25, conf.getMaxSize());
+// assertTrue("Some free", conf.getFree() > 0);
+ //assertEquals(2, conf.getInvocations());
+ assertEquals(25, conf.getMaxSize());
+ }
+
+ public void testTargetSourceSerializableWithoutConfigMixin() throws Exception {
+ CommonsPoolTargetSource cpts = (CommonsPoolTargetSource) beanFactory.getBean("personPoolTargetSource");
+
+ SingletonTargetSource serialized = (SingletonTargetSource) SerializationTestUtils.serializeAndDeserialize(cpts);
+ assertTrue(serialized.getTarget() instanceof Person);
+ }
+
+
+ public void testProxySerializableWithoutConfigMixin() throws Exception {
+ Person pooled = (Person) beanFactory.getBean("pooledPerson");
+
+ //System.out.println(((Advised) pooled).toProxyConfigString());
+ assertTrue(((Advised) pooled).getTargetSource() instanceof CommonsPoolTargetSource);
+
+ //((Advised) pooled).setTargetSource(new SingletonTargetSource(new SerializablePerson()));
+ Person serialized = (Person) SerializationTestUtils.serializeAndDeserialize(pooled);
+ assertTrue(((Advised) serialized).getTargetSource() instanceof SingletonTargetSource);
+ serialized.setAge(25);
+ assertEquals(25, serialized.getAge());
+ }
+
+ public void testHitMaxSize() throws Exception {
+ int maxSize = 10;
+
+ CommonsPoolTargetSource targetSource = new CommonsPoolTargetSource();
+ targetSource.setMaxSize(maxSize);
+ targetSource.setMaxWait(1);
+ prepareTargetSource(targetSource);
+
+ Object[] pooledInstances = new Object[maxSize];
+
+ for (int x = 0; x < maxSize; x++) {
+ Object instance = targetSource.getTarget();
+ assertNotNull(instance);
+ pooledInstances[x] = instance;
+ }
+
+ // should be at maximum now
+ try {
+ targetSource.getTarget();
+ fail("Should throw NoSuchElementException");
+ }
+ catch (NoSuchElementException ex) {
+ // desired
+ }
+
+ // lets now release an object and try to accquire a new one
+ targetSource.releaseTarget(pooledInstances[9]);
+ pooledInstances[9] = targetSource.getTarget();
+
+ // release all objects
+ for (int i = 0; i < pooledInstances.length; i++) {
+ targetSource.releaseTarget(pooledInstances[i]);
+ }
+ }
+
+ public void testHitMaxSizeLoadedFromContext() throws Exception {
+ Advised person = (Advised) beanFactory.getBean("maxSizePooledPerson");
+ CommonsPoolTargetSource targetSource = (CommonsPoolTargetSource) person.getTargetSource();
+
+ int maxSize = targetSource.getMaxSize();
+ Object[] pooledInstances = new Object[maxSize];
+
+ for (int x = 0; x < maxSize; x++) {
+ Object instance = targetSource.getTarget();
+ assertNotNull(instance);
+ pooledInstances[x] = instance;
+ }
+
+ // should be at maximum now
+ try {
+ targetSource.getTarget();
+ fail("Should throw NoSuchElementException");
+ }
+ catch (NoSuchElementException ex) {
+ // desired
+ }
+
+ // lets now release an object and try to accquire a new one
+ targetSource.releaseTarget(pooledInstances[9]);
+ pooledInstances[9] = targetSource.getTarget();
+
+ // release all objects
+ for (int i = 0; i < pooledInstances.length; i++) {
+ targetSource.releaseTarget(pooledInstances[i]);
+ }
+ }
+
+ public void testSetWhenExhaustedAction() {
+ CommonsPoolTargetSource targetSource = new CommonsPoolTargetSource();
+ targetSource.setWhenExhaustedActionName("WHEN_EXHAUSTED_BLOCK");
+ assertEquals(GenericObjectPool.WHEN_EXHAUSTED_BLOCK, targetSource.getWhenExhaustedAction());
+ }
+
+ private void prepareTargetSource(CommonsPoolTargetSource targetSource) {
+ String beanName = "target";
+
+ StaticApplicationContext applicationContext = new StaticApplicationContext();
+ applicationContext.registerPrototype(beanName, SerializablePerson.class);
+
+ targetSource.setTargetBeanName(beanName);
+ targetSource.setBeanFactory(applicationContext);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/target/HotSwappableTargetSourceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/HotSwappableTargetSourceTests.java
new file mode 100644
index 00000000000..3115144eb7e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/HotSwappableTargetSourceTests.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.target;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.framework.Advised;
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.aop.interceptor.SerializableNopInterceptor;
+import org.springframework.aop.interceptor.SideEffectBean;
+import org.springframework.aop.support.DefaultPointcutAdvisor;
+import org.springframework.beans.Person;
+import org.springframework.beans.SerializablePerson;
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.util.SerializationTestUtils;
+
+/**
+ * @author Rod Johnson
+ */
+public class HotSwappableTargetSourceTests extends TestCase {
+
+ /** Initial count value set in bean factory XML */
+ private static final int INITIAL_COUNT = 10;
+
+ private XmlBeanFactory beanFactory;
+
+ protected void setUp() throws Exception {
+ this.beanFactory = new XmlBeanFactory(new ClassPathResource("hotSwapTests.xml", getClass()));
+ }
+
+ /**
+ * We must simulate container shutdown, which should clear threads.
+ */
+ protected void tearDown() {
+ // Will call pool.close()
+ this.beanFactory.destroySingletons();
+ }
+
+ /**
+ * Check it works like a normal invoker
+ *
+ */
+ public void testBasicFunctionality() {
+ SideEffectBean target1 = (SideEffectBean) beanFactory.getBean("target1");
+ SideEffectBean proxied = (SideEffectBean) beanFactory.getBean("swappable");
+ assertEquals(INITIAL_COUNT, proxied.getCount() );
+ proxied.doWork();
+ assertEquals(INITIAL_COUNT + 1, proxied.getCount() );
+
+ proxied = (SideEffectBean) beanFactory.getBean("swappable");
+ proxied.doWork();
+ assertEquals(INITIAL_COUNT + 2, proxied.getCount() );
+ }
+
+ public void testValidSwaps() {
+ SideEffectBean target1 = (SideEffectBean) beanFactory.getBean("target1");
+ SideEffectBean target2 = (SideEffectBean) beanFactory.getBean("target2");
+
+ SideEffectBean proxied = (SideEffectBean) beanFactory.getBean("swappable");
+ // assertEquals(target1, ((Advised) proxied).getTarget());
+ assertEquals(target1.getCount(), proxied.getCount() );
+ proxied.doWork();
+ assertEquals(INITIAL_COUNT + 1, proxied.getCount() );
+
+ HotSwappableTargetSource swapper = (HotSwappableTargetSource) beanFactory.getBean("swapper");
+ Object old = swapper.swap(target2);
+ assertEquals("Correct old target was returned", target1, old);
+
+ // TODO should be able to make this assertion: need to fix target handling
+ // in AdvisedSupport
+ //assertEquals(target2, ((Advised) proxied).getTarget());
+
+ assertEquals(20, proxied.getCount());
+ proxied.doWork();
+ assertEquals(21, target2.getCount());
+
+ // Swap it back
+ swapper.swap(target1);
+ assertEquals(target1.getCount(), proxied.getCount());
+ }
+
+
+ /**
+ *
+ * @param invalid
+ * @return the message
+ */
+ private IllegalArgumentException testRejectsSwapToInvalidValue(Object invalid) {
+ HotSwappableTargetSource swapper = (HotSwappableTargetSource) beanFactory.getBean("swapper");
+ IllegalArgumentException aopex = null;
+ try {
+ swapper.swap(invalid);
+ fail("Shouldn't be able to swap to invalid value [" + invalid + "]");
+ }
+ catch (IllegalArgumentException ex) {
+ // Ok
+ aopex = ex;
+ }
+
+ // It shouldn't be corrupted, it should still work
+ testBasicFunctionality();
+ return aopex;
+ }
+
+ public void testRejectsSwapToNull() {
+ IllegalArgumentException ex = testRejectsSwapToInvalidValue(null);
+ assertTrue(ex.getMessage().indexOf("null") != -1);
+ }
+
+ // TODO test reject swap to wrong interface or class?
+ // how to decide what's valid?
+
+
+ public void testSerialization() throws Exception {
+ SerializablePerson sp1 = new SerializablePerson();
+ sp1.setName("Tony");
+ SerializablePerson sp2 = new SerializablePerson();
+ sp1.setName("Gordon");
+
+ HotSwappableTargetSource hts = new HotSwappableTargetSource(sp1);
+ ProxyFactory pf = new ProxyFactory();
+ pf.addInterface(Person.class);
+ pf.setTargetSource(hts);
+ pf.addAdvisor(new DefaultPointcutAdvisor(new SerializableNopInterceptor()));
+ Person p = (Person) pf.getProxy();
+
+ assertEquals(sp1.getName(), p.getName());
+ hts.swap(sp2);
+ assertEquals(sp2.getName(), p.getName());
+
+ p = (Person) SerializationTestUtils.serializeAndDeserialize(p);
+ // We need to get a reference to the client-side targetsource
+ hts = (HotSwappableTargetSource) ((Advised) p).getTargetSource();
+ assertEquals(sp2.getName(), p.getName());
+ hts.swap(sp1);
+ assertEquals(sp1.getName(), p.getName());
+
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/target/LazyCreationTargetSourceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/LazyCreationTargetSourceTests.java
new file mode 100644
index 00000000000..cae3b1bb87a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/LazyCreationTargetSourceTests.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.aop.target;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.TargetSource;
+import org.springframework.aop.framework.ProxyFactory;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class LazyCreationTargetSourceTests extends TestCase {
+
+ public void testCreateLazy() {
+ TargetSource targetSource = new AbstractLazyCreationTargetSource() {
+ protected Object createObject() {
+ return new InitCountingBean();
+ }
+ public Class getTargetClass() {
+ return InitCountingBean.class;
+ }
+ };
+
+ InitCountingBean proxy = (InitCountingBean) ProxyFactory.getProxy(targetSource);
+ assertEquals("Init count should be 0", 0, InitCountingBean.initCount);
+ assertEquals("Target class incorrect", InitCountingBean.class, targetSource.getTargetClass());
+ assertEquals("Init count should still be 0 after getTargetClass()", 0, InitCountingBean.initCount);
+
+ proxy.doSomething();
+ assertEquals("Init count should now be 1", 1, InitCountingBean.initCount);
+
+ proxy.doSomething();
+ assertEquals("Init count should still be 1", 1, InitCountingBean.initCount);
+ }
+
+
+ private static class InitCountingBean {
+
+ public static int initCount;
+
+ public InitCountingBean() {
+ if (InitCountingBean.class.equals(getClass())) {
+ // only increment when creating the actual target - not the proxy
+ initCount++;
+ }
+ }
+
+ public void doSomething() {
+ //no-op
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/target/LazyInitTargetSourceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/LazyInitTargetSourceTests.java
new file mode 100644
index 00000000000..0f284f4804b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/LazyInitTargetSourceTests.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.target;
+
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Juergen Hoeller
+ * @author Rob Harrop
+ * @since 07.01.2005
+ */
+public class LazyInitTargetSourceTests extends TestCase {
+
+ public void testLazyInitSingletonTargetSource() {
+ XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("lazyInitSingletonTests.xml", getClass()));
+ bf.preInstantiateSingletons();
+
+ ITestBean tb = (ITestBean) bf.getBean("proxy");
+ assertFalse(bf.containsSingleton("target"));
+ assertEquals(10, tb.getAge());
+ assertTrue(bf.containsSingleton("target"));
+ }
+
+ public void testCustomLazyInitSingletonTargetSource() {
+ XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("customLazyInitTarget.xml", getClass()));
+ bf.preInstantiateSingletons();
+
+ ITestBean tb = (ITestBean) bf.getBean("proxy");
+ assertFalse(bf.containsSingleton("target"));
+ assertEquals("Rob Harrop", tb.getName());
+ assertTrue(bf.containsSingleton("target"));
+ }
+
+ public void testLazyInitFactoryBeanTargetSource() {
+ XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("lazyInitFactoryBean.xml", getClass()));
+ bf.preInstantiateSingletons();
+
+ Set set1 = (Set) bf.getBean("proxy1");
+ assertFalse(bf.containsSingleton("target1"));
+ assertTrue(set1.contains("10"));
+ assertTrue(bf.containsSingleton("target1"));
+
+ Set set2 = (Set) bf.getBean("proxy2");
+ assertFalse(bf.containsSingleton("target2"));
+ assertTrue(set2.contains("20"));
+ assertTrue(bf.containsSingleton("target2"));
+ }
+
+
+ public static class CustomLazyInitTargetSource extends LazyInitTargetSource {
+
+ protected void postProcessTargetObject(Object targetObject) {
+ ((ITestBean) targetObject).setName("Rob Harrop");
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/target/PrototypeBasedTargetSourceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/PrototypeBasedTargetSourceTests.java
new file mode 100644
index 00000000000..c3a92a0a813
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/PrototypeBasedTargetSourceTests.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.aop.target;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.TargetSource;
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.SerializablePerson;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.util.SerializationTestUtils;
+
+/**
+ * Unit tests relating to the abstract AbstractPrototypeBasedTargetSource
+ * and not subclasses.
+ *
+ * @author Rod Johnson
+ */
+public class PrototypeBasedTargetSourceTests extends TestCase {
+
+ public void testSerializability() throws Exception {
+ MutablePropertyValues tsPvs = new MutablePropertyValues();
+ tsPvs.addPropertyValue("targetBeanName", "person");
+ RootBeanDefinition tsBd = new RootBeanDefinition(TestTargetSource.class, tsPvs);
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ RootBeanDefinition bd = new RootBeanDefinition(SerializablePerson.class, pvs);
+ bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
+
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ bf.registerBeanDefinition("ts", tsBd);
+ bf.registerBeanDefinition("person", bd);
+
+ TestTargetSource cpts = (TestTargetSource) bf.getBean("ts");
+ TargetSource serialized = (TargetSource) SerializationTestUtils.serializeAndDeserialize(cpts);
+ assertTrue("Changed to SingletonTargetSource on deserialization",
+ serialized instanceof SingletonTargetSource);
+ SingletonTargetSource sts = (SingletonTargetSource) serialized;
+ assertNotNull(sts.getTarget());
+ }
+
+
+ private static class TestTargetSource extends AbstractPrototypeBasedTargetSource {
+
+ /**
+ * Nonserializable test field to check that subclass
+ * state can't prevent serialization from working
+ */
+ private TestBean thisFieldIsNotSerializable = new TestBean();
+
+ public Object getTarget() throws Exception {
+ return newPrototypeInstance();
+ }
+
+ public void releaseTarget(Object target) throws Exception {
+ // Do nothing
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/target/PrototypeTargetSourceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/PrototypeTargetSourceTests.java
new file mode 100644
index 00000000000..292b99b4309
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/PrototypeTargetSourceTests.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.target;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.interceptor.SideEffectBean;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Rod Johnson
+ */
+public class PrototypeTargetSourceTests extends TestCase {
+
+ /** Initial count value set in bean factory XML */
+ private static final int INITIAL_COUNT = 10;
+
+ private BeanFactory beanFactory;
+
+ protected void setUp() throws Exception {
+ this.beanFactory = new XmlBeanFactory(new ClassPathResource("prototypeTests.xml", getClass()));
+ }
+
+ /**
+ * Test that multiple invocations of the prototype bean will result
+ * in no change to visible state, as a new instance is used.
+ * With the singleton, there will be change.
+ */
+ public void testPrototypeAndSingletonBehaveDifferently() {
+ SideEffectBean singleton = (SideEffectBean) beanFactory.getBean("singleton");
+ assertEquals(INITIAL_COUNT, singleton.getCount() );
+ singleton.doWork();
+ assertEquals(INITIAL_COUNT + 1, singleton.getCount() );
+
+ SideEffectBean prototype = (SideEffectBean) beanFactory.getBean("prototype");
+ assertEquals(INITIAL_COUNT, prototype.getCount() );
+ prototype.doWork();
+ assertEquals(INITIAL_COUNT, prototype.getCount() );
+ }
+
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/target/ThreadLocalTargetSourceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/ThreadLocalTargetSourceTests.java
new file mode 100644
index 00000000000..d5817d8eabb
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/ThreadLocalTargetSourceTests.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.aop.target;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.interceptor.SideEffectBean;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Rod Johnson
+ */
+public class ThreadLocalTargetSourceTests extends TestCase {
+
+ /** Initial count value set in bean factory XML */
+ private static final int INITIAL_COUNT = 10;
+
+ private XmlBeanFactory beanFactory;
+
+ protected void setUp() throws Exception {
+ this.beanFactory = new XmlBeanFactory(new ClassPathResource("threadLocalTests.xml", getClass()));
+ }
+
+ /**
+ * We must simulate container shutdown, which should clear threads.
+ */
+ protected void tearDown() {
+ this.beanFactory.destroySingletons();
+ }
+
+ /**
+ * Check we can use two different ThreadLocalTargetSources
+ * managing objects of different types without them interfering
+ * with one another.
+ */
+ public void testUseDifferentManagedInstancesInSameThread() {
+ SideEffectBean apartment = (SideEffectBean) beanFactory.getBean("apartment");
+ assertEquals(INITIAL_COUNT, apartment.getCount() );
+ apartment.doWork();
+ assertEquals(INITIAL_COUNT + 1, apartment.getCount() );
+
+ ITestBean test = (ITestBean) beanFactory.getBean("threadLocal2");
+ assertEquals("Rod", test.getName());
+ assertEquals("Kerry", test.getSpouse().getName());
+ }
+
+ public void testReuseInSameThread() {
+ SideEffectBean apartment = (SideEffectBean) beanFactory.getBean("apartment");
+ assertEquals(INITIAL_COUNT, apartment.getCount() );
+ apartment.doWork();
+ assertEquals(INITIAL_COUNT + 1, apartment.getCount() );
+
+ apartment = (SideEffectBean) beanFactory.getBean("apartment");
+ assertEquals(INITIAL_COUNT + 1, apartment.getCount() );
+ }
+
+ /**
+ * Relies on introduction.
+ */
+ public void testCanGetStatsViaMixin() {
+ ThreadLocalTargetSourceStats stats = (ThreadLocalTargetSourceStats) beanFactory.getBean("apartment");
+ // +1 because creating target for stats call counts
+ assertEquals(1, stats.getInvocationCount());
+ SideEffectBean apartment = (SideEffectBean) beanFactory.getBean("apartment");
+ apartment.doWork();
+ // +1 again
+ assertEquals(3, stats.getInvocationCount());
+ // + 1 for states call!
+ assertEquals(3, stats.getHitCount());
+ apartment.doWork();
+ assertEquals(6, stats.getInvocationCount());
+ assertEquals(6, stats.getHitCount());
+ // Only one thread so only one object can have been bound
+ assertEquals(1, stats.getObjectCount());
+ }
+
+ public void testNewThreadHasOwnInstance() throws InterruptedException {
+ SideEffectBean apartment = (SideEffectBean) beanFactory.getBean("apartment");
+ assertEquals(INITIAL_COUNT, apartment.getCount() );
+ apartment.doWork();
+ apartment.doWork();
+ apartment.doWork();
+ assertEquals(INITIAL_COUNT + 3, apartment.getCount() );
+
+ class Runner implements Runnable {
+ public SideEffectBean mine;
+ public void run() {
+ this.mine = (SideEffectBean) beanFactory.getBean("apartment");
+ assertEquals(INITIAL_COUNT, mine.getCount() );
+ mine.doWork();
+ assertEquals(INITIAL_COUNT + 1, mine.getCount() );
+ }
+ }
+ Runner r = new Runner();
+ Thread t = new Thread(r);
+ t.start();
+ t.join();
+
+ assertNotNull(r);
+
+ // Check it didn't affect the other thread's copy
+ assertEquals(INITIAL_COUNT + 3, apartment.getCount() );
+
+ // When we use other thread's copy in this thread
+ // it should behave like ours
+ assertEquals(INITIAL_COUNT + 3, r.mine.getCount() );
+
+ // Bound to two threads
+ assertEquals(2, ((ThreadLocalTargetSourceStats) apartment).getObjectCount());
+ }
+
+ /**
+ * Test for SPR-1442. Destroyed target should re-associated with thread and not throw NPE
+ */
+ public void testReuseDestroyedTarget() {
+ ThreadLocalTargetSource source = (ThreadLocalTargetSource)this.beanFactory.getBean("threadLocalTs");
+
+ // try first time
+ Object o = source.getTarget();
+ source.destroy();
+
+ // try second time
+ try {
+ source.getTarget();
+ } catch(NullPointerException ex) {
+ fail("Should not throw NPE");
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/target/commonsPoolProxyTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/commonsPoolProxyTests.xml
new file mode 100644
index 00000000000..47bacce831c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/commonsPoolProxyTests.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/target/commonsPoolTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/commonsPoolTests.xml
new file mode 100644
index 00000000000..a67be5b92f0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/commonsPoolTests.xml
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+ 10
+
+
+
+ prototypeTest
+ 25
+
+
+
+
+ getPoolingConfigMixin
+
+
+
+
+
+
+
+ nop
+
+
+
+
+
+
+
+
+ poolConfigAdvisor
+
+ true
+
+
+
+
+
+
+
+
+ prototypePerson
+ 10
+
+
+
+
+ serializableNop
+
+
+
+
+
+
+
+
+
+
+
+ serializableNop
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/target/customLazyInitTarget.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/customLazyInitTarget.xml
new file mode 100644
index 00000000000..09782ac5c02
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/customLazyInitTarget.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ 10
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/target/dynamic/RefreshableTargetSourceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/dynamic/RefreshableTargetSourceTests.java
new file mode 100644
index 00000000000..cc4aee4b4d7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/dynamic/RefreshableTargetSourceTests.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.aop.target.dynamic;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rob Harrop
+ */
+public class RefreshableTargetSourceTests extends TestCase {
+
+ /**
+ * Test what happens when checking for refresh but not refreshing object.
+ */
+ public void testRefreshCheckWithNonRefresh() throws Exception {
+ CountingRefreshableTargetSource ts = new CountingRefreshableTargetSource();
+ ts.setRefreshCheckDelay(0);
+
+ Object a = ts.getTarget();
+ Thread.sleep(1);
+ Object b = ts.getTarget();
+
+ assertEquals("Should be one call to freshTarget to get initial target", 1, ts.getCallCount());
+ assertSame("Returned objects should be the same - no refresh should occur", a, b);
+ }
+
+ /**
+ * Test what happens when checking for refresh and refresh occurs.
+ */
+ public void testRefreshCheckWithRefresh() throws Exception {
+ CountingRefreshableTargetSource ts = new CountingRefreshableTargetSource(true);
+ ts.setRefreshCheckDelay(0);
+
+ Object a = ts.getTarget();
+ Thread.sleep(100);
+ Object b = ts.getTarget();
+
+ assertEquals("Should have called freshTarget twice", 2, ts.getCallCount());
+ assertNotSame("Should be different objects", a, b);
+ }
+
+ /**
+ * Test what happens when no refresh occurs.
+ */
+ public void testWithNoRefreshCheck() throws Exception {
+ CountingRefreshableTargetSource ts = new CountingRefreshableTargetSource(true);
+ ts.setRefreshCheckDelay(-1);
+
+ Object a = ts.getTarget();
+ Object b = ts.getTarget();
+
+ assertEquals("Refresh target should only be called once", 1, ts.getCallCount());
+ assertSame("Objects should be the same - refresh check delay not elapsed", a, b);
+ }
+
+ public void testRefreshOverTime() throws Exception {
+ CountingRefreshableTargetSource ts = new CountingRefreshableTargetSource(true);
+ ts.setRefreshCheckDelay(100);
+
+ Object a = ts.getTarget();
+ Object b = ts.getTarget();
+ assertEquals("Objects should be same", a, b);
+
+ Thread.sleep(50);
+
+ Object c = ts.getTarget();
+ assertEquals("A and C should be same", a, c);
+
+ Thread.sleep(60);
+
+ Object d = ts.getTarget();
+ assertNotNull("D should not be null", d);
+ assertFalse("A and D should not be equal", a.equals(d));
+
+ Object e = ts.getTarget();
+ assertEquals("D and E should be equal", d, e);
+
+ Thread.sleep(110);
+
+ Object f = ts.getTarget();
+ assertFalse("E and F should be different", e.equals(f));
+ }
+
+
+ private static class CountingRefreshableTargetSource extends AbstractRefreshableTargetSource {
+
+ private int callCount;
+
+ private boolean requiresRefresh;
+
+ public CountingRefreshableTargetSource() {
+ }
+
+ public CountingRefreshableTargetSource(boolean requiresRefresh) {
+ this.requiresRefresh = requiresRefresh;
+ }
+
+ protected Object freshTarget() {
+ this.callCount++;
+ return new Object();
+ }
+
+ public int getCallCount() {
+ return this.callCount;
+ }
+
+ protected boolean requiresRefresh() {
+ return this.requiresRefresh;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/target/hotSwapTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/hotSwapTests.xml
new file mode 100644
index 00000000000..349193136c6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/hotSwapTests.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+ 10
+
+
+
+ 20
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/target/lazyInitFactoryBean.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/lazyInitFactoryBean.xml
new file mode 100644
index 00000000000..4b408a3410f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/lazyInitFactoryBean.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+ 10
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 20
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/target/lazyInitSingletonTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/lazyInitSingletonTests.xml
new file mode 100644
index 00000000000..0b2d472135a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/lazyInitSingletonTests.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ 10
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/target/prototypeTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/prototypeTests.xml
new file mode 100644
index 00000000000..33a2907aca2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/prototypeTests.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+ 10
+
+
+
+ 10
+
+
+
+ prototypeTest
+
+
+
+
+
+ debugInterceptor,test
+
+
+
+
+
+ debugInterceptor
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/aop/target/threadLocalTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/threadLocalTests.xml
new file mode 100644
index 00000000000..4c5e3ba3130
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/aop/target/threadLocalTests.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+ 10
+
+
+
+ prototypeTest
+
+
+
+
+
+
+
+ getStatsMixin
+
+
+
+
+ debugInterceptor,statsAdvisor
+
+
+ true
+
+
+
+
+
+ Rod
+
+
+
+
+ Kerry
+
+
+
+ test
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/AbstractPropertyValuesTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/AbstractPropertyValuesTests.java
new file mode 100644
index 00000000000..0d0b71e6842
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/AbstractPropertyValuesTests.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rod Johnson
+ */
+public abstract class AbstractPropertyValuesTests extends TestCase {
+
+ /**
+ * Must contain: forname=Tony surname=Blair age=50
+ */
+ protected void doTestTony(PropertyValues pvs) throws Exception {
+ assertTrue("Contains 3", pvs.getPropertyValues().length == 3);
+ assertTrue("Contains forname", pvs.contains("forname"));
+ assertTrue("Contains surname", pvs.contains("surname"));
+ assertTrue("Contains age", pvs.contains("age"));
+ assertTrue("Doesn't contain tory", !pvs.contains("tory"));
+
+ PropertyValue[] ps = pvs.getPropertyValues();
+ Map m = new HashMap();
+ m.put("forname", "Tony");
+ m.put("surname", "Blair");
+ m.put("age", "50");
+ for (int i = 0; i < ps.length; i++) {
+ Object val = m.get(ps[i].getName());
+ assertTrue("Can't have unexpected value", val != null);
+ assertTrue("Val i string", val instanceof String);
+ assertTrue("val matches expected", val.equals(ps[i].getValue()));
+ m.remove(ps[i].getName());
+ }
+ assertTrue("Map size is 0", m.size() == 0);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/BeanUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/BeanUtilsTests.java
new file mode 100644
index 00000000000..29b9a239b3d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/BeanUtilsTests.java
@@ -0,0 +1,309 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.propertyeditors.CustomDateEditor;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceEditor;
+
+/**
+ * @author Juergen Hoeller
+ * @author Rob Harrop
+ * @since 19.05.2003
+ */
+public class BeanUtilsTests extends TestCase {
+
+ public void testInstantiateClass() {
+ // give proper class
+ BeanUtils.instantiateClass(ArrayList.class);
+
+ try {
+ // give interface
+ BeanUtils.instantiateClass(List.class);
+ fail("Should have thrown FatalBeanException");
+ }
+ catch (FatalBeanException ex) {
+ // expected
+ }
+
+ try {
+ // give class without default constructor
+ BeanUtils.instantiateClass(CustomDateEditor.class);
+ fail("Should have thrown FatalBeanException");
+ }
+ catch (FatalBeanException ex) {
+ // expected
+ }
+ }
+
+ public void testGetPropertyDescriptors() throws Exception {
+ PropertyDescriptor[] actual = Introspector.getBeanInfo(TestBean.class).getPropertyDescriptors();
+ PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(TestBean.class);
+ assertNotNull("Descriptors should not be null", descriptors);
+ assertEquals("Invalid number of descriptors returned", actual.length, descriptors.length);
+ }
+
+ public void testBeanPropertyIsArray() {
+ PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(ContainerBean.class);
+ for (int i = 0; i < descriptors.length; i++) {
+ PropertyDescriptor descriptor = descriptors[i];
+ if ("containedBeans".equals(descriptor.getName())) {
+ assertTrue("Property should be an array", descriptor.getPropertyType().isArray());
+ assertEquals(descriptor.getPropertyType().getComponentType(), ContainedBean.class);
+ }
+ }
+ }
+
+ public void testFindEditorByConvention() {
+ assertEquals(ResourceEditor.class, BeanUtils.findEditorByConvention(Resource.class).getClass());
+ }
+
+ public void testCopyProperties() throws Exception {
+ TestBean tb = new TestBean();
+ tb.setName("rod");
+ tb.setAge(32);
+ tb.setTouchy("touchy");
+ TestBean tb2 = new TestBean();
+ assertTrue("Name empty", tb2.getName() == null);
+ assertTrue("Age empty", tb2.getAge() == 0);
+ assertTrue("Touchy empty", tb2.getTouchy() == null);
+ BeanUtils.copyProperties(tb, tb2);
+ assertTrue("Name copied", tb2.getName().equals(tb.getName()));
+ assertTrue("Age copied", tb2.getAge() == tb.getAge());
+ assertTrue("Touchy copied", tb2.getTouchy().equals(tb.getTouchy()));
+ }
+
+ public void testCopyPropertiesWithDifferentTypes1() throws Exception {
+ DerivedTestBean tb = new DerivedTestBean();
+ tb.setName("rod");
+ tb.setAge(32);
+ tb.setTouchy("touchy");
+ TestBean tb2 = new TestBean();
+ assertTrue("Name empty", tb2.getName() == null);
+ assertTrue("Age empty", tb2.getAge() == 0);
+ assertTrue("Touchy empty", tb2.getTouchy() == null);
+ BeanUtils.copyProperties(tb, tb2);
+ assertTrue("Name copied", tb2.getName().equals(tb.getName()));
+ assertTrue("Age copied", tb2.getAge() == tb.getAge());
+ assertTrue("Touchy copied", tb2.getTouchy().equals(tb.getTouchy()));
+ }
+
+ public void testCopyPropertiesWithDifferentTypes2() throws Exception {
+ TestBean tb = new TestBean();
+ tb.setName("rod");
+ tb.setAge(32);
+ tb.setTouchy("touchy");
+ DerivedTestBean tb2 = new DerivedTestBean();
+ assertTrue("Name empty", tb2.getName() == null);
+ assertTrue("Age empty", tb2.getAge() == 0);
+ assertTrue("Touchy empty", tb2.getTouchy() == null);
+ BeanUtils.copyProperties(tb, tb2);
+ assertTrue("Name copied", tb2.getName().equals(tb.getName()));
+ assertTrue("Age copied", tb2.getAge() == tb.getAge());
+ assertTrue("Touchy copied", tb2.getTouchy().equals(tb.getTouchy()));
+ }
+
+ public void testCopyPropertiesWithEditable() throws Exception {
+ TestBean tb = new TestBean();
+ assertTrue("Name empty", tb.getName() == null);
+ tb.setAge(32);
+ tb.setTouchy("bla");
+ TestBean tb2 = new TestBean();
+ tb2.setName("rod");
+ assertTrue("Age empty", tb2.getAge() == 0);
+ assertTrue("Touchy empty", tb2.getTouchy() == null);
+
+ // "touchy" should not be copied: it's not defined in ITestBean
+ BeanUtils.copyProperties(tb, tb2, ITestBean.class);
+ assertTrue("Name copied", tb2.getName() == null);
+ assertTrue("Age copied", tb2.getAge() == 32);
+ assertTrue("Touchy still empty", tb2.getTouchy() == null);
+ }
+
+ public void testCopyPropertiesWithIgnore() throws Exception {
+ TestBean tb = new TestBean();
+ assertTrue("Name empty", tb.getName() == null);
+ tb.setAge(32);
+ tb.setTouchy("bla");
+ TestBean tb2 = new TestBean();
+ tb2.setName("rod");
+ assertTrue("Age empty", tb2.getAge() == 0);
+ assertTrue("Touchy empty", tb2.getTouchy() == null);
+
+ // "spouse", "touchy", "age" should not be copied
+ BeanUtils.copyProperties(tb, tb2, new String[]{"spouse", "touchy", "age"});
+ assertTrue("Name copied", tb2.getName() == null);
+ assertTrue("Age still empty", tb2.getAge() == 0);
+ assertTrue("Touchy still empty", tb2.getTouchy() == null);
+ }
+
+ public void testCopyPropertiesWithIgnoredNonExistingProperty() {
+ NameAndSpecialProperty source = new NameAndSpecialProperty();
+ source.setName("name");
+ TestBean target = new TestBean();
+ BeanUtils.copyProperties(source, target, new String[]{"specialProperty"});
+ assertEquals(target.getName(), "name");
+ }
+
+ public void testResolveSimpleSignature() throws Exception {
+ Method desiredMethod = MethodSignatureBean.class.getMethod("doSomething", null);
+ assertSignatureEquals(desiredMethod, "doSomething");
+ assertSignatureEquals(desiredMethod, "doSomething()");
+ }
+
+ public void testResolveInvalidSignature() throws Exception {
+ try {
+ BeanUtils.resolveSignature("doSomething(", MethodSignatureBean.class);
+ fail("Should not be able to parse with opening but no closing paren.");
+ }
+ catch (IllegalArgumentException ex) {
+ // success
+ }
+
+ try {
+ BeanUtils.resolveSignature("doSomething)", MethodSignatureBean.class);
+ fail("Should not be able to parse with closing but no opening paren.");
+ }
+ catch (IllegalArgumentException ex) {
+ // success
+ }
+ }
+
+ public void testResolveWithAndWithoutArgList() throws Exception {
+ Method desiredMethod = MethodSignatureBean.class.getMethod("doSomethingElse", new Class[]{String.class, int.class});
+ assertSignatureEquals(desiredMethod, "doSomethingElse");
+ assertNull(BeanUtils.resolveSignature("doSomethingElse()", MethodSignatureBean.class));
+ }
+
+ public void testResolveTypedSignature() throws Exception {
+ Method desiredMethod = MethodSignatureBean.class.getMethod("doSomethingElse", new Class[]{String.class, int.class});
+ assertSignatureEquals(desiredMethod, "doSomethingElse(java.lang.String, int)");
+ }
+
+ public void testResolveOverloadedSignature() throws Exception {
+ // test resolve with no args
+ Method desiredMethod = MethodSignatureBean.class.getMethod("overloaded", null);
+ assertSignatureEquals(desiredMethod, "overloaded()");
+
+ // resolve with single arg
+ desiredMethod = MethodSignatureBean.class.getMethod("overloaded", new Class[]{String.class});
+ assertSignatureEquals(desiredMethod, "overloaded(java.lang.String)");
+
+ // resolve with two args
+ desiredMethod = MethodSignatureBean.class.getMethod("overloaded", new Class[]{String.class, BeanFactory.class});
+ assertSignatureEquals(desiredMethod, "overloaded(java.lang.String, org.springframework.beans.factory.BeanFactory)");
+ }
+
+ public void testResolveSignatureWithArray() throws Exception {
+ Method desiredMethod = MethodSignatureBean.class.getMethod("doSomethingWithAnArray", new Class[]{String[].class});
+ assertSignatureEquals(desiredMethod, "doSomethingWithAnArray(java.lang.String[])");
+
+ desiredMethod = MethodSignatureBean.class.getMethod("doSomethingWithAMultiDimensionalArray", new Class[]{String[][].class});
+ assertSignatureEquals(desiredMethod, "doSomethingWithAMultiDimensionalArray(java.lang.String[][])");
+ }
+
+ private void assertSignatureEquals(Method desiredMethod, String signature) {
+ assertEquals(desiredMethod, BeanUtils.resolveSignature(signature, MethodSignatureBean.class));
+ }
+
+
+ private static class NameAndSpecialProperty {
+
+ private String name;
+
+ private int specialProperty;
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setSpecialProperty(int specialProperty) {
+ this.specialProperty = specialProperty;
+ }
+
+ public int getSpecialProperty() {
+ return specialProperty;
+ }
+ }
+
+
+ private static class ContainerBean {
+
+ private ContainedBean[] containedBeans;
+
+ public ContainedBean[] getContainedBeans() {
+ return containedBeans;
+ }
+
+ public void setContainedBeans(ContainedBean[] containedBeans) {
+ this.containedBeans = containedBeans;
+ }
+ }
+
+
+ private static class ContainedBean {
+
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+ }
+
+
+ private static class MethodSignatureBean {
+
+ public void doSomething() {
+ }
+
+ public void doSomethingElse(String s, int x) {
+ }
+
+ public void overloaded() {
+ }
+
+ public void overloaded(String s) {
+ }
+
+ public void overloaded(String s, BeanFactory beanFactory) {
+ }
+
+ public void doSomethingWithAnArray(String[] strings) {
+ }
+
+ public void doSomethingWithAMultiDimensionalArray(String[][] strings) {
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/BeanWithObjectProperty.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/BeanWithObjectProperty.java
new file mode 100644
index 00000000000..18ddbd3b78b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/BeanWithObjectProperty.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+/**
+ * @author Juergen Hoeller
+ * @since 17.08.2004
+ */
+public class BeanWithObjectProperty {
+
+ private Object object;
+
+ public Object getObject() {
+ return object;
+ }
+
+ public void setObject(Object object) {
+ this.object = object;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/BeanWrapperTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/BeanWrapperTests.java
new file mode 100644
index 00000000000..25991f3ed40
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/BeanWrapperTests.java
@@ -0,0 +1,1711 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+import java.beans.PropertyEditorSupport;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import junit.framework.TestCase;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.FlushMode;
+
+import org.springframework.beans.propertyeditors.CustomNumberEditor;
+import org.springframework.beans.propertyeditors.StringArrayPropertyEditor;
+import org.springframework.beans.propertyeditors.StringTrimmerEditor;
+import org.springframework.beans.support.DerivedFromProtectedBaseBean;
+import org.springframework.util.StopWatch;
+import org.springframework.util.StringUtils;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @author Alef Arendsen
+ * @author Arjen Poutsma
+ */
+public class BeanWrapperTests extends TestCase {
+
+ public void testSetWrappedInstanceOfSameClass() throws Exception {
+ TestBean tb = new TestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ assertTrue(bw.isReadableProperty("age"));
+ tb.setAge(11);
+
+ TestBean tb2 = new TestBean();
+ bw.setWrappedInstance(tb2);
+
+ bw.setPropertyValue("age", new Integer(14));
+ assertTrue("2nd changed", tb2.getAge() == 14);
+ assertTrue("1 didn't change", tb.getAge() == 11);
+ }
+
+ public void testIsReadablePropertyNotReadable() {
+ NoRead nr = new NoRead();
+ BeanWrapper bw = new BeanWrapperImpl(nr);
+ assertFalse(bw.isReadableProperty("age"));
+ }
+
+ /**
+ * Shouldn't throw an exception: should just return false
+ */
+ public void testIsReadablePropertyNoSuchProperty() {
+ NoRead nr = new NoRead();
+ BeanWrapper bw = new BeanWrapperImpl(nr);
+ assertFalse(bw.isReadableProperty("xxxxx"));
+ }
+
+ public void testIsReadablePropertyNull() {
+ NoRead nr = new NoRead();
+ BeanWrapper bw = new BeanWrapperImpl(nr);
+ try {
+ bw.isReadableProperty(null);
+ fail("Can't inquire into readability of null property");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ public void testIsWritablePropertyNull() {
+ NoRead nr = new NoRead();
+ BeanWrapper bw = new BeanWrapperImpl(nr);
+ try {
+ bw.isWritableProperty(null);
+ fail("Can't inquire into writability of null property");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ public void testReadableAndWritableForIndexedProperties() {
+ BeanWrapper bw = new BeanWrapperImpl(IndexedTestBean.class);
+
+ assertTrue(bw.isReadableProperty("array"));
+ assertTrue(bw.isReadableProperty("list"));
+ assertTrue(bw.isReadableProperty("set"));
+ assertTrue(bw.isReadableProperty("map"));
+ assertFalse(bw.isReadableProperty("xxx"));
+
+ assertTrue(bw.isWritableProperty("array"));
+ assertTrue(bw.isWritableProperty("list"));
+ assertTrue(bw.isWritableProperty("set"));
+ assertTrue(bw.isWritableProperty("map"));
+ assertFalse(bw.isWritableProperty("xxx"));
+
+ assertTrue(bw.isReadableProperty("array[0]"));
+ assertTrue(bw.isReadableProperty("array[0].name"));
+ assertTrue(bw.isReadableProperty("list[0]"));
+ assertTrue(bw.isReadableProperty("list[0].name"));
+ assertTrue(bw.isReadableProperty("set[0]"));
+ assertTrue(bw.isReadableProperty("set[0].name"));
+ assertTrue(bw.isReadableProperty("map[key1]"));
+ assertTrue(bw.isReadableProperty("map[key1].name"));
+ assertTrue(bw.isReadableProperty("map[key4][0]"));
+ assertTrue(bw.isReadableProperty("map[key4][0].name"));
+ assertTrue(bw.isReadableProperty("map[key4][1]"));
+ assertTrue(bw.isReadableProperty("map[key4][1].name"));
+ assertFalse(bw.isReadableProperty("array[key1]"));
+
+ assertTrue(bw.isWritableProperty("array[0]"));
+ assertTrue(bw.isWritableProperty("array[0].name"));
+ assertTrue(bw.isWritableProperty("list[0]"));
+ assertTrue(bw.isWritableProperty("list[0].name"));
+ assertTrue(bw.isWritableProperty("set[0]"));
+ assertTrue(bw.isWritableProperty("set[0].name"));
+ assertTrue(bw.isWritableProperty("map[key1]"));
+ assertTrue(bw.isWritableProperty("map[key1].name"));
+ assertTrue(bw.isWritableProperty("map[key4][0]"));
+ assertTrue(bw.isWritableProperty("map[key4][0].name"));
+ assertTrue(bw.isWritableProperty("map[key4][1]"));
+ assertTrue(bw.isWritableProperty("map[key4][1].name"));
+ assertFalse(bw.isWritableProperty("array[key1]"));
+ }
+
+ public void testTypeDeterminationForIndexedProperty() {
+ BeanWrapper bw = new BeanWrapperImpl(IndexedTestBean.class);
+ assertEquals(null, bw.getPropertyType("map[key0]"));
+
+ bw = new BeanWrapperImpl(IndexedTestBean.class);
+ bw.setPropertyValue("map[key0]", "my String");
+ assertEquals(String.class, bw.getPropertyType("map[key0]"));
+
+ bw = new BeanWrapperImpl(IndexedTestBean.class);
+ bw.registerCustomEditor(String.class, "map[key0]", new StringTrimmerEditor(false));
+ assertEquals(String.class, bw.getPropertyType("map[key0]"));
+ }
+
+ public void testSetWrappedInstanceOfDifferentClass() {
+ ThrowsException tex = new ThrowsException();
+ BeanWrapper bw = new BeanWrapperImpl(tex);
+
+ TestBean tb2 = new TestBean();
+ bw.setWrappedInstance(tb2);
+
+ bw.setPropertyValue("age", new Integer(14));
+ assertTrue("2nd changed", tb2.getAge() == 14);
+ }
+
+ public void testGetterThrowsException() {
+ GetterBean gb = new GetterBean();
+ BeanWrapper bw = new BeanWrapperImpl(gb);
+ bw.setPropertyValue("name", "tom");
+ assertTrue("Set name to tom", gb.getName().equals("tom"));
+ }
+
+ public void testEmptyPropertyValuesSet() {
+ TestBean t = new TestBean();
+ int age = 50;
+ String name = "Tony";
+ t.setAge(age);
+ t.setName(name);
+ try {
+ BeanWrapper bw = new BeanWrapperImpl(t);
+ assertTrue("age is OK", t.getAge() == age);
+ assertTrue("name is OK", name.equals(t.getName()));
+ bw.setPropertyValues(new MutablePropertyValues());
+ // Check its unchanged
+ assertTrue("age is OK", t.getAge() == age);
+ assertTrue("name is OK", name.equals(t.getName()));
+ }
+ catch (BeansException ex) {
+ fail("Shouldn't throw exception when everything is valid");
+ }
+ }
+
+ public void testAllValid() {
+ TestBean t = new TestBean();
+ String newName = "tony";
+ int newAge = 65;
+ String newTouchy = "valid";
+ try {
+ BeanWrapper bw = new BeanWrapperImpl(t);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue(new PropertyValue("age", new Integer(newAge)));
+ pvs.addPropertyValue(new PropertyValue("name", newName));
+
+ pvs.addPropertyValue(new PropertyValue("touchy", newTouchy));
+ bw.setPropertyValues(pvs);
+ assertTrue("Validly set property must stick", t.getName().equals(newName));
+ assertTrue("Validly set property must stick", t.getTouchy().equals(newTouchy));
+ assertTrue("Validly set property must stick", t.getAge() == newAge);
+ }
+ catch (BeansException ex) {
+ fail("Shouldn't throw exception when everything is valid");
+ }
+ }
+
+ public void testBeanWrapperUpdates() {
+ TestBean t = new TestBean();
+ int newAge = 33;
+ try {
+ BeanWrapper bw = new BeanWrapperImpl(t);
+ t.setAge(newAge);
+ Object bwAge = bw.getPropertyValue("age");
+ assertTrue("Age is an integer", bwAge instanceof Integer);
+ int bwi = ((Integer) bwAge).intValue();
+ assertTrue("Bean wrapper must pick up changes", bwi == newAge);
+ }
+ catch (Exception ex) {
+ fail("Shouldn't throw exception when everything is valid");
+ }
+ }
+
+ public void testValidNullUpdate() {
+ TestBean t = new TestBean();
+ t.setName("Frank"); // we need to change it back
+ t.setSpouse(t);
+ BeanWrapper bw = new BeanWrapperImpl(t);
+ assertTrue("name is not null to start off", t.getName() != null);
+ bw.setPropertyValue("name", null);
+ assertTrue("name is now null", t.getName() == null);
+ // now test with non-string
+ assertTrue("spouse is not null to start off", t.getSpouse() != null);
+ bw.setPropertyValue("spouse", null);
+ assertTrue("spouse is now null", t.getSpouse() == null);
+ }
+
+ public void testIgnoringIndexedProperty() {
+ MutablePropertyValues values = new MutablePropertyValues();
+ values.addPropertyValue("toBeIgnored[0]", new Integer(42));
+ BeanWrapper bw = new BeanWrapperImpl(new Object());
+ bw.setPropertyValues(values, true);
+ }
+
+ public void testConvertPrimitiveToString() {
+ MutablePropertyValues values = new MutablePropertyValues();
+ values.addPropertyValue("name", new Integer(42));
+ TestBean tb = new TestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ bw.setPropertyValues(values);
+ assertEquals("42", tb.getName());
+ }
+
+ public void testConvertClassToString() {
+ MutablePropertyValues values = new MutablePropertyValues();
+ values.addPropertyValue("name", Integer.class);
+ TestBean tb = new TestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ bw.registerCustomEditor(String.class, new PropertyEditorSupport() {
+ public void setValue(Object value) {
+ super.setValue(value.toString());
+ }
+ });
+ bw.setPropertyValues(values);
+ assertEquals(Integer.class.toString(), tb.getName());
+ }
+
+ public void testBooleanObject() {
+ BooleanTestBean tb = new BooleanTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+
+ bw.setPropertyValue("bool2", "true");
+ assertTrue("Correct bool2 value", Boolean.TRUE.equals(bw.getPropertyValue("bool2")));
+ assertTrue("Correct bool2 value", tb.getBool2().booleanValue());
+
+ bw.setPropertyValue("bool2", "false");
+ assertTrue("Correct bool2 value", Boolean.FALSE.equals(bw.getPropertyValue("bool2")));
+ assertTrue("Correct bool2 value", !tb.getBool2().booleanValue());
+
+ }
+
+ public void testNumberObjects() {
+ NumberTestBean tb = new NumberTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+
+ try {
+ bw.setPropertyValue("short2", "2");
+ bw.setPropertyValue("int2", "8");
+ bw.setPropertyValue("long2", "6");
+ bw.setPropertyValue("bigInteger", "3");
+ bw.setPropertyValue("float2", "8.1");
+ bw.setPropertyValue("double2", "6.1");
+ bw.setPropertyValue("bigDecimal", "4.0");
+ }
+ catch (BeansException ex) {
+ fail("Should not throw BeansException: " + ex.getMessage());
+ }
+
+ assertTrue("Correct short2 value", new Short("2").equals(bw.getPropertyValue("short2")));
+ assertTrue("Correct short2 value", new Short("2").equals(tb.getShort2()));
+ assertTrue("Correct int2 value", new Integer("8").equals(bw.getPropertyValue("int2")));
+ assertTrue("Correct int2 value", new Integer("8").equals(tb.getInt2()));
+ assertTrue("Correct long2 value", new Long("6").equals(bw.getPropertyValue("long2")));
+ assertTrue("Correct long2 value", new Long("6").equals(tb.getLong2()));
+ assertTrue("Correct bigInteger value", new BigInteger("3").equals(bw.getPropertyValue("bigInteger")));
+ assertTrue("Correct bigInteger value", new BigInteger("3").equals(tb.getBigInteger()));
+ assertTrue("Correct float2 value", new Float("8.1").equals(bw.getPropertyValue("float2")));
+ assertTrue("Correct float2 value", new Float("8.1").equals(tb.getFloat2()));
+ assertTrue("Correct double2 value", new Double("6.1").equals(bw.getPropertyValue("double2")));
+ assertTrue("Correct double2 value", new Double("6.1").equals(tb.getDouble2()));
+ assertTrue("Correct bigDecimal value", new BigDecimal("4.0").equals(bw.getPropertyValue("bigDecimal")));
+ assertTrue("Correct bigDecimal value", new BigDecimal("4.0").equals(tb.getBigDecimal()));
+ }
+
+ public void testNumberCoercion() {
+ NumberTestBean tb = new NumberTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+
+ try {
+ bw.setPropertyValue("short2", new Integer(2));
+ bw.setPropertyValue("int2", new Long(8));
+ bw.setPropertyValue("long2", new BigInteger("6"));
+ bw.setPropertyValue("bigInteger", new Integer(3));
+ bw.setPropertyValue("float2", new Double(8.1));
+ bw.setPropertyValue("double2", new BigDecimal(6.1));
+ bw.setPropertyValue("bigDecimal", new Float(4.0));
+ }
+ catch (BeansException ex) {
+ fail("Should not throw BeansException: " + ex.getMessage());
+ }
+
+ assertTrue("Correct short2 value", new Short("2").equals(bw.getPropertyValue("short2")));
+ assertTrue("Correct short2 value", new Short("2").equals(tb.getShort2()));
+ assertTrue("Correct int2 value", new Integer("8").equals(bw.getPropertyValue("int2")));
+ assertTrue("Correct int2 value", new Integer("8").equals(tb.getInt2()));
+ assertTrue("Correct long2 value", new Long("6").equals(bw.getPropertyValue("long2")));
+ assertTrue("Correct long2 value", new Long("6").equals(tb.getLong2()));
+ assertTrue("Correct bigInteger value", new BigInteger("3").equals(bw.getPropertyValue("bigInteger")));
+ assertTrue("Correct bigInteger value", new BigInteger("3").equals(tb.getBigInteger()));
+ assertTrue("Correct float2 value", new Float("8.1").equals(bw.getPropertyValue("float2")));
+ assertTrue("Correct float2 value", new Float("8.1").equals(tb.getFloat2()));
+ assertTrue("Correct double2 value", new Double("6.1").equals(bw.getPropertyValue("double2")));
+ assertTrue("Correct double2 value", new Double("6.1").equals(tb.getDouble2()));
+ assertTrue("Correct bigDecimal value", new BigDecimal("4.0").equals(bw.getPropertyValue("bigDecimal")));
+ assertTrue("Correct bigDecimal value", new BigDecimal("4.0").equals(tb.getBigDecimal()));
+ }
+
+ public void testEnumByFieldName() {
+ EnumTester et = new EnumTester();
+ BeanWrapper bw = new BeanWrapperImpl(et);
+
+ bw.setPropertyValue("flushMode", "NEVER");
+ assertEquals(FlushMode.NEVER, et.getFlushMode());
+
+ bw.setPropertyValue("flushMode", " AUTO ");
+ assertEquals(FlushMode.AUTO, et.getFlushMode());
+
+ try {
+ bw.setPropertyValue("flushMode", "EVER");
+ fail("Should have thrown TypeMismatchException");
+ }
+ catch (TypeMismatchException ex) {
+ // expected
+ }
+ }
+
+ public void testPropertiesProperty() throws Exception {
+ PropsTester pt = new PropsTester();
+ BeanWrapper bw = new BeanWrapperImpl(pt);
+ bw.setPropertyValue("name", "ptest");
+
+ // Note format...
+ String ps = "peace=war\nfreedom=slavery";
+ bw.setPropertyValue("properties", ps);
+
+ assertTrue("name was set", pt.name.equals("ptest"));
+ assertTrue("props non null", pt.props != null);
+ String freedomVal = pt.props.getProperty("freedom");
+ String peaceVal = pt.props.getProperty("peace");
+ assertTrue("peace==war", peaceVal.equals("war"));
+ assertTrue("Freedom==slavery", freedomVal.equals("slavery"));
+ }
+
+ public void testStringArrayProperty() throws Exception {
+ PropsTester pt = new PropsTester();
+ BeanWrapper bw = new BeanWrapperImpl(pt);
+
+ bw.setPropertyValue("stringArray", new String[] {"foo", "fi", "fi", "fum"});
+ assertTrue("stringArray length = 4", pt.stringArray.length == 4);
+ assertTrue("correct values", pt.stringArray[0].equals("foo") && pt.stringArray[1].equals("fi") &&
+ pt.stringArray[2].equals("fi") && pt.stringArray[3].equals("fum"));
+
+ List list = new ArrayList();
+ list.add("foo");
+ list.add("fi");
+ list.add("fi");
+ list.add("fum");
+ bw.setPropertyValue("stringArray", list);
+ assertTrue("stringArray length = 4", pt.stringArray.length == 4);
+ assertTrue("correct values", pt.stringArray[0].equals("foo") && pt.stringArray[1].equals("fi") &&
+ pt.stringArray[2].equals("fi") && pt.stringArray[3].equals("fum"));
+
+ Set set = new HashSet();
+ set.add("foo");
+ set.add("fi");
+ set.add("fum");
+ bw.setPropertyValue("stringArray", set);
+ assertTrue("stringArray length = 3", pt.stringArray.length == 3);
+ List result = Arrays.asList(pt.stringArray);
+ assertTrue("correct values", result.contains("foo") && result.contains("fi") && result.contains("fum"));
+
+ bw.setPropertyValue("stringArray", "one");
+ assertTrue("stringArray length = 1", pt.stringArray.length == 1);
+ assertTrue("stringArray elt is ok", pt.stringArray[0].equals("one"));
+
+ bw.setPropertyValue("stringArray", null);
+ assertTrue("stringArray is null", pt.stringArray == null);
+ }
+
+ public void testStringArrayPropertyWithCustomStringEditor() throws Exception {
+ PropsTester pt = new PropsTester();
+ BeanWrapper bw = new BeanWrapperImpl(pt);
+ bw.registerCustomEditor(String.class, "stringArray", new PropertyEditorSupport() {
+ public void setAsText(String text) {
+ setValue(text.substring(1));
+ }
+ });
+
+ bw.setPropertyValue("stringArray", new String[] {"4foo", "7fi", "6fi", "5fum"});
+ assertTrue("stringArray length = 4", pt.stringArray.length == 4);
+ assertTrue("correct values", pt.stringArray[0].equals("foo") && pt.stringArray[1].equals("fi") &&
+ pt.stringArray[2].equals("fi") && pt.stringArray[3].equals("fum"));
+
+ List list = new ArrayList();
+ list.add("4foo");
+ list.add("7fi");
+ list.add("6fi");
+ list.add("5fum");
+ bw.setPropertyValue("stringArray", list);
+ assertTrue("stringArray length = 4", pt.stringArray.length == 4);
+ assertTrue("correct values", pt.stringArray[0].equals("foo") && pt.stringArray[1].equals("fi") &&
+ pt.stringArray[2].equals("fi") && pt.stringArray[3].equals("fum"));
+
+ Set set = new HashSet();
+ set.add("4foo");
+ set.add("7fi");
+ set.add("6fum");
+ bw.setPropertyValue("stringArray", set);
+ assertTrue("stringArray length = 3", pt.stringArray.length == 3);
+ List result = Arrays.asList(pt.stringArray);
+ assertTrue("correct values", result.contains("foo") && result.contains("fi") && result.contains("fum"));
+
+ bw.setPropertyValue("stringArray", "8one");
+ assertTrue("stringArray length = 1", pt.stringArray.length == 1);
+ assertTrue("correct values", pt.stringArray[0].equals("one"));
+ }
+
+ public void testStringArrayPropertyWithStringSplitting() throws Exception {
+ PropsTester pt = new PropsTester();
+ BeanWrapperImpl bw = new BeanWrapperImpl(pt);
+ bw.useConfigValueEditors();
+ bw.setPropertyValue("stringArray", "a1,b2");
+ assertTrue("stringArray length = 2", pt.stringArray.length == 2);
+ assertTrue("correct values", pt.stringArray[0].equals("a1") && pt.stringArray[1].equals("b2"));
+ }
+
+ public void testStringArrayPropertyWithCustomStringDelimiter() throws Exception {
+ PropsTester pt = new PropsTester();
+ BeanWrapper bw = new BeanWrapperImpl(pt);
+ bw.registerCustomEditor(String[].class, "stringArray", new StringArrayPropertyEditor("-"));
+ bw.setPropertyValue("stringArray", "a1-b2");
+ assertTrue("stringArray length = 2", pt.stringArray.length == 2);
+ assertTrue("correct values", pt.stringArray[0].equals("a1") && pt.stringArray[1].equals("b2"));
+ }
+
+ public void testStringPropertyWithCustomEditor() throws Exception {
+ TestBean tb = new TestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ bw.registerCustomEditor(String.class, "name", new PropertyEditorSupport() {
+ public void setValue(Object value) {
+ if (value instanceof String[]) {
+ setValue(StringUtils.arrayToDelimitedString(((String[]) value), "-"));
+ }
+ else {
+ super.setValue(value != null ? value : "");
+ }
+ }
+ });
+ bw.setPropertyValue("name", new String[] {});
+ assertEquals("", tb.getName());
+ bw.setPropertyValue("name", new String[] {"a1", "b2"});
+ assertEquals("a1-b2", tb.getName());
+ bw.setPropertyValue("name", null);
+ assertEquals("", tb.getName());
+ }
+
+ public void testIntArrayProperty() {
+ PropsTester pt = new PropsTester();
+ BeanWrapper bw = new BeanWrapperImpl(pt);
+
+ bw.setPropertyValue("intArray", new int[] {4, 5, 2, 3});
+ assertTrue("intArray length = 4", pt.intArray.length == 4);
+ assertTrue("correct values", pt.intArray[0] == 4 && pt.intArray[1] == 5 &&
+ pt.intArray[2] == 2 && pt.intArray[3] == 3);
+
+ bw.setPropertyValue("intArray", new String[] {"4", "5", "2", "3"});
+ assertTrue("intArray length = 4", pt.intArray.length == 4);
+ assertTrue("correct values", pt.intArray[0] == 4 && pt.intArray[1] == 5 &&
+ pt.intArray[2] == 2 && pt.intArray[3] == 3);
+
+ List list = new ArrayList();
+ list.add(new Integer(4));
+ list.add("5");
+ list.add(new Integer(2));
+ list.add("3");
+ bw.setPropertyValue("intArray", list);
+ assertTrue("intArray length = 4", pt.intArray.length == 4);
+ assertTrue("correct values", pt.intArray[0] == 4 && pt.intArray[1] == 5 &&
+ pt.intArray[2] == 2 && pt.intArray[3] == 3);
+
+ Set set = new HashSet();
+ set.add("4");
+ set.add(new Integer(5));
+ set.add("3");
+ bw.setPropertyValue("intArray", set);
+ assertTrue("intArray length = 3", pt.intArray.length == 3);
+ List result = new ArrayList();
+ result.add(new Integer(pt.intArray[0]));
+ result.add(new Integer(pt.intArray[1]));
+ result.add(new Integer(pt.intArray[2]));
+ assertTrue("correct values", result.contains(new Integer(4)) && result.contains(new Integer(5)) &&
+ result.contains(new Integer(3)));
+
+ bw.setPropertyValue("intArray", new Integer[] {new Integer(1)});
+ assertTrue("intArray length = 4", pt.intArray.length == 1);
+ assertTrue("correct values", pt.intArray[0] == 1);
+
+ bw.setPropertyValue("intArray", new Integer(1));
+ assertTrue("intArray length = 4", pt.intArray.length == 1);
+ assertTrue("correct values", pt.intArray[0] == 1);
+
+ bw.setPropertyValue("intArray", new String[] {"1"});
+ assertTrue("intArray length = 4", pt.intArray.length == 1);
+ assertTrue("correct values", pt.intArray[0] == 1);
+
+ bw.setPropertyValue("intArray", "1");
+ assertTrue("intArray length = 4", pt.intArray.length == 1);
+ assertTrue("correct values", pt.intArray[0] == 1);
+ }
+
+ public void testIntArrayPropertyWithCustomEditor() {
+ PropsTester pt = new PropsTester();
+ BeanWrapper bw = new BeanWrapperImpl(pt);
+ bw.registerCustomEditor(int.class, new PropertyEditorSupport() {
+ public void setAsText(String text) {
+ setValue(new Integer(Integer.parseInt(text) + 1));
+ }
+ });
+
+ bw.setPropertyValue("intArray", new int[] {4, 5, 2, 3});
+ assertTrue("intArray length = 4", pt.intArray.length == 4);
+ assertTrue("correct values", pt.intArray[0] == 4 && pt.intArray[1] == 5 &&
+ pt.intArray[2] == 2 && pt.intArray[3] == 3);
+
+ bw.setPropertyValue("intArray", new String[] {"3", "4", "1", "2"});
+ assertTrue("intArray length = 4", pt.intArray.length == 4);
+ assertTrue("correct values", pt.intArray[0] == 4 && pt.intArray[1] == 5 &&
+ pt.intArray[2] == 2 && pt.intArray[3] == 3);
+
+ bw.setPropertyValue("intArray", new Integer(1));
+ assertTrue("intArray length = 4", pt.intArray.length == 1);
+ assertTrue("correct values", pt.intArray[0] == 1);
+
+ bw.setPropertyValue("intArray", new String[] {"0"});
+ assertTrue("intArray length = 4", pt.intArray.length == 1);
+ assertTrue("correct values", pt.intArray[0] == 1);
+
+ bw.setPropertyValue("intArray", "0");
+ assertTrue("intArray length = 4", pt.intArray.length == 1);
+ assertTrue("correct values", pt.intArray[0] == 1);
+ }
+
+ public void testIntArrayPropertyWithStringSplitting() throws Exception {
+ PropsTester pt = new PropsTester();
+ BeanWrapperImpl bw = new BeanWrapperImpl(pt);
+ bw.useConfigValueEditors();
+ bw.setPropertyValue("intArray", "4,5");
+ assertTrue("intArray length = 2", pt.intArray.length == 2);
+ assertTrue("correct values", pt.intArray[0] == 4 && pt.intArray[1] == 5);
+ }
+
+ public void testIndividualAllValid() {
+ TestBean t = new TestBean();
+ String newName = "tony";
+ int newAge = 65;
+ String newTouchy = "valid";
+ try {
+ BeanWrapper bw = new BeanWrapperImpl(t);
+ bw.setPropertyValue("age", new Integer(newAge));
+ bw.setPropertyValue(new PropertyValue("name", newName));
+ bw.setPropertyValue(new PropertyValue("touchy", newTouchy));
+ assertTrue("Validly set property must stick", t.getName().equals(newName));
+ assertTrue("Validly set property must stick", t.getTouchy().equals(newTouchy));
+ assertTrue("Validly set property must stick", t.getAge() == newAge);
+ }
+ catch (BeansException ex) {
+ fail("Shouldn't throw exception when everything is valid");
+ }
+ }
+
+ public void test2Invalid() {
+ TestBean t = new TestBean();
+ String newName = "tony";
+ String invalidTouchy = ".valid";
+ try {
+ BeanWrapper bw = new BeanWrapperImpl(t);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue(new PropertyValue("age", "foobar"));
+ pvs.addPropertyValue(new PropertyValue("name", newName));
+ pvs.addPropertyValue(new PropertyValue("touchy", invalidTouchy));
+ bw.setPropertyValues(pvs);
+ fail("Should throw exception when everything is valid");
+ }
+ catch (PropertyBatchUpdateException ex) {
+ assertTrue("Must contain 2 exceptions", ex.getExceptionCount() == 2);
+ // Test validly set property matches
+ assertTrue("Validly set property must stick", t.getName().equals(newName));
+ assertTrue("Invalidly set property must retain old value", t.getAge() == 0);
+ assertTrue("New value of dodgy setter must be available through exception",
+ ex.getPropertyAccessException("touchy").getPropertyChangeEvent().getNewValue().equals(invalidTouchy));
+ }
+ }
+
+ public void testPossibleMatches() {
+ TestBean tb = new TestBean();
+ try {
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ bw.setPropertyValue("ag", "foobar");
+ fail("Should throw exception on invalid property");
+ }
+ catch (NotWritablePropertyException ex) {
+ // expected
+ assertEquals(1, ex.getPossibleMatches().length);
+ assertEquals("age", ex.getPossibleMatches()[0]);
+ }
+ }
+
+ public void testTypeMismatch() {
+ TestBean t = new TestBean();
+ try {
+ BeanWrapper bw = new BeanWrapperImpl(t);
+ bw.setPropertyValue("age", "foobar");
+ fail("Should throw exception on type mismatch");
+ }
+ catch (TypeMismatchException ex) {
+ // expected
+ }
+ }
+
+ public void testEmptyValueForPrimitiveProperty() {
+ TestBean t = new TestBean();
+ try {
+ BeanWrapper bw = new BeanWrapperImpl(t);
+ bw.setPropertyValue("age", "");
+ fail("Should throw exception on type mismatch");
+ }
+ catch (TypeMismatchException ex) {
+ // expected
+ }
+ catch (Exception ex) {
+ fail("Shouldn't throw exception other than Type mismatch");
+ }
+ }
+
+ public void testSetPropertyValuesIgnoresInvalidNestedOnRequest() {
+ ITestBean rod = new TestBean();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue(new PropertyValue("name", "rod"));
+ pvs.addPropertyValue(new PropertyValue("graceful.rubbish", "tony"));
+ pvs.addPropertyValue(new PropertyValue("more.garbage", new Object()));
+ BeanWrapper bw = new BeanWrapperImpl(rod);
+ bw.setPropertyValues(pvs, true);
+ assertTrue("Set valid and ignored invalid", rod.getName().equals("rod"));
+ try {
+ // Don't ignore: should fail
+ bw.setPropertyValues(pvs, false);
+ fail("Shouldn't have ignored invalid updates");
+ }
+ catch (NotWritablePropertyException ex) {
+ // OK: but which exception??
+ }
+ }
+
+ public void testGetNestedProperty() {
+ ITestBean rod = new TestBean("rod", 31);
+ ITestBean kerry = new TestBean("kerry", 35);
+ rod.setSpouse(kerry);
+ kerry.setSpouse(rod);
+ BeanWrapper bw = new BeanWrapperImpl(rod);
+ Integer KA = (Integer) bw.getPropertyValue("spouse.age");
+ assertTrue("kerry is 35", KA.intValue() == 35);
+ Integer RA = (Integer) bw.getPropertyValue("spouse.spouse.age");
+ assertTrue("rod is 31, not" + RA, RA.intValue() == 31);
+ ITestBean spousesSpouse = (ITestBean) bw.getPropertyValue("spouse.spouse");
+ assertTrue("spousesSpouse = initial point", rod == spousesSpouse);
+ }
+
+ public void testGetNestedPropertyNullValue() throws Exception {
+ ITestBean rod = new TestBean("rod", 31);
+ ITestBean kerry = new TestBean("kerry", 35);
+ rod.setSpouse(kerry);
+
+ BeanWrapper bw = new BeanWrapperImpl(rod);
+ try {
+ bw.getPropertyValue("spouse.spouse.age");
+ fail("Shouldn't have succeded with null path");
+ }
+ catch (NullValueInNestedPathException ex) {
+ // ok
+ assertTrue("it was the spouse.spouse property that was null, not " + ex.getPropertyName(),
+ ex.getPropertyName().equals("spouse.spouse"));
+ }
+ }
+
+ public void testSetNestedProperty() throws Exception {
+ ITestBean rod = new TestBean("rod", 31);
+ ITestBean kerry = new TestBean("kerry", 0);
+
+ BeanWrapper bw = new BeanWrapperImpl(rod);
+ bw.setPropertyValue("spouse", kerry);
+
+ assertTrue("nested set worked", rod.getSpouse() == kerry);
+ assertTrue("no back relation", kerry.getSpouse() == null);
+ bw.setPropertyValue(new PropertyValue("spouse.spouse", rod));
+ assertTrue("nested set worked", kerry.getSpouse() == rod);
+ assertTrue("kerry age not set", kerry.getAge() == 0);
+ bw.setPropertyValue(new PropertyValue("spouse.age", new Integer(35)));
+ assertTrue("Set primitive on spouse", kerry.getAge() == 35);
+
+ assertEquals(kerry, bw.getPropertyValue("spouse"));
+ assertEquals(rod, bw.getPropertyValue("spouse.spouse"));
+ }
+
+ public void testSetNestedPropertyNullValue() throws Exception {
+ ITestBean rod = new TestBean("rod", 31);
+ BeanWrapper bw = new BeanWrapperImpl(rod);
+ try {
+ bw.setPropertyValue("spouse.age", new Integer(31));
+ fail("Shouldn't have succeeded with null path");
+ }
+ catch (NullValueInNestedPathException ex) {
+ // expected
+ assertTrue("it was the spouse property that was null, not " + ex.getPropertyName(),
+ ex.getPropertyName().equals("spouse"));
+ }
+ }
+
+ public void testSetNestedPropertyPolymorphic() throws Exception {
+ ITestBean rod = new TestBean("rod", 31);
+ ITestBean kerry = new Employee();
+
+ BeanWrapper bw = new BeanWrapperImpl(rod);
+ bw.setPropertyValue("spouse", kerry);
+ bw.setPropertyValue("spouse.age", new Integer(35));
+ bw.setPropertyValue("spouse.name", "Kerry");
+ bw.setPropertyValue("spouse.company", "Lewisham");
+ assertTrue("kerry name is Kerry", kerry.getName().equals("Kerry"));
+
+ assertTrue("nested set worked", rod.getSpouse() == kerry);
+ assertTrue("no back relation", kerry.getSpouse() == null);
+ bw.setPropertyValue(new PropertyValue("spouse.spouse", rod));
+ assertTrue("nested set worked", kerry.getSpouse() == rod);
+
+ BeanWrapper kbw = new BeanWrapperImpl(kerry);
+ assertTrue("spouse.spouse.spouse.spouse.company=Lewisham",
+ "Lewisham".equals(kbw.getPropertyValue("spouse.spouse.spouse.spouse.company")));
+ }
+
+ public void testNewWrappedInstancePropertyValuesGet() {
+ BeanWrapper bw = new BeanWrapperImpl();
+
+ TestBean t = new TestBean("Tony", 50);
+ bw.setWrappedInstance(t);
+ assertEquals("Bean wrapper returns wrong property value",
+ new Integer(t.getAge()), bw.getPropertyValue("age"));
+
+ TestBean u = new TestBean("Udo", 30);
+ bw.setWrappedInstance(u);
+ assertEquals("Bean wrapper returns cached property value",
+ new Integer(u.getAge()), bw.getPropertyValue("age"));
+ }
+
+ public void testNewWrappedInstanceNestedPropertyValuesGet() {
+ BeanWrapper bw = new BeanWrapperImpl();
+
+ TestBean t = new TestBean("Tony", 50);
+ t.setSpouse(new TestBean("Sue", 40));
+ bw.setWrappedInstance(t);
+ assertEquals("Bean wrapper returns wrong nested property value",
+ new Integer(t.getSpouse().getAge()), bw.getPropertyValue("spouse.age"));
+
+ TestBean u = new TestBean("Udo", 30);
+ u.setSpouse(new TestBean("Vera", 20));
+ bw.setWrappedInstance(u);
+ assertEquals("Bean wrapper returns cached nested property value",
+ new Integer(u.getSpouse().getAge()), bw.getPropertyValue("spouse.age"));
+ }
+
+ public void testNullObject() {
+ try {
+ new BeanWrapperImpl((Object) null);
+ fail("Must throw an exception when constructed with null object");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ public void testNestedProperties() {
+ String doctorCompany = "";
+ String lawyerCompany = "Dr. Sueem";
+ TestBean tb = new TestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ bw.setPropertyValue("doctor.company", doctorCompany);
+ bw.setPropertyValue("lawyer.company", lawyerCompany);
+ assertEquals(doctorCompany, tb.getDoctor().getCompany());
+ assertEquals(lawyerCompany, tb.getLawyer().getCompany());
+ }
+
+ public void testIndexedProperties() {
+ IndexedTestBean bean = new IndexedTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(bean);
+ TestBean tb0 = bean.getArray()[0];
+ TestBean tb1 = bean.getArray()[1];
+ TestBean tb2 = ((TestBean) bean.getList().get(0));
+ TestBean tb3 = ((TestBean) bean.getList().get(1));
+ TestBean tb6 = ((TestBean) bean.getSet().toArray()[0]);
+ TestBean tb7 = ((TestBean) bean.getSet().toArray()[1]);
+ TestBean tb4 = ((TestBean) bean.getMap().get("key1"));
+ TestBean tb5 = ((TestBean) bean.getMap().get("key.3"));
+ assertEquals("name0", tb0.getName());
+ assertEquals("name1", tb1.getName());
+ assertEquals("name2", tb2.getName());
+ assertEquals("name3", tb3.getName());
+ assertEquals("name6", tb6.getName());
+ assertEquals("name7", tb7.getName());
+ assertEquals("name4", tb4.getName());
+ assertEquals("name5", tb5.getName());
+ assertEquals("name0", bw.getPropertyValue("array[0].name"));
+ assertEquals("name1", bw.getPropertyValue("array[1].name"));
+ assertEquals("name2", bw.getPropertyValue("list[0].name"));
+ assertEquals("name3", bw.getPropertyValue("list[1].name"));
+ assertEquals("name6", bw.getPropertyValue("set[0].name"));
+ assertEquals("name7", bw.getPropertyValue("set[1].name"));
+ assertEquals("name4", bw.getPropertyValue("map[key1].name"));
+ assertEquals("name5", bw.getPropertyValue("map[key.3].name"));
+ assertEquals("name4", bw.getPropertyValue("map['key1'].name"));
+ assertEquals("name5", bw.getPropertyValue("map[\"key.3\"].name"));
+ assertEquals("nameX", bw.getPropertyValue("map[key4][0].name"));
+ assertEquals("nameY", bw.getPropertyValue("map[key4][1].name"));
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("array[0].name", "name5");
+ pvs.addPropertyValue("array[1].name", "name4");
+ pvs.addPropertyValue("list[0].name", "name3");
+ pvs.addPropertyValue("list[1].name", "name2");
+ pvs.addPropertyValue("set[0].name", "name8");
+ pvs.addPropertyValue("set[1].name", "name9");
+ pvs.addPropertyValue("map[key1].name", "name1");
+ pvs.addPropertyValue("map['key.3'].name", "name0");
+ pvs.addPropertyValue("map[key4][0].name", "nameA");
+ pvs.addPropertyValue("map[key4][1].name", "nameB");
+ bw.setPropertyValues(pvs);
+ assertEquals("name5", tb0.getName());
+ assertEquals("name4", tb1.getName());
+ assertEquals("name3", tb2.getName());
+ assertEquals("name2", tb3.getName());
+ assertEquals("name1", tb4.getName());
+ assertEquals("name0", tb5.getName());
+ assertEquals("name5", bw.getPropertyValue("array[0].name"));
+ assertEquals("name4", bw.getPropertyValue("array[1].name"));
+ assertEquals("name3", bw.getPropertyValue("list[0].name"));
+ assertEquals("name2", bw.getPropertyValue("list[1].name"));
+ assertEquals("name8", bw.getPropertyValue("set[0].name"));
+ assertEquals("name9", bw.getPropertyValue("set[1].name"));
+ assertEquals("name1", bw.getPropertyValue("map[\"key1\"].name"));
+ assertEquals("name0", bw.getPropertyValue("map['key.3'].name"));
+ assertEquals("nameA", bw.getPropertyValue("map[key4][0].name"));
+ assertEquals("nameB", bw.getPropertyValue("map[key4][1].name"));
+ }
+
+ public void testIndexedPropertiesWithDirectAccess() {
+ IndexedTestBean bean = new IndexedTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(bean);
+ TestBean tb0 = bean.getArray()[0];
+ TestBean tb1 = bean.getArray()[1];
+ TestBean tb2 = ((TestBean) bean.getList().get(0));
+ TestBean tb3 = ((TestBean) bean.getList().get(1));
+ TestBean tb6 = ((TestBean) bean.getSet().toArray()[0]);
+ TestBean tb7 = ((TestBean) bean.getSet().toArray()[1]);
+ TestBean tb4 = ((TestBean) bean.getMap().get("key1"));
+ TestBean tb5 = ((TestBean) bean.getMap().get("key2"));
+ assertEquals(tb0, bw.getPropertyValue("array[0]"));
+ assertEquals(tb1, bw.getPropertyValue("array[1]"));
+ assertEquals(tb2, bw.getPropertyValue("list[0]"));
+ assertEquals(tb3, bw.getPropertyValue("list[1]"));
+ assertEquals(tb6, bw.getPropertyValue("set[0]"));
+ assertEquals(tb7, bw.getPropertyValue("set[1]"));
+ assertEquals(tb4, bw.getPropertyValue("map[key1]"));
+ assertEquals(tb5, bw.getPropertyValue("map[key2]"));
+ assertEquals(tb4, bw.getPropertyValue("map['key1']"));
+ assertEquals(tb5, bw.getPropertyValue("map[\"key2\"]"));
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("array[0]", tb5);
+ pvs.addPropertyValue("array[1]", tb4);
+ pvs.addPropertyValue("list[0]", tb3);
+ pvs.addPropertyValue("list[1]", tb2);
+ pvs.addPropertyValue("list[2]", tb0);
+ pvs.addPropertyValue("list[4]", tb1);
+ pvs.addPropertyValue("map[key1]", tb1);
+ pvs.addPropertyValue("map['key2']", tb0);
+ pvs.addPropertyValue("map[key5]", tb4);
+ pvs.addPropertyValue("map['key9']", tb5);
+ bw.setPropertyValues(pvs);
+ assertEquals(tb5, bean.getArray()[0]);
+ assertEquals(tb4, bean.getArray()[1]);
+ assertEquals(tb3, ((TestBean) bean.getList().get(0)));
+ assertEquals(tb2, ((TestBean) bean.getList().get(1)));
+ assertEquals(tb0, ((TestBean) bean.getList().get(2)));
+ assertEquals(null, ((TestBean) bean.getList().get(3)));
+ assertEquals(tb1, ((TestBean) bean.getList().get(4)));
+ assertEquals(tb1, ((TestBean) bean.getMap().get("key1")));
+ assertEquals(tb0, ((TestBean) bean.getMap().get("key2")));
+ assertEquals(tb4, ((TestBean) bean.getMap().get("key5")));
+ assertEquals(tb5, ((TestBean) bean.getMap().get("key9")));
+ assertEquals(tb5, bw.getPropertyValue("array[0]"));
+ assertEquals(tb4, bw.getPropertyValue("array[1]"));
+ assertEquals(tb3, bw.getPropertyValue("list[0]"));
+ assertEquals(tb2, bw.getPropertyValue("list[1]"));
+ assertEquals(tb0, bw.getPropertyValue("list[2]"));
+ assertEquals(null, bw.getPropertyValue("list[3]"));
+ assertEquals(tb1, bw.getPropertyValue("list[4]"));
+ assertEquals(tb1, bw.getPropertyValue("map[\"key1\"]"));
+ assertEquals(tb0, bw.getPropertyValue("map['key2']"));
+ assertEquals(tb4, bw.getPropertyValue("map[\"key5\"]"));
+ assertEquals(tb5, bw.getPropertyValue("map['key9']"));
+ }
+
+ public void testMapAccessWithTypeConversion() {
+ IndexedTestBean bean = new IndexedTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(bean);
+ bw.registerCustomEditor(TestBean.class, new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ if (!StringUtils.hasLength(text)) {
+ throw new IllegalArgumentException();
+ }
+ setValue(new TestBean(text));
+ }
+ });
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("map[key1]", "rod");
+ pvs.addPropertyValue("map[key2]", "rob");
+ bw.setPropertyValues(pvs);
+ assertEquals("rod", ((TestBean) bean.getMap().get("key1")).getName());
+ assertEquals("rob", ((TestBean) bean.getMap().get("key2")).getName());
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("map[key1]", "rod");
+ pvs.addPropertyValue("map[key2]", "");
+ try {
+ bw.setPropertyValues(pvs);
+ fail("Should have thrown TypeMismatchException");
+ }
+ catch (PropertyBatchUpdateException ex) {
+ PropertyAccessException pae = ex.getPropertyAccessException("map[key2]");
+ assertTrue(pae instanceof TypeMismatchException);
+ }
+ }
+
+ public void testMapAccessWithUnmodifiableMap() {
+ IndexedTestBean bean = new IndexedTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(bean);
+ bw.registerCustomEditor(TestBean.class, "map", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ if (!StringUtils.hasLength(text)) {
+ throw new IllegalArgumentException();
+ }
+ setValue(new TestBean(text));
+ }
+ });
+
+ Map inputMap = new HashMap();
+ inputMap.put(new Integer(1), "rod");
+ inputMap.put(new Integer(2), "rob");
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("map", Collections.unmodifiableMap(inputMap));
+ bw.setPropertyValues(pvs);
+ assertEquals("rod", ((TestBean) bean.getMap().get(new Integer(1))).getName());
+ assertEquals("rob", ((TestBean) bean.getMap().get(new Integer(2))).getName());
+ }
+
+ public void testMapAccessWithCustomUnmodifiableMap() {
+ IndexedTestBean bean = new IndexedTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(bean);
+ bw.registerCustomEditor(TestBean.class, "map", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ if (!StringUtils.hasLength(text)) {
+ throw new IllegalArgumentException();
+ }
+ setValue(new TestBean(text));
+ }
+ });
+
+ Map inputMap = new HashMap();
+ inputMap.put(new Integer(1), "rod");
+ inputMap.put(new Integer(2), "rob");
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("map", new ReadOnlyMap(inputMap));
+ bw.setPropertyValues(pvs);
+ assertEquals("rod", ((TestBean) bean.getMap().get(new Integer(1))).getName());
+ assertEquals("rob", ((TestBean) bean.getMap().get(new Integer(2))).getName());
+ }
+
+ public void testRawMapAccessWithNoEditorRegistered() {
+ IndexedTestBean bean = new IndexedTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(bean);
+ Map inputMap = new HashMap();
+ inputMap.put(new Integer(1), "rod");
+ inputMap.put(new Integer(2), "rob");
+ ReadOnlyMap readOnlyMap = new ReadOnlyMap(inputMap);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("map", readOnlyMap);
+ bw.setPropertyValues(pvs);
+ assertSame(readOnlyMap, bean.getMap());
+ assertFalse(readOnlyMap.isAccessed());
+ }
+
+ public void testPrimitiveArray() {
+ PrimitiveArrayBean tb = new PrimitiveArrayBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ bw.setPropertyValue("array", new String[] {"1", "2"});
+ assertEquals(2, tb.getArray().length);
+ assertEquals(1, tb.getArray()[0]);
+ assertEquals(2, tb.getArray()[1]);
+ }
+
+ public void testLargeMatchingPrimitiveArray() {
+ if (LogFactory.getLog(BeanWrapperTests.class).isTraceEnabled()) {
+ // Skip this test: Trace logging blows the time limit.
+ return;
+ }
+
+ PrimitiveArrayBean tb = new PrimitiveArrayBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ int[] input = new int[1024];
+ StopWatch sw = new StopWatch();
+ sw.start("array1");
+ for (int i = 0; i < 1000; i++) {
+ bw.setPropertyValue("array", input);
+ }
+ sw.stop();
+ assertEquals(1024, tb.getArray().length);
+ assertEquals(0, tb.getArray()[0]);
+ long time1 = sw.getLastTaskTimeMillis();
+ assertTrue("Took too long", sw.getLastTaskTimeMillis() < 100);
+
+ bw.registerCustomEditor(String.class, new StringTrimmerEditor(false));
+ sw.start("array2");
+ for (int i = 0; i < 1000; i++) {
+ bw.setPropertyValue("array", input);
+ }
+ sw.stop();
+ assertTrue("Took too long", sw.getLastTaskTimeMillis() < 100);
+
+ bw.registerCustomEditor(int.class, "array.somePath", new CustomNumberEditor(Integer.class, false));
+ sw.start("array3");
+ for (int i = 0; i < 1000; i++) {
+ bw.setPropertyValue("array", input);
+ }
+ sw.stop();
+ assertTrue("Took too long", sw.getLastTaskTimeMillis() < 100);
+
+ bw.registerCustomEditor(int.class, "array[0].somePath", new CustomNumberEditor(Integer.class, false));
+ sw.start("array3");
+ for (int i = 0; i < 1000; i++) {
+ bw.setPropertyValue("array", input);
+ }
+ sw.stop();
+ assertTrue("Took too long", sw.getLastTaskTimeMillis() < 100);
+
+ bw.registerCustomEditor(int.class, new CustomNumberEditor(Integer.class, false));
+ sw.start("array4");
+ for (int i = 0; i < 100; i++) {
+ bw.setPropertyValue("array", input);
+ }
+ sw.stop();
+ assertEquals(1024, tb.getArray().length);
+ assertEquals(0, tb.getArray()[0]);
+ assertTrue("Took too long", sw.getLastTaskTimeMillis() > time1);
+ }
+
+ public void testLargeMatchingPrimitiveArrayWithSpecificEditor() {
+ PrimitiveArrayBean tb = new PrimitiveArrayBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ bw.registerCustomEditor(int.class, "array", new PropertyEditorSupport() {
+ public void setValue(Object value) {
+ if (value instanceof Integer) {
+ super.setValue(new Integer(((Integer) value).intValue() + 1));
+ }
+ }
+ });
+ int[] input = new int[1024];
+ bw.setPropertyValue("array", input);
+ assertEquals(1024, tb.getArray().length);
+ assertEquals(1, tb.getArray()[0]);
+ assertEquals(1, tb.getArray()[1]);
+ }
+
+ public void testLargeMatchingPrimitiveArrayWithIndexSpecificEditor() {
+ PrimitiveArrayBean tb = new PrimitiveArrayBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ bw.registerCustomEditor(int.class, "array[1]", new PropertyEditorSupport() {
+ public void setValue(Object value) {
+ if (value instanceof Integer) {
+ super.setValue(new Integer(((Integer) value).intValue() + 1));
+ }
+ }
+ });
+ int[] input = new int[1024];
+ bw.setPropertyValue("array", input);
+ assertEquals(1024, tb.getArray().length);
+ assertEquals(0, tb.getArray()[0]);
+ assertEquals(1, tb.getArray()[1]);
+ }
+
+ public void testPropertiesInProtectedBaseBean() {
+ DerivedFromProtectedBaseBean bean = new DerivedFromProtectedBaseBean();
+ BeanWrapper bw = new BeanWrapperImpl(bean);
+ bw.setPropertyValue("someProperty", "someValue");
+ assertEquals("someValue", bw.getPropertyValue("someProperty"));
+ assertEquals("someValue", bean.getSomeProperty());
+ }
+
+ public void testErrorMessageOfNestedProperty() {
+ ITestBean parent = new TestBean();
+ ITestBean child = new DifferentTestBean();
+ child.setName("test");
+ parent.setSpouse(child);
+ BeanWrapper bw = new BeanWrapperImpl(parent);
+ try {
+ bw.getPropertyValue("spouse.bla");
+ }
+ catch (NotReadablePropertyException ex) {
+ assertTrue(ex.getMessage().indexOf(TestBean.class.getName()) != -1);
+ }
+ }
+
+ public void testMatchingCollections() {
+ IndexedTestBean tb = new IndexedTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ Collection coll = new HashSet();
+ coll.add("coll1");
+ bw.setPropertyValue("collection", coll);
+ Set set = new HashSet();
+ set.add("set1");
+ bw.setPropertyValue("set", set);
+ SortedSet sortedSet = new TreeSet();
+ sortedSet.add("sortedSet1");
+ bw.setPropertyValue("sortedSet", sortedSet);
+ List list = new LinkedList();
+ list.add("list1");
+ bw.setPropertyValue("list", list);
+ assertSame(coll, tb.getCollection());
+ assertSame(set, tb.getSet());
+ assertSame(sortedSet, tb.getSortedSet());
+ assertSame(list, tb.getList());
+ }
+
+ public void testNonMatchingCollections() {
+ IndexedTestBean tb = new IndexedTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ Collection coll = new ArrayList();
+ coll.add("coll1");
+ bw.setPropertyValue("collection", coll);
+ List set = new LinkedList();
+ set.add("set1");
+ bw.setPropertyValue("set", set);
+ List sortedSet = new ArrayList();
+ sortedSet.add("sortedSet1");
+ bw.setPropertyValue("sortedSet", sortedSet);
+ Set list = new HashSet();
+ list.add("list1");
+ bw.setPropertyValue("list", list);
+ assertEquals(1, tb.getCollection().size());
+ assertTrue(tb.getCollection().containsAll(coll));
+ assertEquals(1, tb.getSet().size());
+ assertTrue(tb.getSet().containsAll(set));
+ assertEquals(1, tb.getSortedSet().size());
+ assertTrue(tb.getSortedSet().containsAll(sortedSet));
+ assertEquals(1, tb.getList().size());
+ assertTrue(tb.getList().containsAll(list));
+ }
+
+ public void testCollectionsWithArrayValues() {
+ IndexedTestBean tb = new IndexedTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ Collection coll = new HashSet();
+ coll.add("coll1");
+ bw.setPropertyValue("collection", coll.toArray());
+ List set = new LinkedList();
+ set.add("set1");
+ bw.setPropertyValue("set", set.toArray());
+ List sortedSet = new ArrayList();
+ sortedSet.add("sortedSet1");
+ bw.setPropertyValue("sortedSet", sortedSet.toArray());
+ Set list = new HashSet();
+ list.add("list1");
+ bw.setPropertyValue("list", list.toArray());
+ assertEquals(1, tb.getCollection().size());
+ assertTrue(tb.getCollection().containsAll(coll));
+ assertEquals(1, tb.getSet().size());
+ assertTrue(tb.getSet().containsAll(set));
+ assertEquals(1, tb.getSortedSet().size());
+ assertTrue(tb.getSortedSet().containsAll(sortedSet));
+ assertEquals(1, tb.getList().size());
+ assertTrue(tb.getList().containsAll(list));
+ }
+
+ public void testCollectionsWithIntArrayValues() {
+ IndexedTestBean tb = new IndexedTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ Collection coll = new HashSet();
+ coll.add(new Integer(0));
+ bw.setPropertyValue("collection", new int[] {0});
+ List set = new LinkedList();
+ set.add(new Integer(1));
+ bw.setPropertyValue("set", new int[] {1});
+ List sortedSet = new ArrayList();
+ sortedSet.add(new Integer(2));
+ bw.setPropertyValue("sortedSet", new int[] {2});
+ Set list = new HashSet();
+ list.add(new Integer(3));
+ bw.setPropertyValue("list", new int[] {3});
+ assertEquals(1, tb.getCollection().size());
+ assertTrue(tb.getCollection().containsAll(coll));
+ assertEquals(1, tb.getSet().size());
+ assertTrue(tb.getSet().containsAll(set));
+ assertEquals(1, tb.getSortedSet().size());
+ assertTrue(tb.getSortedSet().containsAll(sortedSet));
+ assertEquals(1, tb.getList().size());
+ assertTrue(tb.getList().containsAll(list));
+ }
+
+ public void testCollectionsWithIntegerValues() {
+ IndexedTestBean tb = new IndexedTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ Collection coll = new HashSet();
+ coll.add(new Integer(0));
+ bw.setPropertyValue("collection", new Integer(0));
+ List set = new LinkedList();
+ set.add(new Integer(1));
+ bw.setPropertyValue("set", new Integer(1));
+ List sortedSet = new ArrayList();
+ sortedSet.add(new Integer(2));
+ bw.setPropertyValue("sortedSet", new Integer(2));
+ Set list = new HashSet();
+ list.add(new Integer(3));
+ bw.setPropertyValue("list", new Integer(3));
+ assertEquals(1, tb.getCollection().size());
+ assertTrue(tb.getCollection().containsAll(coll));
+ assertEquals(1, tb.getSet().size());
+ assertTrue(tb.getSet().containsAll(set));
+ assertEquals(1, tb.getSortedSet().size());
+ assertTrue(tb.getSortedSet().containsAll(sortedSet));
+ assertEquals(1, tb.getList().size());
+ assertTrue(tb.getList().containsAll(list));
+ }
+
+ public void testCollectionsWithStringValues() {
+ IndexedTestBean tb = new IndexedTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ List set = new LinkedList();
+ set.add("set1");
+ bw.setPropertyValue("set", "set1");
+ List sortedSet = new ArrayList();
+ sortedSet.add("sortedSet1");
+ bw.setPropertyValue("sortedSet", "sortedSet1");
+ Set list = new HashSet();
+ list.add("list1");
+ bw.setPropertyValue("list", "list1");
+ assertEquals(1, tb.getSet().size());
+ assertTrue(tb.getSet().containsAll(set));
+ assertEquals(1, tb.getSortedSet().size());
+ assertTrue(tb.getSortedSet().containsAll(sortedSet));
+ assertEquals(1, tb.getList().size());
+ assertTrue(tb.getList().containsAll(list));
+ }
+
+ public void testCollectionsWithStringValuesAndCustomEditor() {
+ IndexedTestBean tb = new IndexedTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ bw.registerCustomEditor(String.class, "set", new StringTrimmerEditor(false));
+ bw.registerCustomEditor(String.class, "list", new StringTrimmerEditor(false));
+
+ bw.setPropertyValue("set", "set1 ");
+ bw.setPropertyValue("sortedSet", "sortedSet1");
+ bw.setPropertyValue("list", "list1 ");
+ assertEquals(1, tb.getSet().size());
+ assertTrue(tb.getSet().contains("set1"));
+ assertEquals(1, tb.getSortedSet().size());
+ assertTrue(tb.getSortedSet().contains("sortedSet1"));
+ assertEquals(1, tb.getList().size());
+ assertTrue(tb.getList().contains("list1"));
+
+ bw.setPropertyValue("list", Arrays.asList(new String[] {"list1 "}));
+ assertTrue(tb.getList().contains("list1"));
+ }
+
+ public void testMatchingMaps() {
+ IndexedTestBean tb = new IndexedTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ Map map = new HashMap();
+ map.put("key", "value");
+ bw.setPropertyValue("map", map);
+ SortedMap sortedMap = new TreeMap();
+ map.put("sortedKey", "sortedValue");
+ bw.setPropertyValue("sortedMap", sortedMap);
+ assertSame(map, tb.getMap());
+ assertSame(sortedMap, tb.getSortedMap());
+ }
+
+ public void testNonMatchingMaps() {
+ IndexedTestBean tb = new IndexedTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ Map map = new TreeMap();
+ map.put("key", "value");
+ bw.setPropertyValue("map", map);
+ Map sortedMap = new HashMap();
+ sortedMap.put("sortedKey", "sortedValue");
+ bw.setPropertyValue("sortedMap", sortedMap);
+ assertEquals(1, tb.getMap().size());
+ assertEquals("value", tb.getMap().get("key"));
+ assertEquals(1, tb.getSortedMap().size());
+ assertEquals("sortedValue", tb.getSortedMap().get("sortedKey"));
+ }
+
+ public void testSetNumberProperties() {
+ NumberPropertyBean bean = new NumberPropertyBean();
+ BeanWrapper bw = new BeanWrapperImpl(bean);
+
+ String byteValue = " " + Byte.MAX_VALUE + " ";
+ String shortValue = " " + Short.MAX_VALUE + " ";
+ String intValue = " " + Integer.MAX_VALUE + " ";
+ String longValue = " " + Long.MAX_VALUE + " ";
+ String floatValue = " " + Float.MAX_VALUE + " ";
+ String doubleValue = " " + Double.MAX_VALUE + " ";
+
+ bw.setPropertyValue("myPrimitiveByte", byteValue);
+ bw.setPropertyValue("myByte", byteValue);
+
+ bw.setPropertyValue("myPrimitiveShort", shortValue);
+ bw.setPropertyValue("myShort", shortValue);
+
+ bw.setPropertyValue("myPrimitiveInt", intValue);
+ bw.setPropertyValue("myInteger", intValue);
+
+ bw.setPropertyValue("myPrimitiveLong", longValue);
+ bw.setPropertyValue("myLong", longValue);
+
+ bw.setPropertyValue("myPrimitiveFloat", floatValue);
+ bw.setPropertyValue("myFloat", floatValue);
+
+ bw.setPropertyValue("myPrimitiveDouble", doubleValue);
+ bw.setPropertyValue("myDouble", doubleValue);
+
+ assertEquals(Byte.MAX_VALUE, bean.getMyPrimitiveByte());
+ assertEquals(Byte.MAX_VALUE, bean.getMyByte().byteValue());
+
+ assertEquals(Short.MAX_VALUE, bean.getMyPrimitiveShort());
+ assertEquals(Short.MAX_VALUE, bean.getMyShort().shortValue());
+
+ assertEquals(Integer.MAX_VALUE, bean.getMyPrimitiveInt());
+ assertEquals(Integer.MAX_VALUE, bean.getMyInteger().intValue());
+
+ assertEquals(Long.MAX_VALUE, bean.getMyPrimitiveLong());
+ assertEquals(Long.MAX_VALUE, bean.getMyLong().longValue());
+
+ assertEquals(Float.MAX_VALUE, bean.getMyPrimitiveFloat(), 0.001);
+ assertEquals(Float.MAX_VALUE, bean.getMyFloat().floatValue(), 0.001);
+
+ assertEquals(Double.MAX_VALUE, bean.getMyPrimitiveDouble(), 0.001);
+ assertEquals(Double.MAX_VALUE, bean.getMyDouble().doubleValue(), 0.001);
+
+ }
+
+ public void testAlternativesForTypo() {
+ IntelliBean ib = new IntelliBean();
+ BeanWrapper bw = new BeanWrapperImpl(ib);
+ try {
+ bw.setPropertyValue("names", "Alef");
+ }
+ catch (NotWritablePropertyException ex) {
+ assertNotNull("Possible matches not determined", ex.getPossibleMatches());
+ assertEquals("Invalid amount of alternatives", 1, ex.getPossibleMatches().length);
+ }
+ }
+
+ public void testAlternativesForTypos() {
+ IntelliBean ib = new IntelliBean();
+ BeanWrapper bw = new BeanWrapperImpl(ib);
+ try {
+ bw.setPropertyValue("mystring", "Arjen");
+ }
+ catch (NotWritablePropertyException ex) {
+ assertNotNull("Possible matches not determined", ex.getPossibleMatches());
+ assertEquals("Invalid amount of alternatives", 3, ex.getPossibleMatches().length);
+ }
+ }
+
+
+ private static class DifferentTestBean extends TestBean {
+ // class to test naming of beans in a BeanWrapper error message
+ }
+
+
+ private static class NoRead {
+
+ public void setAge(int age) {
+ }
+ }
+
+
+ private static class EnumTester {
+
+ private FlushMode flushMode;
+
+ public void setFlushMode(FlushMode flushMode) {
+ this.flushMode = flushMode;
+ }
+
+ public FlushMode getFlushMode() {
+ return flushMode;
+ }
+ }
+
+
+ private static class PropsTester {
+
+ private Properties props;
+
+ private String name;
+
+ private String[] stringArray;
+
+ private int[] intArray;
+
+ public void setProperties(Properties p) {
+ props = p;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setStringArray(String[] sa) {
+ this.stringArray = sa;
+ }
+
+ public void setIntArray(int[] intArray) {
+ this.intArray = intArray;
+ }
+ }
+
+
+ private static class GetterBean {
+
+ private String name;
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ if (this.name == null) {
+ throw new RuntimeException("name property must be set");
+ }
+ return name;
+ }
+ }
+
+
+ private static class ThrowsException {
+
+ public void doSomething(Throwable t) throws Throwable {
+ throw t;
+ }
+ }
+
+
+ private static class PrimitiveArrayBean {
+
+ private int[] array;
+
+ public int[] getArray() {
+ return array;
+ }
+
+ public void setArray(int[] array) {
+ this.array = array;
+ }
+ }
+
+
+ private static class NumberPropertyBean {
+
+ private byte myPrimitiveByte;
+ private Byte myByte;
+
+ private short myPrimitiveShort;
+ private Short myShort;
+
+ private int myPrimitiveInt;
+ private Integer myInteger;
+
+ private long myPrimitiveLong;
+ private Long myLong;
+
+ private float myPrimitiveFloat;
+ private Float myFloat;
+
+ private double myPrimitiveDouble;
+ private Double myDouble;
+
+ public byte getMyPrimitiveByte() {
+ return myPrimitiveByte;
+ }
+
+ public void setMyPrimitiveByte(byte myPrimitiveByte) {
+ this.myPrimitiveByte = myPrimitiveByte;
+ }
+
+ public Byte getMyByte() {
+ return myByte;
+ }
+
+ public void setMyByte(Byte myByte) {
+ this.myByte = myByte;
+ }
+
+ public short getMyPrimitiveShort() {
+ return myPrimitiveShort;
+ }
+
+ public void setMyPrimitiveShort(short myPrimitiveShort) {
+ this.myPrimitiveShort = myPrimitiveShort;
+ }
+
+ public Short getMyShort() {
+ return myShort;
+ }
+
+ public void setMyShort(Short myShort) {
+ this.myShort = myShort;
+ }
+
+ public int getMyPrimitiveInt() {
+ return myPrimitiveInt;
+ }
+
+ public void setMyPrimitiveInt(int myPrimitiveInt) {
+ this.myPrimitiveInt = myPrimitiveInt;
+ }
+
+ public Integer getMyInteger() {
+ return myInteger;
+ }
+
+ public void setMyInteger(Integer myInteger) {
+ this.myInteger = myInteger;
+ }
+
+ public long getMyPrimitiveLong() {
+ return myPrimitiveLong;
+ }
+
+ public void setMyPrimitiveLong(long myPrimitiveLong) {
+ this.myPrimitiveLong = myPrimitiveLong;
+ }
+
+ public Long getMyLong() {
+ return myLong;
+ }
+
+ public void setMyLong(Long myLong) {
+ this.myLong = myLong;
+ }
+
+ public float getMyPrimitiveFloat() {
+ return myPrimitiveFloat;
+ }
+
+ public void setMyPrimitiveFloat(float myPrimitiveFloat) {
+ this.myPrimitiveFloat = myPrimitiveFloat;
+ }
+
+ public Float getMyFloat() {
+ return myFloat;
+ }
+
+ public void setMyFloat(Float myFloat) {
+ this.myFloat = myFloat;
+ }
+
+ public double getMyPrimitiveDouble() {
+ return myPrimitiveDouble;
+ }
+
+ public void setMyPrimitiveDouble(double myPrimitiveDouble) {
+ this.myPrimitiveDouble = myPrimitiveDouble;
+ }
+
+ public Double getMyDouble() {
+ return myDouble;
+ }
+
+ public void setMyDouble(Double myDouble) {
+ this.myDouble = myDouble;
+ }
+ }
+
+
+ private static class IntelliBean {
+
+ public void setName(String name) {}
+
+ public void setMyString(String string) {}
+
+ public void setMyStrings(String string) {}
+
+ public void setMyStriNg(String string) {}
+
+ public void setMyStringss(String string) {}
+ }
+
+
+ public static class ReadOnlyMap extends HashMap {
+
+ private boolean frozen = false;
+
+ private boolean accessed = false;
+
+ public ReadOnlyMap() {
+ this.frozen = true;
+ }
+
+ public ReadOnlyMap(Map map) {
+ super(map);
+ this.frozen = true;
+ }
+
+ public Object put(Object key, Object value) {
+ if (this.frozen) {
+ throw new UnsupportedOperationException();
+ }
+ else {
+ return super.put(key, value);
+ }
+ }
+
+ public Set entrySet() {
+ this.accessed = true;
+ return super.entrySet();
+ }
+
+ public Set keySet() {
+ this.accessed = true;
+ return super.keySet();
+ }
+
+ public int size() {
+ this.accessed = true;
+ return super.size();
+ }
+
+ public boolean isAccessed() {
+ return this.accessed;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/BooleanTestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/BooleanTestBean.java
new file mode 100644
index 00000000000..608fb109eea
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/BooleanTestBean.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+/**
+ * @author Juergen Hoeller
+ * @since 10.06.2003
+ */
+public class BooleanTestBean {
+
+ private boolean bool1;
+
+ private Boolean bool2;
+
+ public boolean isBool1() {
+ return bool1;
+ }
+
+ public void setBool1(boolean bool1) {
+ this.bool1 = bool1;
+ }
+
+ public Boolean getBool2() {
+ return bool2;
+ }
+
+ public void setBool2(Boolean bool2) {
+ this.bool2 = bool2;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/CachedIntrospectionResultsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/CachedIntrospectionResultsTests.java
new file mode 100644
index 00000000000..09db3bb2ce6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/CachedIntrospectionResultsTests.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+import junit.framework.TestCase;
+
+import org.springframework.core.OverridingClassLoader;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class CachedIntrospectionResultsTests extends TestCase {
+
+ public void testAcceptClassLoader() throws Exception {
+ BeanWrapper bw = new BeanWrapperImpl(TestBean.class);
+ assertTrue(bw.isWritableProperty("name"));
+ assertTrue(bw.isWritableProperty("age"));
+ assertTrue(CachedIntrospectionResults.classCache.containsKey(TestBean.class));
+
+ ClassLoader child = new OverridingClassLoader(getClass().getClassLoader());
+ Class tbClass = child.loadClass("org.springframework.beans.TestBean");
+ assertFalse(CachedIntrospectionResults.classCache.containsKey(tbClass));
+ CachedIntrospectionResults.acceptClassLoader(child);
+ bw = new BeanWrapperImpl(tbClass);
+ assertTrue(bw.isWritableProperty("name"));
+ assertTrue(bw.isWritableProperty("age"));
+ assertTrue(CachedIntrospectionResults.classCache.containsKey(tbClass));
+ CachedIntrospectionResults.clearClassLoader(child);
+ assertFalse(CachedIntrospectionResults.classCache.containsKey(tbClass));
+
+ assertTrue(CachedIntrospectionResults.classCache.containsKey(TestBean.class));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/Colour.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/Colour.java
new file mode 100644
index 00000000000..4db722187d9
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/Colour.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+import org.springframework.core.enums.ShortCodedLabeledEnum;
+
+/**
+ * @author Rob Harrop
+ */
+public class Colour extends ShortCodedLabeledEnum {
+
+ public static final Colour RED = new Colour(0, "RED");
+ public static final Colour BLUE = new Colour(1, "BLUE");
+ public static final Colour GREEN = new Colour(2, "GREEN");
+ public static final Colour PURPLE = new Colour(3, "PURPLE");
+
+ private Colour(int code, String label) {
+ super(code, label);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/ConcurrentBeanWrapperTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/ConcurrentBeanWrapperTests.java
new file mode 100644
index 00000000000..028f79e46c3
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/ConcurrentBeanWrapperTests.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+
+import junit.framework.TestCase;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * @author Guillaume Poirier
+ * @author Juergen Hoeller
+ * @since 08.03.2004
+ */
+public class ConcurrentBeanWrapperTests extends TestCase {
+
+ private final Log logger = LogFactory.getLog(getClass());
+
+ private Set set = Collections.synchronizedSet(new HashSet());
+
+ private Throwable ex = null;
+
+ public void testSingleThread() {
+ for (int i = 0; i < 100; i++) {
+ performSet();
+ }
+ }
+
+ public void testConcurrent() {
+ for (int i = 0; i < 10; i++) {
+ TestRun run = new TestRun(this);
+ set.add(run);
+ Thread t = new Thread(run);
+ t.setDaemon(true);
+ t.start();
+ }
+ logger.info("Thread creation over, " + set.size() + " still active.");
+ synchronized (this) {
+ while (!set.isEmpty() && ex == null) {
+ try {
+ wait();
+ }
+ catch (InterruptedException e) {
+ logger.info(e.toString());
+ }
+ logger.info(set.size() + " threads still active.");
+ }
+ }
+ if (ex != null) {
+ fail(ex.getMessage());
+ }
+ }
+
+ private static void performSet() {
+ TestBean bean = new TestBean();
+
+ Properties p = (Properties) System.getProperties().clone();
+
+ assertTrue("The System properties must not be empty", p.size() != 0);
+
+ for (Iterator i = p.entrySet().iterator(); i.hasNext();) {
+ i.next();
+ if (Math.random() > 0.9) {
+ i.remove();
+ }
+ }
+
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ try {
+ p.store(buffer, null);
+ }
+ catch (IOException e) {
+ // ByteArrayOutputStream does not throw
+ // any IOException
+ }
+ String value = new String(buffer.toByteArray());
+
+ BeanWrapperImpl wrapper = new BeanWrapperImpl(bean);
+ wrapper.setPropertyValue("properties", value);
+ assertEquals(p, bean.getProperties());
+ }
+
+
+ private static class TestRun implements Runnable {
+
+ private ConcurrentBeanWrapperTests test;
+
+ public TestRun(ConcurrentBeanWrapperTests test) {
+ this.test = test;
+ }
+
+ public void run() {
+ try {
+ for (int i = 0; i < 100; i++) {
+ performSet();
+ }
+ }
+ catch (Throwable e) {
+ test.ex = e;
+ }
+ finally {
+ synchronized (test) {
+ test.set.remove(this);
+ test.notifyAll();
+ }
+ }
+ }
+ }
+
+
+ private static class TestBean {
+
+ private Properties properties;
+
+ public Properties getProperties() {
+ return properties;
+ }
+
+ public void setProperties(Properties properties) {
+ this.properties = properties;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/DerivedTestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/DerivedTestBean.java
new file mode 100644
index 00000000000..db326041c36
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/DerivedTestBean.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+import java.io.Serializable;
+
+import org.springframework.beans.factory.BeanNameAware;
+import org.springframework.beans.factory.DisposableBean;
+
+/**
+ * @author Juergen Hoeller
+ * @since 21.08.2003
+ */
+public class DerivedTestBean extends TestBean implements Serializable, BeanNameAware, DisposableBean {
+
+ private String beanName;
+
+ private boolean initialized;
+
+ private boolean destroyed;
+
+
+ public DerivedTestBean() {
+ }
+
+ public DerivedTestBean(String[] names) {
+ if (names == null || names.length < 2) {
+ throw new IllegalArgumentException("Invalid names array");
+ }
+ setName(names[0]);
+ setBeanName(names[1]);
+ }
+
+ public static DerivedTestBean create(String[] names) {
+ return new DerivedTestBean(names);
+ }
+
+
+ public void setBeanName(String beanName) {
+ if (this.beanName == null || beanName == null) {
+ this.beanName = beanName;
+ }
+ }
+
+ public String getBeanName() {
+ return beanName;
+ }
+
+ public void setSpouseRef(String name) {
+ setSpouse(new TestBean(name));
+ }
+
+
+ public void initialize() {
+ this.initialized = true;
+ }
+
+ public boolean wasInitialized() {
+ return initialized;
+ }
+
+
+ public void destroy() {
+ this.destroyed = true;
+ }
+
+ public boolean wasDestroyed() {
+ return destroyed;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/Employee.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/Employee.java
new file mode 100644
index 00000000000..923c0041087
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/Employee.java
@@ -0,0 +1,39 @@
+
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+public class Employee extends TestBean {
+
+ private String co;
+
+ /**
+ * Constructor for Employee.
+ */
+ public Employee() {
+ super();
+ }
+
+ public String getCompany() {
+ return co;
+ }
+
+ public void setCompany(String co) {
+ this.co = co;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/FieldAccessBean.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/FieldAccessBean.java
new file mode 100644
index 00000000000..f367fb5d6e3
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/FieldAccessBean.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+/**
+ * @author Juergen Hoeller
+ * @since 07.03.2006
+ */
+public class FieldAccessBean {
+
+ public String name;
+
+ protected int age;
+
+ private TestBean spouse;
+
+
+ public String getName() {
+ return name;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public TestBean getSpouse() {
+ return spouse;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/INestedTestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/INestedTestBean.java
new file mode 100644
index 00000000000..e9d9c581bb4
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/INestedTestBean.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+public interface INestedTestBean {
+
+ public String getCompany();
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/IOther.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/IOther.java
new file mode 100644
index 00000000000..41f657082c4
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/IOther.java
@@ -0,0 +1,24 @@
+
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+public interface IOther {
+
+ void absquatulate();
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/ITestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/ITestBean.java
new file mode 100644
index 00000000000..2efb9b7be1b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/ITestBean.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+import java.io.IOException;
+
+/**
+ * Interface used for {@link TestBean}.
+ *
+ *
Two methods are the same as on Person, but if this
+ * extends person it breaks quite a few tests..
+ *
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public interface ITestBean {
+
+ int getAge();
+
+ void setAge(int age);
+
+ String getName();
+
+ void setName(String name);
+
+ ITestBean getSpouse();
+
+ void setSpouse(ITestBean spouse);
+
+ ITestBean[] getSpouses();
+
+ String[] getStringArray();
+
+ void setStringArray(String[] stringArray);
+
+ /**
+ * Throws a given (non-null) exception.
+ */
+ void exceptional(Throwable t) throws Throwable;
+
+ Object returnsThis();
+
+ INestedTestBean getDoctor();
+
+ INestedTestBean getLawyer();
+
+ IndexedTestBean getNestedIndexedBean();
+
+ /**
+ * Increment the age by one.
+ * @return the previous age
+ */
+ int haveBirthday();
+
+ void unreliableFileOperation() throws IOException;
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/IndexedTestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/IndexedTestBean.java
new file mode 100644
index 00000000000..4f3012666ea
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/IndexedTestBean.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * @author Juergen Hoeller
+ * @since 11.11.2003
+ */
+public class IndexedTestBean {
+
+ private TestBean[] array;
+
+ private Collection collection;
+
+ private List list;
+
+ private Set set;
+
+ private SortedSet sortedSet;
+
+ private Map map;
+
+ private SortedMap sortedMap;
+
+
+ public IndexedTestBean() {
+ this(true);
+ }
+
+ public IndexedTestBean(boolean populate) {
+ if (populate) {
+ populate();
+ }
+ }
+
+ public void populate() {
+ TestBean tb0 = new TestBean("name0", 0);
+ TestBean tb1 = new TestBean("name1", 0);
+ TestBean tb2 = new TestBean("name2", 0);
+ TestBean tb3 = new TestBean("name3", 0);
+ TestBean tb4 = new TestBean("name4", 0);
+ TestBean tb5 = new TestBean("name5", 0);
+ TestBean tb6 = new TestBean("name6", 0);
+ TestBean tb7 = new TestBean("name7", 0);
+ TestBean tbX = new TestBean("nameX", 0);
+ TestBean tbY = new TestBean("nameY", 0);
+ this.array = new TestBean[] {tb0, tb1};
+ this.list = new ArrayList();
+ this.list.add(tb2);
+ this.list.add(tb3);
+ this.set = new TreeSet();
+ this.set.add(tb6);
+ this.set.add(tb7);
+ this.map = new HashMap();
+ this.map.put("key1", tb4);
+ this.map.put("key2", tb5);
+ this.map.put("key.3", tb5);
+ List list = new ArrayList();
+ list.add(tbX);
+ list.add(tbY);
+ this.map.put("key4", list);
+ }
+
+
+ public TestBean[] getArray() {
+ return array;
+ }
+
+ public void setArray(TestBean[] array) {
+ this.array = array;
+ }
+
+ public Collection getCollection() {
+ return collection;
+ }
+
+ public void setCollection(Collection collection) {
+ this.collection = collection;
+ }
+
+ public List getList() {
+ return list;
+ }
+
+ public void setList(List list) {
+ this.list = list;
+ }
+
+ public Set getSet() {
+ return set;
+ }
+
+ public void setSet(Set set) {
+ this.set = set;
+ }
+
+ public SortedSet getSortedSet() {
+ return sortedSet;
+ }
+
+ public void setSortedSet(SortedSet sortedSet) {
+ this.sortedSet = sortedSet;
+ }
+
+ public Map getMap() {
+ return map;
+ }
+
+ public void setMap(Map map) {
+ this.map = map;
+ }
+
+ public SortedMap getSortedMap() {
+ return sortedMap;
+ }
+
+ public void setSortedMap(SortedMap sortedMap) {
+ this.sortedMap = sortedMap;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/MutablePropertyValuesTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/MutablePropertyValuesTests.java
new file mode 100644
index 00000000000..c6fa04227a4
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/MutablePropertyValuesTests.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+/**
+ * Tests for MutablePropertyValues.
+ *
+ * @author Rod Johnson
+ */
+public class MutablePropertyValuesTests extends AbstractPropertyValuesTests {
+
+ public void testValid() throws Exception {
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue(new PropertyValue("forname", "Tony"));
+ pvs.addPropertyValue(new PropertyValue("surname", "Blair"));
+ pvs.addPropertyValue(new PropertyValue("age", "50"));
+ doTestTony(pvs);
+
+ MutablePropertyValues deepCopy = new MutablePropertyValues(pvs);
+ doTestTony(deepCopy);
+ deepCopy.setPropertyValueAt(new PropertyValue("name", "Gordon"), 0);
+ doTestTony(pvs);
+ assertEquals("Gordon", deepCopy.getPropertyValue("name").getValue());
+ }
+
+ public void addOrOverride() throws Exception {
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue(new PropertyValue("forname", "Tony"));
+ pvs.addPropertyValue(new PropertyValue("surname", "Blair"));
+ pvs.addPropertyValue(new PropertyValue("age", "50"));
+ doTestTony(pvs);
+ PropertyValue addedPv = new PropertyValue("rod", "Rod");
+ pvs.addPropertyValue(addedPv);
+ assertTrue(pvs.getPropertyValue("rod").equals(addedPv));
+ PropertyValue changedPv = new PropertyValue("forname", "Greg");
+ pvs.addPropertyValue(changedPv);
+ assertTrue(pvs.getPropertyValue("forename").equals(changedPv));
+ }
+
+ public void testChangesOnEquals() throws Exception {
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue(new PropertyValue("forname", "Tony"));
+ pvs.addPropertyValue(new PropertyValue("surname", "Blair"));
+ pvs.addPropertyValue(new PropertyValue("age", "50"));
+ MutablePropertyValues pvs2 = pvs;
+ PropertyValues changes = pvs2.changesSince(pvs);
+ assertTrue("changes are empty", changes.getPropertyValues().length == 0);
+ }
+
+ public void testChangeOfOneField() throws Exception {
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue(new PropertyValue("forname", "Tony"));
+ pvs.addPropertyValue(new PropertyValue("surname", "Blair"));
+ pvs.addPropertyValue(new PropertyValue("age", "50"));
+
+ MutablePropertyValues pvs2 = new MutablePropertyValues(pvs);
+ PropertyValues changes = pvs2.changesSince(pvs);
+ assertTrue("changes are empty, not of length " + changes.getPropertyValues().length,
+ changes.getPropertyValues().length == 0);
+
+ pvs2.addPropertyValue(new PropertyValue("forname", "Gordon"));
+ changes = pvs2.changesSince(pvs);
+ assertEquals("1 change", 1, changes.getPropertyValues().length);
+ PropertyValue fn = changes.getPropertyValue("forname");
+ assertTrue("change is forname", fn != null);
+ assertTrue("new value is gordon", fn.getValue().equals("Gordon"));
+
+ MutablePropertyValues pvs3 = new MutablePropertyValues(pvs);
+ changes = pvs3.changesSince(pvs);
+ assertTrue("changes are empty, not of length " + changes.getPropertyValues().length,
+ changes.getPropertyValues().length == 0);
+
+ // add new
+ pvs3.addPropertyValue(new PropertyValue("foo", "bar"));
+ pvs3.addPropertyValue(new PropertyValue("fi", "fum"));
+ changes = pvs3.changesSince(pvs);
+ assertTrue("2 change", changes.getPropertyValues().length == 2);
+ fn = changes.getPropertyValue("foo");
+ assertTrue("change in foo", fn != null);
+ assertTrue("new value is bar", fn.getValue().equals("bar"));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/NestedTestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/NestedTestBean.java
new file mode 100644
index 00000000000..6b545416234
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/NestedTestBean.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+/**
+ * Simple nested test bean used for testing bean factories, AOP framework etc.
+ *
+ * @author Trevor D. Cook
+ * @since 30.09.2003
+ */
+public class NestedTestBean implements INestedTestBean {
+
+ private String company = "";
+
+ public NestedTestBean() {
+ }
+
+ public NestedTestBean(String company) {
+ setCompany(company);
+ }
+
+ public void setCompany(String company) {
+ this.company = (company != null ? company : "");
+ }
+
+ public String getCompany() {
+ return company;
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof NestedTestBean)) {
+ return false;
+ }
+ NestedTestBean ntb = (NestedTestBean) obj;
+ return this.company.equals(ntb.company);
+ }
+
+ public int hashCode() {
+ return this.company.hashCode();
+ }
+
+ public String toString() {
+ return "NestedTestBean: " + this.company;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/NumberTestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/NumberTestBean.java
new file mode 100644
index 00000000000..80c3ec372aa
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/NumberTestBean.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+/**
+ * @author Juergen Hoeller
+ * @since 10.06.2003
+ */
+public class NumberTestBean {
+
+ private short short1;
+ private Short short2;
+
+ private int int1;
+ private Integer int2;
+
+ private long long1;
+ private Long long2;
+
+ private BigInteger bigInteger;
+
+ private float float1;
+ private Float float2;
+
+ private double double1;
+ private Double double2;
+
+ private BigDecimal bigDecimal;
+
+ public short getShort1() {
+ return short1;
+ }
+
+ public void setShort1(short short1) {
+ this.short1 = short1;
+ }
+
+ public Short getShort2() {
+ return short2;
+ }
+
+ public void setShort2(Short short2) {
+ this.short2 = short2;
+ }
+
+ public int getInt1() {
+ return int1;
+ }
+
+ public void setInt1(int int1) {
+ this.int1 = int1;
+ }
+
+ public Integer getInt2() {
+ return int2;
+ }
+
+ public void setInt2(Integer int2) {
+ this.int2 = int2;
+ }
+
+ public long getLong1() {
+ return long1;
+ }
+
+ public void setLong1(long long1) {
+ this.long1 = long1;
+ }
+
+ public Long getLong2() {
+ return long2;
+ }
+
+ public void setLong2(Long long2) {
+ this.long2 = long2;
+ }
+
+ public BigInteger getBigInteger() {
+ return bigInteger;
+ }
+
+ public void setBigInteger(BigInteger bigInteger) {
+ this.bigInteger = bigInteger;
+ }
+
+ public float getFloat1() {
+ return float1;
+ }
+
+ public void setFloat1(float float1) {
+ this.float1 = float1;
+ }
+
+ public Float getFloat2() {
+ return float2;
+ }
+
+ public void setFloat2(Float float2) {
+ this.float2 = float2;
+ }
+
+ public double getDouble1() {
+ return double1;
+ }
+
+ public void setDouble1(double double1) {
+ this.double1 = double1;
+ }
+
+ public Double getDouble2() {
+ return double2;
+ }
+
+ public void setDouble2(Double double2) {
+ this.double2 = double2;
+ }
+
+ public BigDecimal getBigDecimal() {
+ return bigDecimal;
+ }
+
+ public void setBigDecimal(BigDecimal bigDecimal) {
+ this.bigDecimal = bigDecimal;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/Person.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/Person.java
new file mode 100644
index 00000000000..af3bb924f7e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/Person.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+/**
+ *
+ * @author Rod Johnson
+ */
+public interface Person {
+
+ String getName();
+ void setName(String name);
+ int getAge();
+ void setAge(int i);
+
+ /**
+ * Test for non-property method matching.
+ * If the parameter is a Throwable, it will be thrown rather than
+ * returned.
+ */
+ Object echo(Object o) throws Throwable;
+}
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/Pet.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/Pet.java
new file mode 100644
index 00000000000..eb78f612fb0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/Pet.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+/**
+ * @author Rob Harrop
+ * @since 2.0
+ */
+public class Pet {
+
+ private String name;
+
+ public Pet(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String toString() {
+ return getName();
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final Pet pet = (Pet) o;
+
+ if (name != null ? !name.equals(pet.name) : pet.name != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ return (name != null ? name.hashCode() : 0);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/PropertyAccessorUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/PropertyAccessorUtilsTests.java
new file mode 100644
index 00000000000..7c483830807
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/PropertyAccessorUtilsTests.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class PropertyAccessorUtilsTests extends TestCase {
+
+ public void testCanonicalPropertyName() {
+ assertEquals("map", PropertyAccessorUtils.canonicalPropertyName("map"));
+ assertEquals("map[key1]", PropertyAccessorUtils.canonicalPropertyName("map[key1]"));
+ assertEquals("map[key1]", PropertyAccessorUtils.canonicalPropertyName("map['key1']"));
+ assertEquals("map[key1]", PropertyAccessorUtils.canonicalPropertyName("map[\"key1\"]"));
+ assertEquals("map[key1][key2]", PropertyAccessorUtils.canonicalPropertyName("map[key1][key2]"));
+ assertEquals("map[key1][key2]", PropertyAccessorUtils.canonicalPropertyName("map['key1'][\"key2\"]"));
+ assertEquals("map[key1].name", PropertyAccessorUtils.canonicalPropertyName("map[key1].name"));
+ assertEquals("map[key1].name", PropertyAccessorUtils.canonicalPropertyName("map['key1'].name"));
+ assertEquals("map[key1].name", PropertyAccessorUtils.canonicalPropertyName("map[\"key1\"].name"));
+ }
+
+ public void testCanonicalPropertyNames() {
+ String[] original =
+ new String[] {"map", "map[key1]", "map['key1']", "map[\"key1\"]", "map[key1][key2]",
+ "map['key1'][\"key2\"]", "map[key1].name", "map['key1'].name", "map[\"key1\"].name"};
+ String[] canonical =
+ new String[] {"map", "map[key1]", "map[key1]", "map[key1]", "map[key1][key2]",
+ "map[key1][key2]", "map[key1].name", "map[key1].name", "map[key1].name"};
+
+ assertTrue(Arrays.equals(canonical, PropertyAccessorUtils.canonicalPropertyNames(original)));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/ResourceTestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/ResourceTestBean.java
new file mode 100644
index 00000000000..d9d8cd166ae
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/ResourceTestBean.java
@@ -0,0 +1,41 @@
+package org.springframework.beans;
+
+import java.io.InputStream;
+
+import org.springframework.core.io.Resource;
+
+/**
+ * @author Juergen Hoeller
+ * @since 01.04.2004
+ */
+public class ResourceTestBean {
+
+ private Resource resource;
+
+ private InputStream inputStream;
+
+ public ResourceTestBean() {
+ }
+
+ public ResourceTestBean(Resource resource, InputStream inputStream) {
+ this.resource = resource;
+ this.inputStream = inputStream;
+ }
+
+ public void setResource(Resource resource) {
+ this.resource = resource;
+ }
+
+ public void setInputStream(InputStream inputStream) {
+ this.inputStream = inputStream;
+ }
+
+ public Resource getResource() {
+ return resource;
+ }
+
+ public InputStream getInputStream() {
+ return inputStream;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/SerializablePerson.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/SerializablePerson.java
new file mode 100644
index 00000000000..66a41f51131
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/SerializablePerson.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+import java.io.Serializable;
+
+import org.springframework.util.ObjectUtils;
+
+/**
+ * Serializable implementation of the Person interface.
+ *
+ * @author Rod Johnson
+ */
+public class SerializablePerson implements Person, Serializable {
+
+ private String name;
+ private int age;
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Object echo(Object o) throws Throwable {
+ if (o instanceof Throwable) {
+ throw (Throwable) o;
+ }
+ return o;
+ }
+
+ public boolean equals(Object other) {
+ if (!(other instanceof SerializablePerson)) {
+ return false;
+ }
+ SerializablePerson p = (SerializablePerson) other;
+ return p.age == age && ObjectUtils.nullSafeEquals(name, p.name);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/TestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/TestBean.java
new file mode 100644
index 00000000000..c2a39d38788
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/TestBean.java
@@ -0,0 +1,437 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.beans;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanFactoryAware;
+import org.springframework.beans.factory.BeanNameAware;
+import org.springframework.util.ObjectUtils;
+
+/**
+ * Simple test bean used for testing bean factories, the AOP framework etc.
+ *
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @since 15 April 2001
+ */
+public class TestBean implements BeanNameAware, BeanFactoryAware, ITestBean, IOther, Comparable {
+
+ private String beanName;
+
+ private String country;
+
+ private BeanFactory beanFactory;
+
+ private boolean postProcessed;
+
+ private String name;
+
+ private String sex;
+
+ private int age;
+
+ private boolean jedi;
+
+ private ITestBean[] spouses;
+
+ private String touchy;
+
+ private String[] stringArray;
+
+ private Integer[] someIntegerArray;
+
+ private Date date = new Date();
+
+ private Float myFloat = new Float(0.0);
+
+ private Collection friends = new LinkedList();
+
+ private Set someSet = new HashSet();
+
+ private Map someMap = new HashMap();
+
+ private List someList = new ArrayList();
+
+ private Properties someProperties = new Properties();
+
+ private INestedTestBean doctor = new NestedTestBean();
+
+ private INestedTestBean lawyer = new NestedTestBean();
+
+ private IndexedTestBean nestedIndexedBean;
+
+ private boolean destroyed;
+
+ private Number someNumber;
+
+ private Colour favouriteColour;
+
+ private Boolean someBoolean;
+
+ private List otherColours;
+
+ private List pets;
+
+
+ public TestBean() {
+ }
+
+ public TestBean(String name) {
+ this.name = name;
+ }
+
+ public TestBean(ITestBean spouse) {
+ this.spouses = new ITestBean[] {spouse};
+ }
+
+ public TestBean(String name, int age) {
+ this.name = name;
+ this.age = age;
+ }
+
+ public TestBean(ITestBean spouse, Properties someProperties) {
+ this.spouses = new ITestBean[] {spouse};
+ this.someProperties = someProperties;
+ }
+
+ public TestBean(List someList) {
+ this.someList = someList;
+ }
+
+ public TestBean(Set someSet) {
+ this.someSet = someSet;
+ }
+
+ public TestBean(Map someMap) {
+ this.someMap = someMap;
+ }
+
+ public TestBean(Properties someProperties) {
+ this.someProperties = someProperties;
+ }
+
+
+ public void setBeanName(String beanName) {
+ this.beanName = beanName;
+ }
+
+ public String getBeanName() {
+ return beanName;
+ }
+
+ public void setBeanFactory(BeanFactory beanFactory) {
+ this.beanFactory = beanFactory;
+ }
+
+ public BeanFactory getBeanFactory() {
+ return beanFactory;
+ }
+
+ public void setPostProcessed(boolean postProcessed) {
+ this.postProcessed = postProcessed;
+ }
+
+ public boolean isPostProcessed() {
+ return postProcessed;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getSex() {
+ return sex;
+ }
+
+ public void setSex(String sex) {
+ this.sex = sex;
+ if (this.name == null) {
+ this.name = sex;
+ }
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ public boolean isJedi() {
+ return jedi;
+ }
+
+ public void setJedi(boolean jedi) {
+ this.jedi = jedi;
+ }
+
+ public ITestBean getSpouse() {
+ return (spouses != null ? spouses[0] : null);
+ }
+
+ public void setSpouse(ITestBean spouse) {
+ this.spouses = new ITestBean[] {spouse};
+ }
+
+ public ITestBean[] getSpouses() {
+ return spouses;
+ }
+
+ public String getTouchy() {
+ return touchy;
+ }
+
+ public void setTouchy(String touchy) throws Exception {
+ if (touchy.indexOf('.') != -1) {
+ throw new Exception("Can't contain a .");
+ }
+ if (touchy.indexOf(',') != -1) {
+ throw new NumberFormatException("Number format exception: contains a ,");
+ }
+ this.touchy = touchy;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ public String[] getStringArray() {
+ return stringArray;
+ }
+
+ public void setStringArray(String[] stringArray) {
+ this.stringArray = stringArray;
+ }
+
+ public Integer[] getSomeIntegerArray() {
+ return someIntegerArray;
+ }
+
+ public void setSomeIntegerArray(Integer[] someIntegerArray) {
+ this.someIntegerArray = someIntegerArray;
+ }
+
+ public Date getDate() {
+ return date;
+ }
+
+ public void setDate(Date date) {
+ this.date = date;
+ }
+
+ public Float getMyFloat() {
+ return myFloat;
+ }
+
+ public void setMyFloat(Float myFloat) {
+ this.myFloat = myFloat;
+ }
+
+ public Collection getFriends() {
+ return friends;
+ }
+
+ public void setFriends(Collection friends) {
+ this.friends = friends;
+ }
+
+ public Set getSomeSet() {
+ return someSet;
+ }
+
+ public void setSomeSet(Set someSet) {
+ this.someSet = someSet;
+ }
+
+ public Map getSomeMap() {
+ return someMap;
+ }
+
+ public void setSomeMap(Map someMap) {
+ this.someMap = someMap;
+ }
+
+ public List getSomeList() {
+ return someList;
+ }
+
+ public void setSomeList(List someList) {
+ this.someList = someList;
+ }
+
+ public Properties getSomeProperties() {
+ return someProperties;
+ }
+
+ public void setSomeProperties(Properties someProperties) {
+ this.someProperties = someProperties;
+ }
+
+ public INestedTestBean getDoctor() {
+ return doctor;
+ }
+
+ public void setDoctor(INestedTestBean doctor) {
+ this.doctor = doctor;
+ }
+
+ public INestedTestBean getLawyer() {
+ return lawyer;
+ }
+
+ public void setLawyer(INestedTestBean lawyer) {
+ this.lawyer = lawyer;
+ }
+
+ public Number getSomeNumber() {
+ return someNumber;
+ }
+
+ public void setSomeNumber(Number someNumber) {
+ this.someNumber = someNumber;
+ }
+
+ public Colour getFavouriteColour() {
+ return favouriteColour;
+ }
+
+ public void setFavouriteColour(Colour favouriteColour) {
+ this.favouriteColour = favouriteColour;
+ }
+
+ public Boolean getSomeBoolean() {
+ return someBoolean;
+ }
+
+ public void setSomeBoolean(Boolean someBoolean) {
+ this.someBoolean = someBoolean;
+ }
+
+ public IndexedTestBean getNestedIndexedBean() {
+ return nestedIndexedBean;
+ }
+
+ public void setNestedIndexedBean(IndexedTestBean nestedIndexedBean) {
+ this.nestedIndexedBean = nestedIndexedBean;
+ }
+
+ public List getOtherColours() {
+ return otherColours;
+ }
+
+ public void setOtherColours(List otherColours) {
+ this.otherColours = otherColours;
+ }
+
+ public List getPets() {
+ return pets;
+ }
+
+ public void setPets(List pets) {
+ this.pets = pets;
+ }
+
+
+ /**
+ * @see ITestBean#exceptional(Throwable)
+ */
+ public void exceptional(Throwable t) throws Throwable {
+ if (t != null) {
+ throw t;
+ }
+ }
+
+ public void unreliableFileOperation() throws IOException {
+ throw new IOException();
+ }
+ /**
+ * @see ITestBean#returnsThis()
+ */
+ public Object returnsThis() {
+ return this;
+ }
+
+ /**
+ * @see IOther#absquatulate()
+ */
+ public void absquatulate() {
+ }
+
+ public int haveBirthday() {
+ return age++;
+ }
+
+
+ public void destroy() {
+ this.destroyed = true;
+ }
+
+ public boolean wasDestroyed() {
+ return destroyed;
+ }
+
+
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (other == null || !(other instanceof TestBean)) {
+ return false;
+ }
+ TestBean tb2 = (TestBean) other;
+ return (ObjectUtils.nullSafeEquals(this.name, tb2.name) && this.age == tb2.age);
+ }
+
+ public int hashCode() {
+ return this.age;
+ }
+
+ public int compareTo(Object other) {
+ if (this.name != null && other instanceof TestBean) {
+ return this.name.compareTo(((TestBean) other).getName());
+ }
+ else {
+ return 1;
+ }
+ }
+
+ public String toString() {
+ return this.name;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/AbstractBeanFactoryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/AbstractBeanFactoryTests.java
new file mode 100644
index 00000000000..06adde9568f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/AbstractBeanFactoryTests.java
@@ -0,0 +1,328 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.beans.factory;
+
+import java.beans.PropertyEditorSupport;
+import java.util.StringTokenizer;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.PropertyBatchUpdateException;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+
+/**
+ * Subclasses must implement setUp() to initialize bean factory
+ * and any other variables they need.
+ *
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public abstract class AbstractBeanFactoryTests extends TestCase {
+
+ protected abstract BeanFactory getBeanFactory();
+
+ /**
+ * Roderick beans inherits from rod, overriding name only.
+ */
+ public void testInheritance() {
+ assertTrue(getBeanFactory().containsBean("rod"));
+ assertTrue(getBeanFactory().containsBean("roderick"));
+ TestBean rod = (TestBean) getBeanFactory().getBean("rod");
+ TestBean roderick = (TestBean) getBeanFactory().getBean("roderick");
+ assertTrue("not == ", rod != roderick);
+ assertTrue("rod.name is Rod", rod.getName().equals("Rod"));
+ assertTrue("rod.age is 31", rod.getAge() == 31);
+ assertTrue("roderick.name is Roderick", roderick.getName().equals("Roderick"));
+ assertTrue("roderick.age was inherited", roderick.getAge() == rod.getAge());
+ }
+
+ public void testGetBeanWithNullArg() {
+ try {
+ getBeanFactory().getBean(null);
+ fail("Can't get null bean");
+ }
+ catch (IllegalArgumentException ex) {
+ // OK
+ }
+ }
+
+ /**
+ * Test that InitializingBean objects receive the afterPropertiesSet() callback
+ */
+ public void testInitializingBeanCallback() {
+ MustBeInitialized mbi = (MustBeInitialized) getBeanFactory().getBean("mustBeInitialized");
+ // The dummy business method will throw an exception if the
+ // afterPropertiesSet() callback wasn't invoked
+ mbi.businessMethod();
+ }
+
+ /**
+ * Test that InitializingBean/BeanFactoryAware/DisposableBean objects receive the
+ * afterPropertiesSet() callback before BeanFactoryAware callbacks
+ */
+ public void testLifecycleCallbacks() {
+ LifecycleBean lb = (LifecycleBean) getBeanFactory().getBean("lifecycle");
+ assertEquals("lifecycle", lb.getBeanName());
+ // The dummy business method will throw an exception if the
+ // necessary callbacks weren't invoked in the right order.
+ lb.businessMethod();
+ assertTrue("Not destroyed", !lb.isDestroyed());
+ }
+
+ public void testFindsValidInstance() {
+ try {
+ Object o = getBeanFactory().getBean("rod");
+ assertTrue("Rod bean is a TestBean", o instanceof TestBean);
+ TestBean rod = (TestBean) o;
+ assertTrue("rod.name is Rod", rod.getName().equals("Rod"));
+ assertTrue("rod.age is 31", rod.getAge() == 31);
+ }
+ catch (Exception ex) {
+ ex.printStackTrace();
+ fail("Shouldn't throw exception on getting valid instance");
+ }
+ }
+
+ public void testGetInstanceByMatchingClass() {
+ try {
+ Object o = getBeanFactory().getBean("rod", TestBean.class);
+ assertTrue("Rod bean is a TestBean", o instanceof TestBean);
+ }
+ catch (Exception ex) {
+ ex.printStackTrace();
+ fail("Shouldn't throw exception on getting valid instance with matching class");
+ }
+ }
+
+ public void testGetInstanceByNonmatchingClass() {
+ try {
+ Object o = getBeanFactory().getBean("rod", BeanFactory.class);
+ fail("Rod bean is not of type BeanFactory; getBeanInstance(rod, BeanFactory.class) should throw BeanNotOfRequiredTypeException");
+ }
+ catch (BeanNotOfRequiredTypeException ex) {
+ // So far, so good
+ assertTrue("Exception has correct bean name", ex.getBeanName().equals("rod"));
+ assertTrue("Exception requiredType must be BeanFactory.class", ex.getRequiredType().equals(BeanFactory.class));
+ assertTrue("Exception actualType as TestBean.class", TestBean.class.isAssignableFrom(ex.getActualType()));
+ assertTrue("Actual type is correct", ex.getActualType() == getBeanFactory().getBean("rod").getClass());
+ }
+ catch (Exception ex) {
+ ex.printStackTrace();
+ fail("Shouldn't throw exception on getting valid instance");
+ }
+ }
+
+ public void testGetSharedInstanceByMatchingClass() {
+ try {
+ Object o = getBeanFactory().getBean("rod", TestBean.class);
+ assertTrue("Rod bean is a TestBean", o instanceof TestBean);
+ }
+ catch (Exception ex) {
+ ex.printStackTrace();
+ fail("Shouldn't throw exception on getting valid instance with matching class");
+ }
+ }
+
+ public void testGetSharedInstanceByMatchingClassNoCatch() {
+ Object o = getBeanFactory().getBean("rod", TestBean.class);
+ assertTrue("Rod bean is a TestBean", o instanceof TestBean);
+ }
+
+ public void testGetSharedInstanceByNonmatchingClass() {
+ try {
+ Object o = getBeanFactory().getBean("rod", BeanFactory.class);
+ fail("Rod bean is not of type BeanFactory; getBeanInstance(rod, BeanFactory.class) should throw BeanNotOfRequiredTypeException");
+ }
+ catch (BeanNotOfRequiredTypeException ex) {
+ // So far, so good
+ assertTrue("Exception has correct bean name", ex.getBeanName().equals("rod"));
+ assertTrue("Exception requiredType must be BeanFactory.class", ex.getRequiredType().equals(BeanFactory.class));
+ assertTrue("Exception actualType as TestBean.class", TestBean.class.isAssignableFrom(ex.getActualType()));
+ }
+ catch (Exception ex) {
+ ex.printStackTrace();
+ fail("Shouldn't throw exception on getting valid instance");
+ }
+ }
+
+ public void testSharedInstancesAreEqual() {
+ try {
+ Object o = getBeanFactory().getBean("rod");
+ assertTrue("Rod bean1 is a TestBean", o instanceof TestBean);
+ Object o1 = getBeanFactory().getBean("rod");
+ assertTrue("Rod bean2 is a TestBean", o1 instanceof TestBean);
+ assertTrue("Object equals applies", o == o1);
+ }
+ catch (Exception ex) {
+ ex.printStackTrace();
+ fail("Shouldn't throw exception on getting valid instance");
+ }
+ }
+
+ public void testPrototypeInstancesAreIndependent() {
+ TestBean tb1 = (TestBean) getBeanFactory().getBean("kathy");
+ TestBean tb2 = (TestBean) getBeanFactory().getBean("kathy");
+ assertTrue("ref equal DOES NOT apply", tb1 != tb2);
+ assertTrue("object equal true", tb1.equals(tb2));
+ tb1.setAge(1);
+ tb2.setAge(2);
+ assertTrue("1 age independent = 1", tb1.getAge() == 1);
+ assertTrue("2 age independent = 2", tb2.getAge() == 2);
+ assertTrue("object equal now false", !tb1.equals(tb2));
+ }
+
+ public void testNotThere() {
+ assertFalse(getBeanFactory().containsBean("Mr Squiggle"));
+ try {
+ Object o = getBeanFactory().getBean("Mr Squiggle");
+ fail("Can't find missing bean");
+ }
+ catch (BeansException ex) {
+ //ex.printStackTrace();
+ //fail("Shouldn't throw exception on getting valid instance");
+ }
+ }
+
+ public void testValidEmpty() {
+ try {
+ Object o = getBeanFactory().getBean("validEmpty");
+ assertTrue("validEmpty bean is a TestBean", o instanceof TestBean);
+ TestBean ve = (TestBean) o;
+ assertTrue("Valid empty has defaults", ve.getName() == null && ve.getAge() == 0 && ve.getSpouse() == null);
+ }
+ catch (BeansException ex) {
+ ex.printStackTrace();
+ fail("Shouldn't throw exception on valid empty");
+ }
+ }
+
+ public void xtestTypeMismatch() {
+ try {
+ Object o = getBeanFactory().getBean("typeMismatch");
+ fail("Shouldn't succeed with type mismatch");
+ }
+ catch (BeanCreationException wex) {
+ assertEquals("typeMismatch", wex.getBeanName());
+ assertTrue(wex.getCause() instanceof PropertyBatchUpdateException);
+ PropertyBatchUpdateException ex = (PropertyBatchUpdateException) wex.getCause();
+ // Further tests
+ assertTrue("Has one error ", ex.getExceptionCount() == 1);
+ assertTrue("Error is for field age", ex.getPropertyAccessException("age") != null);
+ assertTrue("We have rejected age in exception", ex.getPropertyAccessException("age").getPropertyChangeEvent().getNewValue().equals("34x"));
+ }
+ }
+
+ public void testGrandparentDefinitionFoundInBeanFactory() throws Exception {
+ TestBean dad = (TestBean) getBeanFactory().getBean("father");
+ assertTrue("Dad has correct name", dad.getName().equals("Albert"));
+ }
+
+ public void testFactorySingleton() throws Exception {
+ assertTrue(getBeanFactory().isSingleton("&singletonFactory"));
+ assertTrue(getBeanFactory().isSingleton("singletonFactory"));
+ TestBean tb = (TestBean) getBeanFactory().getBean("singletonFactory");
+ assertTrue("Singleton from factory has correct name, not " + tb.getName(), tb.getName().equals(DummyFactory.SINGLETON_NAME));
+ DummyFactory factory = (DummyFactory) getBeanFactory().getBean("&singletonFactory");
+ TestBean tb2 = (TestBean) getBeanFactory().getBean("singletonFactory");
+ assertTrue("Singleton references ==", tb == tb2);
+ assertTrue("FactoryBean is BeanFactoryAware", factory.getBeanFactory() != null);
+ }
+
+ public void testFactoryPrototype() throws Exception {
+ assertTrue(getBeanFactory().isSingleton("&prototypeFactory"));
+ assertFalse(getBeanFactory().isSingleton("prototypeFactory"));
+ TestBean tb = (TestBean) getBeanFactory().getBean("prototypeFactory");
+ assertTrue(!tb.getName().equals(DummyFactory.SINGLETON_NAME));
+ TestBean tb2 = (TestBean) getBeanFactory().getBean("prototypeFactory");
+ assertTrue("Prototype references !=", tb != tb2);
+ }
+
+ /**
+ * Check that we can get the factory bean itself.
+ * This is only possible if we're dealing with a factory
+ * @throws Exception
+ */
+ public void testGetFactoryItself() throws Exception {
+ DummyFactory factory = (DummyFactory) getBeanFactory().getBean("&singletonFactory");
+ assertTrue(factory != null);
+ }
+
+ /**
+ * Check that afterPropertiesSet gets called on factory
+ * @throws Exception
+ */
+ public void testFactoryIsInitialized() throws Exception {
+ TestBean tb = (TestBean) getBeanFactory().getBean("singletonFactory");
+ DummyFactory factory = (DummyFactory) getBeanFactory().getBean("&singletonFactory");
+ assertTrue("Factory was initialized because it implemented InitializingBean", factory.wasInitialized());
+ }
+
+ /**
+ * It should be illegal to dereference a normal bean
+ * as a factory
+ */
+ public void testRejectsFactoryGetOnNormalBean() {
+ try {
+ getBeanFactory().getBean("&rod");
+ fail("Shouldn't permit factory get on normal bean");
+ }
+ catch (BeanIsNotAFactoryException ex) {
+ // Ok
+ }
+ }
+
+ // TODO: refactor in AbstractBeanFactory (tests for AbstractBeanFactory)
+ // and rename this class
+ public void testAliasing() {
+ BeanFactory bf = getBeanFactory();
+ if (!(bf instanceof ConfigurableBeanFactory)) {
+ return;
+ }
+ ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) bf;
+
+ String alias = "rods alias";
+ try {
+ cbf.getBean(alias);
+ fail("Shouldn't permit factory get on normal bean");
+ }
+ catch (NoSuchBeanDefinitionException ex) {
+ // Ok
+ assertTrue(alias.equals(ex.getBeanName()));
+ }
+
+ // Create alias
+ cbf.registerAlias("rod", alias);
+ Object rod = getBeanFactory().getBean("rod");
+ Object aliasRod = getBeanFactory().getBean(alias);
+ assertTrue(rod == aliasRod);
+ }
+
+
+ public static class TestBeanEditor extends PropertyEditorSupport {
+
+ public void setAsText(String text) {
+ TestBean tb = new TestBean();
+ StringTokenizer st = new StringTokenizer(text, "_");
+ tb.setName(st.nextToken());
+ tb.setAge(Integer.parseInt(st.nextToken()));
+ setValue(tb);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/AbstractListableBeanFactoryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/AbstractListableBeanFactoryTests.java
new file mode 100644
index 00000000000..0230237cd9c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/AbstractListableBeanFactoryTests.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory;
+
+import org.springframework.beans.TestBean;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public abstract class AbstractListableBeanFactoryTests extends AbstractBeanFactoryTests {
+
+ /** Subclasses must initialize this */
+ protected ListableBeanFactory getListableBeanFactory() {
+ BeanFactory bf = getBeanFactory();
+ if (!(bf instanceof ListableBeanFactory)) {
+ throw new IllegalStateException("ListableBeanFactory required");
+ }
+ return (ListableBeanFactory) bf;
+ }
+
+ /**
+ * Subclasses can override this.
+ */
+ public void testCount() {
+ assertCount(13);
+ }
+
+ protected final void assertCount(int count) {
+ String[] defnames = getListableBeanFactory().getBeanDefinitionNames();
+ assertTrue("We should have " + count + " beans, not " + defnames.length, defnames.length == count);
+ }
+
+ public void assertTestBeanCount(int count) {
+ String[] defNames = getListableBeanFactory().getBeanNamesForType(TestBean.class, true, false);
+ assertTrue("We should have " + count + " beans for class org.springframework.beans.TestBean, not " +
+ defNames.length, defNames.length == count);
+
+ int countIncludingFactoryBeans = count + 2;
+ String[] names = getListableBeanFactory().getBeanNamesForType(TestBean.class, true, true);
+ assertTrue("We should have " + countIncludingFactoryBeans +
+ " beans for class org.springframework.beans.TestBean, not " + names.length,
+ names.length == countIncludingFactoryBeans);
+ }
+
+ public void testGetDefinitionsForNoSuchClass() {
+ String[] defnames = getListableBeanFactory().getBeanNamesForType(String.class);
+ assertTrue("No string definitions", defnames.length == 0);
+ }
+
+ /**
+ * Check that count refers to factory class, not bean class. (We don't know
+ * what type factories may return, and it may even change over time.)
+ */
+ public void testGetCountForFactoryClass() {
+ assertTrue("Should have 2 factories, not " +
+ getListableBeanFactory().getBeanNamesForType(FactoryBean.class).length,
+ getListableBeanFactory().getBeanNamesForType(FactoryBean.class).length == 2);
+
+ assertTrue("Should have 2 factories, not " +
+ getListableBeanFactory().getBeanNamesForType(FactoryBean.class).length,
+ getListableBeanFactory().getBeanNamesForType(FactoryBean.class).length == 2);
+ }
+
+ public void testContainsBeanDefinition() {
+ assertTrue(getListableBeanFactory().containsBeanDefinition("rod"));
+ assertTrue(getListableBeanFactory().containsBeanDefinition("roderick"));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/BeanFactoryUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/BeanFactoryUtilsTests.java
new file mode 100644
index 00000000000..bd5240cc828
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/BeanFactoryUtilsTests.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.IndexedTestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.support.StaticListableBeanFactory;
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.util.ObjectUtils;
+import org.springframework.web.servlet.HandlerAdapter;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @since 04.07.2003
+ */
+public class BeanFactoryUtilsTests extends TestCase {
+
+ private ConfigurableListableBeanFactory listableBeanFactory;
+
+ private ConfigurableListableBeanFactory dependentBeansBF;
+
+ protected void setUp() {
+ // Interesting hierarchical factory to test counts.
+ // Slow to read so we cache it.
+ XmlBeanFactory grandParent = new XmlBeanFactory(new ClassPathResource("root.xml", getClass()));
+ XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("middle.xml", getClass()), grandParent);
+ XmlBeanFactory child = new XmlBeanFactory(new ClassPathResource("leaf.xml", getClass()), parent);
+ this.dependentBeansBF = new XmlBeanFactory(new ClassPathResource("dependentBeans.xml", getClass()));
+ dependentBeansBF.preInstantiateSingletons();
+ this.listableBeanFactory = child;
+ }
+
+ public void testHierarchicalCountBeansWithNonHierarchicalFactory() {
+ StaticListableBeanFactory lbf = new StaticListableBeanFactory();
+ lbf.addBean("t1", new TestBean());
+ lbf.addBean("t2", new TestBean());
+ assertTrue(BeanFactoryUtils.countBeansIncludingAncestors(lbf) == 2);
+ }
+
+ /**
+ * Check that override doesn't count as two separate beans.
+ */
+ public void testHierarchicalCountBeansWithOverride() throws Exception {
+ // Leaf count
+ assertTrue(this.listableBeanFactory.getBeanDefinitionCount() == 1);
+ // Count minus duplicate
+ assertTrue("Should count 7 beans, not "
+ + BeanFactoryUtils.countBeansIncludingAncestors(this.listableBeanFactory),
+ BeanFactoryUtils.countBeansIncludingAncestors(this.listableBeanFactory) == 7);
+ }
+
+ public void testHierarchicalNamesWithNoMatch() throws Exception {
+ List names = Arrays.asList(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory,
+ HandlerAdapter.class));
+ assertEquals(0, names.size());
+ }
+
+ public void testHierarchicalNamesWithMatchOnlyInRoot() throws Exception {
+ List names = Arrays.asList(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory,
+ IndexedTestBean.class));
+ assertEquals(1, names.size());
+ assertTrue(names.contains("indexedBean"));
+ // Distinguish from default ListableBeanFactory behavior
+ assertTrue(listableBeanFactory.getBeanNamesForType(IndexedTestBean.class).length == 0);
+ }
+
+ public void testGetBeanNamesForTypeWithOverride() throws Exception {
+ List names = Arrays.asList(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.listableBeanFactory,
+ ITestBean.class));
+ // includes 2 TestBeans from FactoryBeans (DummyFactory definitions)
+ assertEquals(4, names.size());
+ assertTrue(names.contains("test"));
+ assertTrue(names.contains("test3"));
+ assertTrue(names.contains("testFactory1"));
+ assertTrue(names.contains("testFactory2"));
+ }
+
+ public void testNoBeansOfType() {
+ StaticListableBeanFactory lbf = new StaticListableBeanFactory();
+ lbf.addBean("foo", new Object());
+ Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf, ITestBean.class, true, false);
+ assertTrue(beans.isEmpty());
+ }
+
+ public void testFindsBeansOfTypeWithStaticFactory() {
+ StaticListableBeanFactory lbf = new StaticListableBeanFactory();
+ TestBean t1 = new TestBean();
+ TestBean t2 = new TestBean();
+ DummyFactory t3 = new DummyFactory();
+ DummyFactory t4 = new DummyFactory();
+ t4.setSingleton(false);
+ lbf.addBean("t1", t1);
+ lbf.addBean("t2", t2);
+ lbf.addBean("t3", t3);
+ lbf.addBean("t4", t4);
+
+ Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf, ITestBean.class, true, false);
+ assertEquals(2, beans.size());
+ assertEquals(t1, beans.get("t1"));
+ assertEquals(t2, beans.get("t2"));
+
+ beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf, ITestBean.class, false, true);
+ assertEquals(3, beans.size());
+ assertEquals(t1, beans.get("t1"));
+ assertEquals(t2, beans.get("t2"));
+ assertEquals(t3.getObject(), beans.get("t3"));
+
+ beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf, ITestBean.class, true, true);
+ assertEquals(4, beans.size());
+ assertEquals(t1, beans.get("t1"));
+ assertEquals(t2, beans.get("t2"));
+ assertEquals(t3.getObject(), beans.get("t3"));
+ assertTrue(beans.get("t4") instanceof TestBean);
+
+ beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf, DummyFactory.class, true, true);
+ assertEquals(2, beans.size());
+ assertEquals(t3, beans.get("&t3"));
+ assertEquals(t4, beans.get("&t4"));
+
+ beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(lbf, FactoryBean.class, true, true);
+ assertEquals(2, beans.size());
+ assertEquals(t3, beans.get("&t3"));
+ assertEquals(t4, beans.get("&t4"));
+ }
+
+ public void testFindsBeansOfTypeWithDefaultFactory() {
+ Object test3 = this.listableBeanFactory.getBean("test3");
+ Object test = this.listableBeanFactory.getBean("test");
+
+ TestBean t1 = new TestBean();
+ TestBean t2 = new TestBean();
+ DummyFactory t3 = new DummyFactory();
+ DummyFactory t4 = new DummyFactory();
+ t4.setSingleton(false);
+ this.listableBeanFactory.registerSingleton("t1", t1);
+ this.listableBeanFactory.registerSingleton("t2", t2);
+ this.listableBeanFactory.registerSingleton("t3", t3);
+ this.listableBeanFactory.registerSingleton("t4", t4);
+
+ Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, ITestBean.class, true,
+ false);
+ assertEquals(6, beans.size());
+ assertEquals(test3, beans.get("test3"));
+ assertEquals(test, beans.get("test"));
+ assertEquals(t1, beans.get("t1"));
+ assertEquals(t2, beans.get("t2"));
+ assertEquals(t3.getObject(), beans.get("t3"));
+ assertTrue(beans.get("t4") instanceof TestBean);
+ // t3 and t4 are found here as of Spring 2.0, since they are
+ // pre-registered
+ // singleton instances, while testFactory1 and testFactory are *not*
+ // found
+ // because they are FactoryBean definitions that haven't been
+ // initialized yet.
+
+ beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, ITestBean.class, false, true);
+ Object testFactory1 = this.listableBeanFactory.getBean("testFactory1");
+ assertEquals(5, beans.size());
+ assertEquals(test, beans.get("test"));
+ assertEquals(testFactory1, beans.get("testFactory1"));
+ assertEquals(t1, beans.get("t1"));
+ assertEquals(t2, beans.get("t2"));
+ assertEquals(t3.getObject(), beans.get("t3"));
+
+ beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, ITestBean.class, true, true);
+ assertEquals(8, beans.size());
+ assertEquals(test3, beans.get("test3"));
+ assertEquals(test, beans.get("test"));
+ assertEquals(testFactory1, beans.get("testFactory1"));
+ assertTrue(beans.get("testFactory2") instanceof TestBean);
+ assertEquals(t1, beans.get("t1"));
+ assertEquals(t2, beans.get("t2"));
+ assertEquals(t3.getObject(), beans.get("t3"));
+ assertTrue(beans.get("t4") instanceof TestBean);
+
+ beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, DummyFactory.class, true, true);
+ assertEquals(4, beans.size());
+ assertEquals(this.listableBeanFactory.getBean("&testFactory1"), beans.get("&testFactory1"));
+ assertEquals(this.listableBeanFactory.getBean("&testFactory2"), beans.get("&testFactory2"));
+ assertEquals(t3, beans.get("&t3"));
+ assertEquals(t4, beans.get("&t4"));
+
+ beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, FactoryBean.class, true, true);
+ assertEquals(4, beans.size());
+ assertEquals(this.listableBeanFactory.getBean("&testFactory1"), beans.get("&testFactory1"));
+ assertEquals(this.listableBeanFactory.getBean("&testFactory2"), beans.get("&testFactory2"));
+ assertEquals(t3, beans.get("&t3"));
+ assertEquals(t4, beans.get("&t4"));
+ }
+
+ public void testHierarchicalResolutionWithOverride() throws Exception {
+ Object test3 = this.listableBeanFactory.getBean("test3");
+ Object test = this.listableBeanFactory.getBean("test");
+
+ Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, ITestBean.class, true,
+ false);
+ assertEquals(2, beans.size());
+ assertEquals(test3, beans.get("test3"));
+ assertEquals(test, beans.get("test"));
+
+ beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, ITestBean.class, false, false);
+ assertEquals(1, beans.size());
+ assertEquals(test, beans.get("test"));
+
+ beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, ITestBean.class, false, true);
+ Object testFactory1 = this.listableBeanFactory.getBean("testFactory1");
+ assertEquals(2, beans.size());
+ assertEquals(test, beans.get("test"));
+ assertEquals(testFactory1, beans.get("testFactory1"));
+
+ beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, ITestBean.class, true, true);
+ assertEquals(4, beans.size());
+ assertEquals(test3, beans.get("test3"));
+ assertEquals(test, beans.get("test"));
+ assertEquals(testFactory1, beans.get("testFactory1"));
+ assertTrue(beans.get("testFactory2") instanceof TestBean);
+
+ beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, DummyFactory.class, true, true);
+ assertEquals(2, beans.size());
+ assertEquals(this.listableBeanFactory.getBean("&testFactory1"), beans.get("&testFactory1"));
+ assertEquals(this.listableBeanFactory.getBean("&testFactory2"), beans.get("&testFactory2"));
+
+ beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.listableBeanFactory, FactoryBean.class, true, true);
+ assertEquals(2, beans.size());
+ assertEquals(this.listableBeanFactory.getBean("&testFactory1"), beans.get("&testFactory1"));
+ assertEquals(this.listableBeanFactory.getBean("&testFactory2"), beans.get("&testFactory2"));
+ }
+
+ public void testADependencies() {
+ String[] deps = this.dependentBeansBF.getDependentBeans("a");
+ assertTrue(ObjectUtils.isEmpty(deps));
+ }
+
+ public void testBDependencies() {
+ String[] deps = this.dependentBeansBF.getDependentBeans("b");
+ assertTrue(Arrays.equals(new String[] { "c" }, deps));
+ }
+
+ public void testCDependencies() {
+ String[] deps = this.dependentBeansBF.getDependentBeans("c");
+ assertTrue(Arrays.equals(new String[] { "int", "long" }, deps));
+ }
+
+ public void testIntDependencies() {
+ String[] deps = this.dependentBeansBF.getDependentBeans("int");
+ assertTrue(Arrays.equals(new String[] { "buffer" }, deps));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/ConcurrentBeanFactoryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/ConcurrentBeanFactoryTests.java
new file mode 100644
index 00000000000..81ab7fe5ff4
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/ConcurrentBeanFactoryTests.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import junit.framework.TestCase;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.beans.propertyeditors.CustomDateEditor;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Guillaume Poirier
+ * @author Juergen Hoeller
+ * @since 10.03.2004
+ */
+public class ConcurrentBeanFactoryTests extends TestCase {
+
+ private static final Log logger = LogFactory.getLog(ConcurrentBeanFactoryTests.class);
+
+ private static final SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd");
+
+ private static final Date date1;
+
+ private static final Date date2;
+
+ static {
+ try {
+ date1 = df.parse("2004/08/08");
+ date2 = df.parse("2000/02/02");
+ }
+ catch (ParseException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private BeanFactory factory;
+
+ private Set set = Collections.synchronizedSet(new HashSet());
+
+ private Throwable ex = null;
+
+ protected void setUp() throws Exception {
+ XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("concurrent.xml", getClass()));
+ CustomDateEditor editor = new CustomDateEditor(df, false);
+ factory.registerCustomEditor(Date.class, editor);
+ this.factory = factory;
+ }
+
+ public void testSingleThread() {
+ for (int i = 0; i < 100; i++) {
+ performTest();
+ }
+ }
+
+ public void testConcurrent() {
+ for (int i = 0; i < 100; i++) {
+ TestRun run = new TestRun();
+ run.setDaemon(true);
+ set.add(run);
+ }
+ for (Iterator it = new HashSet(set).iterator(); it.hasNext();) {
+ TestRun run = (TestRun) it.next();
+ run.start();
+ }
+ logger.info("Thread creation over, " + set.size() + " still active.");
+ synchronized (set) {
+ while (!set.isEmpty() && ex == null) {
+ try {
+ set.wait();
+ }
+ catch (InterruptedException e) {
+ logger.info(e.toString());
+ }
+ logger.info(set.size() + " threads still active.");
+ }
+ }
+ if (ex != null) {
+ fail(ex.getMessage());
+ }
+ }
+
+ private void performTest() {
+ ConcurrentBean b1 = (ConcurrentBean) factory.getBean("bean1");
+ ConcurrentBean b2 = (ConcurrentBean) factory.getBean("bean2");
+
+ assertEquals(b1.getDate(), date1);
+ assertEquals(b2.getDate(), date2);
+ }
+
+
+ private class TestRun extends Thread {
+
+ public void run() {
+ try {
+ for (int i = 0; i < 10000; i++) {
+ performTest();
+ }
+ }
+ catch (Throwable e) {
+ ex = e;
+ }
+ finally {
+ synchronized (set) {
+ set.remove(this);
+ set.notifyAll();
+ }
+ }
+ }
+ }
+
+
+ public static class ConcurrentBean {
+
+ private Date date;
+
+ public Date getDate() {
+ return date;
+ }
+
+ public void setDate(Date date) {
+ this.date = date;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/CountingFactory.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/CountingFactory.java
new file mode 100644
index 00000000000..147184f2328
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/CountingFactory.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory;
+
+import org.springframework.beans.TestBean;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class CountingFactory implements FactoryBean {
+
+ private static int factoryBeanInstanceCount = 0;
+
+
+ /**
+ * Clear static state.
+ */
+ public static void reset() {
+ factoryBeanInstanceCount = 0;
+ }
+
+ public static int getFactoryBeanInstanceCount() {
+ return factoryBeanInstanceCount;
+ }
+
+
+ public CountingFactory() {
+ factoryBeanInstanceCount++;
+ }
+
+ public void setTestBean(TestBean tb) {
+ if (tb.getSpouse() == null) {
+ throw new IllegalStateException("TestBean needs to have spouse");
+ }
+ }
+
+
+ public Object getObject() {
+ return "myString";
+ }
+
+ public Class getObjectType() {
+ return String.class;
+ }
+
+ public boolean isSingleton() {
+ return true;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java
new file mode 100644
index 00000000000..2b127406e65
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java
@@ -0,0 +1,2239 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.beans.factory;
+
+import java.lang.reflect.Field;
+import java.net.MalformedURLException;
+import java.security.AccessController;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+
+import junit.framework.TestCase;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.aop.interceptor.SideEffectBean;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.DerivedTestBean;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.NestedTestBean;
+import org.springframework.beans.NotWritablePropertyException;
+import org.springframework.beans.PropertyValue;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.TypeConverter;
+import org.springframework.beans.TypeMismatchException;
+import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.beans.factory.config.ConstructorArgumentValues;
+import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
+import org.springframework.beans.factory.support.AbstractBeanFactory;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.ChildBeanDefinition;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.support.ManagedList;
+import org.springframework.beans.factory.support.PropertiesBeanDefinitionReader;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.beans.factory.xml.ConstructorDependenciesBean;
+import org.springframework.beans.factory.xml.DependenciesBean;
+import org.springframework.beans.propertyeditors.CustomNumberEditor;
+import org.springframework.core.MethodParameter;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.UrlResource;
+import org.springframework.test.AssertThrows;
+import org.springframework.util.StopWatch;
+
+/**
+ * Tests properties population and autowire behavior.
+ *
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ * @author Sam Brannen
+ */
+public class DefaultListableBeanFactoryTests extends TestCase {
+
+ private static final Log factoryLog = LogFactory.getLog(DefaultListableBeanFactory.class);
+
+
+ public void testUnreferencedSingletonWasInstantiated() {
+ KnowsIfInstantiated.clearInstantiationRecord();
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+ p.setProperty("x1.(class)", KnowsIfInstantiated.class.getName());
+ assertTrue("singleton not instantiated", !KnowsIfInstantiated.wasInstantiated());
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+ lbf.preInstantiateSingletons();
+ assertTrue("singleton was instantiated", KnowsIfInstantiated.wasInstantiated());
+ }
+
+ public void testLazyInitialization() {
+ KnowsIfInstantiated.clearInstantiationRecord();
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+ p.setProperty("x1.(class)", KnowsIfInstantiated.class.getName());
+ p.setProperty("x1.(lazy-init)", "true");
+ assertTrue("singleton not instantiated", !KnowsIfInstantiated.wasInstantiated());
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+ assertTrue("singleton not instantiated", !KnowsIfInstantiated.wasInstantiated());
+ lbf.preInstantiateSingletons();
+
+ assertTrue("singleton not instantiated", !KnowsIfInstantiated.wasInstantiated());
+ lbf.getBean("x1");
+ assertTrue("singleton was instantiated", KnowsIfInstantiated.wasInstantiated());
+ }
+
+ public void testFactoryBeanDidNotCreatePrototype() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+ p.setProperty("x1.(class)", DummyFactory.class.getName());
+ // Reset static state
+ DummyFactory.reset();
+ p.setProperty("x1.singleton", "false");
+ assertTrue("prototype not instantiated", !DummyFactory.wasPrototypeCreated());
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+ assertTrue("prototype not instantiated", !DummyFactory.wasPrototypeCreated());
+ assertEquals(TestBean.class, lbf.getType("x1"));
+ lbf.preInstantiateSingletons();
+
+ assertTrue("prototype not instantiated", !DummyFactory.wasPrototypeCreated());
+ lbf.getBean("x1");
+ assertEquals(TestBean.class, lbf.getType("x1"));
+ assertTrue(lbf.containsBean("x1"));
+ assertTrue(lbf.containsBean("&x1"));
+ assertTrue("prototype was instantiated", DummyFactory.wasPrototypeCreated());
+ }
+
+ public void testPrototypeFactoryBeanIgnoredByNonEagerTypeMatching() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+ p.setProperty("x1.(class)", DummyFactory.class.getName());
+ // Reset static state
+ DummyFactory.reset();
+ p.setProperty("x1.(singleton)", "false");
+ p.setProperty("x1.singleton", "false");
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+
+ assertTrue("prototype not instantiated", !DummyFactory.wasPrototypeCreated());
+ String[] beanNames = lbf.getBeanNamesForType(TestBean.class, true, false);
+ assertEquals(0, beanNames.length);
+ assertFalse(lbf.containsSingleton("x1"));
+ assertTrue(lbf.containsBean("x1"));
+ assertTrue(lbf.containsBean("&x1"));
+ assertFalse(lbf.isSingleton("x1"));
+ assertFalse(lbf.isSingleton("&x1"));
+ assertTrue(lbf.isPrototype("x1"));
+ assertTrue(lbf.isPrototype("&x1"));
+ assertTrue(lbf.isTypeMatch("x1", TestBean.class));
+ assertFalse(lbf.isTypeMatch("&x1", TestBean.class));
+ assertTrue(lbf.isTypeMatch("&x1", DummyFactory.class));
+ assertEquals(TestBean.class, lbf.getType("x1"));
+ assertEquals(DummyFactory.class, lbf.getType("&x1"));
+ assertTrue("prototype not instantiated", !DummyFactory.wasPrototypeCreated());
+ }
+
+ public void testPrototypeSingletonFactoryBeanIgnoredByNonEagerTypeMatching() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+ p.setProperty("x1.(class)", DummyFactory.class.getName());
+ // Reset static state
+ DummyFactory.reset();
+ p.setProperty("x1.(singleton)", "false");
+ p.setProperty("x1.singleton", "true");
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+
+ assertTrue("prototype not instantiated", !DummyFactory.wasPrototypeCreated());
+ String[] beanNames = lbf.getBeanNamesForType(TestBean.class, true, false);
+ assertEquals(0, beanNames.length);
+ assertFalse(lbf.containsSingleton("x1"));
+ assertTrue(lbf.containsBean("x1"));
+ assertTrue(lbf.containsBean("&x1"));
+ assertFalse(lbf.isSingleton("x1"));
+ assertFalse(lbf.isSingleton("&x1"));
+ assertTrue(lbf.isPrototype("x1"));
+ assertTrue(lbf.isPrototype("&x1"));
+ assertTrue(lbf.isTypeMatch("x1", TestBean.class));
+ assertFalse(lbf.isTypeMatch("&x1", TestBean.class));
+ assertTrue(lbf.isTypeMatch("&x1", DummyFactory.class));
+ assertEquals(TestBean.class, lbf.getType("x1"));
+ assertEquals(DummyFactory.class, lbf.getType("&x1"));
+ assertTrue("prototype not instantiated", !DummyFactory.wasPrototypeCreated());
+ }
+
+ public void testNonInitializedFactoryBeanIgnoredByNonEagerTypeMatching() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+ p.setProperty("x1.(class)", DummyFactory.class.getName());
+ // Reset static state
+ DummyFactory.reset();
+ p.setProperty("x1.singleton", "false");
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+
+ assertTrue("prototype not instantiated", !DummyFactory.wasPrototypeCreated());
+ String[] beanNames = lbf.getBeanNamesForType(TestBean.class, true, false);
+ assertEquals(0, beanNames.length);
+ assertFalse(lbf.containsSingleton("x1"));
+ assertTrue(lbf.containsBean("x1"));
+ assertTrue(lbf.containsBean("&x1"));
+ assertFalse(lbf.isSingleton("x1"));
+ assertTrue(lbf.isSingleton("&x1"));
+ assertTrue(lbf.isPrototype("x1"));
+ assertFalse(lbf.isPrototype("&x1"));
+ assertTrue(lbf.isTypeMatch("x1", TestBean.class));
+ assertFalse(lbf.isTypeMatch("&x1", TestBean.class));
+ assertTrue(lbf.isTypeMatch("&x1", DummyFactory.class));
+ assertEquals(TestBean.class, lbf.getType("x1"));
+ assertEquals(DummyFactory.class, lbf.getType("&x1"));
+ assertTrue("prototype not instantiated", !DummyFactory.wasPrototypeCreated());
+ }
+
+ public void testInitializedFactoryBeanFoundByNonEagerTypeMatching() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+ p.setProperty("x1.(class)", DummyFactory.class.getName());
+ // Reset static state
+ DummyFactory.reset();
+ p.setProperty("x1.singleton", "false");
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+ lbf.preInstantiateSingletons();
+
+ assertTrue("prototype not instantiated", !DummyFactory.wasPrototypeCreated());
+ String[] beanNames = lbf.getBeanNamesForType(TestBean.class, true, false);
+ assertEquals(1, beanNames.length);
+ assertEquals("x1", beanNames[0]);
+ assertTrue(lbf.containsSingleton("x1"));
+ assertTrue(lbf.containsBean("x1"));
+ assertTrue(lbf.containsBean("&x1"));
+ assertTrue(lbf.containsLocalBean("x1"));
+ assertTrue(lbf.containsLocalBean("&x1"));
+ assertFalse(lbf.isSingleton("x1"));
+ assertTrue(lbf.isSingleton("&x1"));
+ assertTrue(lbf.isPrototype("x1"));
+ assertFalse(lbf.isPrototype("&x1"));
+ assertTrue(lbf.isTypeMatch("x1", TestBean.class));
+ assertFalse(lbf.isTypeMatch("&x1", TestBean.class));
+ assertTrue(lbf.isTypeMatch("&x1", DummyFactory.class));
+ assertTrue(lbf.isTypeMatch("x1", Object.class));
+ assertTrue(lbf.isTypeMatch("&x1", Object.class));
+ assertEquals(TestBean.class, lbf.getType("x1"));
+ assertEquals(DummyFactory.class, lbf.getType("&x1"));
+ assertTrue("prototype not instantiated", !DummyFactory.wasPrototypeCreated());
+
+ lbf.registerAlias("x1", "x2");
+ assertTrue(lbf.containsBean("x2"));
+ assertTrue(lbf.containsBean("&x2"));
+ assertTrue(lbf.containsLocalBean("x2"));
+ assertTrue(lbf.containsLocalBean("&x2"));
+ assertFalse(lbf.isSingleton("x2"));
+ assertTrue(lbf.isSingleton("&x2"));
+ assertTrue(lbf.isPrototype("x2"));
+ assertFalse(lbf.isPrototype("&x2"));
+ assertTrue(lbf.isTypeMatch("x2", TestBean.class));
+ assertFalse(lbf.isTypeMatch("&x2", TestBean.class));
+ assertTrue(lbf.isTypeMatch("&x2", DummyFactory.class));
+ assertTrue(lbf.isTypeMatch("x2", Object.class));
+ assertTrue(lbf.isTypeMatch("&x2", Object.class));
+ assertEquals(TestBean.class, lbf.getType("x2"));
+ assertEquals(DummyFactory.class, lbf.getType("&x2"));
+ assertEquals(1, lbf.getAliases("x1").length);
+ assertEquals("x2", lbf.getAliases("x1")[0]);
+ assertEquals(1, lbf.getAliases("&x1").length);
+ assertEquals("&x2", lbf.getAliases("&x1")[0]);
+ assertEquals(1, lbf.getAliases("x2").length);
+ assertEquals("x1", lbf.getAliases("x2")[0]);
+ assertEquals(1, lbf.getAliases("&x2").length);
+ assertEquals("&x1", lbf.getAliases("&x2")[0]);
+ }
+
+ public void testStaticFactoryMethodFoundByNonEagerTypeMatching() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition rbd = new RootBeanDefinition(TestBeanFactory.class);
+ rbd.setFactoryMethodName("createTestBean");
+ lbf.registerBeanDefinition("x1", rbd);
+
+ TestBeanFactory.initialized = false;
+ String[] beanNames = lbf.getBeanNamesForType(TestBean.class, true, false);
+ assertEquals(1, beanNames.length);
+ assertEquals("x1", beanNames[0]);
+ assertFalse(lbf.containsSingleton("x1"));
+ assertTrue(lbf.containsBean("x1"));
+ assertFalse(lbf.containsBean("&x1"));
+ assertTrue(lbf.isSingleton("x1"));
+ assertFalse(lbf.isSingleton("&x1"));
+ assertFalse(lbf.isPrototype("x1"));
+ assertFalse(lbf.isPrototype("&x1"));
+ assertTrue(lbf.isTypeMatch("x1", TestBean.class));
+ assertFalse(lbf.isTypeMatch("&x1", TestBean.class));
+ assertEquals(TestBean.class, lbf.getType("x1"));
+ assertEquals(null, lbf.getType("&x1"));
+ assertFalse(TestBeanFactory.initialized);
+ }
+
+ public void testStaticPrototypeFactoryMethodFoundByNonEagerTypeMatching() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition rbd = new RootBeanDefinition(TestBeanFactory.class);
+ rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
+ rbd.setFactoryMethodName("createTestBean");
+ lbf.registerBeanDefinition("x1", rbd);
+
+ TestBeanFactory.initialized = false;
+ String[] beanNames = lbf.getBeanNamesForType(TestBean.class, true, false);
+ assertEquals(1, beanNames.length);
+ assertEquals("x1", beanNames[0]);
+ assertFalse(lbf.containsSingleton("x1"));
+ assertTrue(lbf.containsBean("x1"));
+ assertFalse(lbf.containsBean("&x1"));
+ assertFalse(lbf.isSingleton("x1"));
+ assertFalse(lbf.isSingleton("&x1"));
+ assertTrue(lbf.isPrototype("x1"));
+ assertFalse(lbf.isPrototype("&x1"));
+ assertTrue(lbf.isTypeMatch("x1", TestBean.class));
+ assertFalse(lbf.isTypeMatch("&x1", TestBean.class));
+ assertEquals(TestBean.class, lbf.getType("x1"));
+ assertEquals(null, lbf.getType("&x1"));
+ assertFalse(TestBeanFactory.initialized);
+ }
+
+ public void testNonStaticFactoryMethodFoundByNonEagerTypeMatching() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition factoryBd = new RootBeanDefinition(TestBeanFactory.class);
+ lbf.registerBeanDefinition("factory", factoryBd);
+ RootBeanDefinition rbd = new RootBeanDefinition(TestBeanFactory.class);
+ rbd.setFactoryBeanName("factory");
+ rbd.setFactoryMethodName("createTestBeanNonStatic");
+ lbf.registerBeanDefinition("x1", rbd);
+
+ TestBeanFactory.initialized = false;
+ String[] beanNames = lbf.getBeanNamesForType(TestBean.class, true, false);
+ assertEquals(1, beanNames.length);
+ assertEquals("x1", beanNames[0]);
+ assertFalse(lbf.containsSingleton("x1"));
+ assertTrue(lbf.containsBean("x1"));
+ assertFalse(lbf.containsBean("&x1"));
+ assertTrue(lbf.isSingleton("x1"));
+ assertFalse(lbf.isSingleton("&x1"));
+ assertFalse(lbf.isPrototype("x1"));
+ assertFalse(lbf.isPrototype("&x1"));
+ assertTrue(lbf.isTypeMatch("x1", TestBean.class));
+ assertFalse(lbf.isTypeMatch("&x1", TestBean.class));
+ assertEquals(TestBean.class, lbf.getType("x1"));
+ assertEquals(null, lbf.getType("&x1"));
+ assertFalse(TestBeanFactory.initialized);
+ }
+
+ public void testNonStaticPrototypeFactoryMethodFoundByNonEagerTypeMatching() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition factoryBd = new RootBeanDefinition(TestBeanFactory.class);
+ lbf.registerBeanDefinition("factory", factoryBd);
+ RootBeanDefinition rbd = new RootBeanDefinition();
+ rbd.setFactoryBeanName("factory");
+ rbd.setFactoryMethodName("createTestBeanNonStatic");
+ rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
+ lbf.registerBeanDefinition("x1", rbd);
+
+ TestBeanFactory.initialized = false;
+ String[] beanNames = lbf.getBeanNamesForType(TestBean.class, true, false);
+ assertEquals(1, beanNames.length);
+ assertEquals("x1", beanNames[0]);
+ assertFalse(lbf.containsSingleton("x1"));
+ assertTrue(lbf.containsBean("x1"));
+ assertFalse(lbf.containsBean("&x1"));
+ assertTrue(lbf.containsLocalBean("x1"));
+ assertFalse(lbf.containsLocalBean("&x1"));
+ assertFalse(lbf.isSingleton("x1"));
+ assertFalse(lbf.isSingleton("&x1"));
+ assertTrue(lbf.isPrototype("x1"));
+ assertFalse(lbf.isPrototype("&x1"));
+ assertTrue(lbf.isTypeMatch("x1", TestBean.class));
+ assertFalse(lbf.isTypeMatch("&x1", TestBean.class));
+ assertTrue(lbf.isTypeMatch("x1", Object.class));
+ assertFalse(lbf.isTypeMatch("&x1", Object.class));
+ assertEquals(TestBean.class, lbf.getType("x1"));
+ assertEquals(null, lbf.getType("&x1"));
+ assertFalse(TestBeanFactory.initialized);
+
+ lbf.registerAlias("x1", "x2");
+ assertTrue(lbf.containsBean("x2"));
+ assertFalse(lbf.containsBean("&x2"));
+ assertTrue(lbf.containsLocalBean("x2"));
+ assertFalse(lbf.containsLocalBean("&x2"));
+ assertFalse(lbf.isSingleton("x2"));
+ assertFalse(lbf.isSingleton("&x2"));
+ assertTrue(lbf.isPrototype("x2"));
+ assertFalse(lbf.isPrototype("&x2"));
+ assertTrue(lbf.isTypeMatch("x2", TestBean.class));
+ assertFalse(lbf.isTypeMatch("&x2", TestBean.class));
+ assertTrue(lbf.isTypeMatch("x2", Object.class));
+ assertFalse(lbf.isTypeMatch("&x2", Object.class));
+ assertEquals(TestBean.class, lbf.getType("x2"));
+ assertEquals(null, lbf.getType("&x2"));
+ assertEquals(1, lbf.getAliases("x1").length);
+ assertEquals("x2", lbf.getAliases("x1")[0]);
+ assertEquals(1, lbf.getAliases("&x1").length);
+ assertEquals("&x2", lbf.getAliases("&x1")[0]);
+ assertEquals(1, lbf.getAliases("x2").length);
+ assertEquals("x1", lbf.getAliases("x2")[0]);
+ assertEquals(1, lbf.getAliases("&x2").length);
+ assertEquals("&x1", lbf.getAliases("&x2")[0]);
+ }
+
+ public void testEmpty() {
+ ListableBeanFactory lbf = new DefaultListableBeanFactory();
+ assertTrue("No beans defined --> array != null", lbf.getBeanDefinitionNames() != null);
+ assertTrue("No beans defined after no arg constructor", lbf.getBeanDefinitionNames().length == 0);
+ assertTrue("No beans defined after no arg constructor", lbf.getBeanDefinitionCount() == 0);
+ }
+
+ public void testEmptyPropertiesPopulation() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+ assertTrue("No beans defined after ignorable invalid", lbf.getBeanDefinitionCount() == 0);
+ }
+
+ public void testHarmlessIgnorableRubbish() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+ p.setProperty("foo", "bar");
+ p.setProperty("qwert", "er");
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p, "test");
+ assertTrue("No beans defined after harmless ignorable rubbish", lbf.getBeanDefinitionCount() == 0);
+ }
+
+ public void testPropertiesPopulationWithNullPrefix() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+ p.setProperty("test.(class)", "org.springframework.beans.TestBean");
+ p.setProperty("test.name", "Tony");
+ p.setProperty("test.age", "48");
+ int count = (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+ assertTrue("1 beans registered, not " + count, count == 1);
+ testSingleTestBean(lbf);
+ }
+
+ public void testPropertiesPopulationWithPrefix() {
+ String PREFIX = "beans.";
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+ p.setProperty(PREFIX + "test.(class)", "org.springframework.beans.TestBean");
+ p.setProperty(PREFIX + "test.name", "Tony");
+ p.setProperty(PREFIX + "test.age", "0x30");
+ int count = (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p, PREFIX);
+ assertTrue("1 beans registered, not " + count, count == 1);
+ testSingleTestBean(lbf);
+ }
+
+ public void testSimpleReference() {
+ String PREFIX = "beans.";
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+
+ p.setProperty(PREFIX + "rod.(class)", "org.springframework.beans.TestBean");
+ p.setProperty(PREFIX + "rod.name", "Rod");
+
+ p.setProperty(PREFIX + "kerry.(class)", "org.springframework.beans.TestBean");
+ p.setProperty(PREFIX + "kerry.name", "Kerry");
+ p.setProperty(PREFIX + "kerry.age", "35");
+ p.setProperty(PREFIX + "kerry.spouse(ref)", "rod");
+
+ int count = (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p, PREFIX);
+ assertTrue("2 beans registered, not " + count, count == 2);
+
+ TestBean kerry = (TestBean) lbf.getBean("kerry", TestBean.class);
+ assertTrue("Kerry name is Kerry", "Kerry".equals(kerry.getName()));
+ ITestBean spouse = kerry.getSpouse();
+ assertTrue("Kerry spouse is non null", spouse != null);
+ assertTrue("Kerry spouse name is Rod", "Rod".equals(spouse.getName()));
+ }
+
+ public void testPropertiesWithDotsInKey() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+
+ p.setProperty("tb.(class)", "org.springframework.beans.TestBean");
+ p.setProperty("tb.someMap[my.key]", "my.value");
+
+ int count = (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+ assertTrue("1 beans registered, not " + count, count == 1);
+ assertEquals(1, lbf.getBeanDefinitionCount());
+
+ TestBean tb = (TestBean) lbf.getBean("tb", TestBean.class);
+ assertEquals("my.value", tb.getSomeMap().get("my.key"));
+ }
+
+ public void testUnresolvedReference() {
+ String PREFIX = "beans.";
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+
+ try {
+ p.setProperty(PREFIX + "kerry.(class)", "org.springframework.beans.TestBean");
+ p.setProperty(PREFIX + "kerry.name", "Kerry");
+ p.setProperty(PREFIX + "kerry.age", "35");
+ p.setProperty(PREFIX + "kerry.spouse(ref)", "rod");
+
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p, PREFIX);
+
+ lbf.getBean("kerry");
+ fail("Unresolved reference should have been detected");
+ }
+ catch (BeansException ex) {
+ // cool
+ }
+ }
+
+ public void testSelfReference() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("spouse", new RuntimeBeanReference("self"));
+ lbf.registerBeanDefinition("self", new RootBeanDefinition(TestBean.class, pvs));
+ TestBean self = (TestBean) lbf.getBean("self");
+ assertEquals(self, self.getSpouse());
+ }
+
+ public void testPossibleMatches() {
+ try {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("ag", "foobar");
+ lbf.registerBeanDefinition("tb", new RootBeanDefinition(TestBean.class, pvs));
+ lbf.getBean("tb");
+ fail("Should throw exception on invalid property");
+ }
+ catch (BeanCreationException ex) {
+ ex.printStackTrace();
+ assertTrue(ex.getCause() instanceof NotWritablePropertyException);
+ NotWritablePropertyException cause = (NotWritablePropertyException) ex.getCause();
+ // expected
+ assertEquals(1, cause.getPossibleMatches().length);
+ assertEquals("age", cause.getPossibleMatches()[0]);
+ }
+ }
+
+ public void testPrototype() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+ p.setProperty("kerry.(class)", "org.springframework.beans.TestBean");
+ p.setProperty("kerry.age", "35");
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+ TestBean kerry1 = (TestBean) lbf.getBean("kerry");
+ TestBean kerry2 = (TestBean) lbf.getBean("kerry");
+ assertTrue("Non null", kerry1 != null);
+ assertTrue("Singletons equal", kerry1 == kerry2);
+
+ lbf = new DefaultListableBeanFactory();
+ p = new Properties();
+ p.setProperty("kerry.(class)", "org.springframework.beans.TestBean");
+ p.setProperty("kerry.(scope)", "prototype");
+ p.setProperty("kerry.age", "35");
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+ kerry1 = (TestBean) lbf.getBean("kerry");
+ kerry2 = (TestBean) lbf.getBean("kerry");
+ assertTrue("Non null", kerry1 != null);
+ assertTrue("Prototypes NOT equal", kerry1 != kerry2);
+
+ lbf = new DefaultListableBeanFactory();
+ p = new Properties();
+ p.setProperty("kerry.(class)", "org.springframework.beans.TestBean");
+ p.setProperty("kerry.(scope)", "singleton");
+ p.setProperty("kerry.age", "35");
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+ kerry1 = (TestBean) lbf.getBean("kerry");
+ kerry2 = (TestBean) lbf.getBean("kerry");
+ assertTrue("Non null", kerry1 != null);
+ assertTrue("Specified singletons equal", kerry1 == kerry2);
+ }
+
+ public void testPrototypeCircleLeadsToException() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+ p.setProperty("kerry.(class)", "org.springframework.beans.TestBean");
+ p.setProperty("kerry.(singleton)", "false");
+ p.setProperty("kerry.age", "35");
+ p.setProperty("kerry.spouse", "*rod");
+ p.setProperty("rod.(class)", "org.springframework.beans.TestBean");
+ p.setProperty("rod.(singleton)", "false");
+ p.setProperty("rod.age", "34");
+ p.setProperty("rod.spouse", "*kerry");
+
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+ try {
+ lbf.getBean("kerry");
+ fail("Should have thrown BeanCreationException");
+ }
+ catch (BeanCreationException ex) {
+ // expected
+ assertTrue(ex.contains(BeanCurrentlyInCreationException.class));
+ }
+ }
+
+ public void testPrototypeExtendsPrototype() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+ p.setProperty("wife.(class)", "org.springframework.beans.TestBean");
+ p.setProperty("wife.name", "kerry");
+
+ p.setProperty("kerry.(parent)", "wife");
+ p.setProperty("kerry.age", "35");
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+ TestBean kerry1 = (TestBean) lbf.getBean("kerry");
+ TestBean kerry2 = (TestBean) lbf.getBean("kerry");
+ assertEquals("kerry", kerry1.getName());
+ assertNotNull("Non null", kerry1);
+ assertTrue("Singletons equal", kerry1 == kerry2);
+
+ lbf = new DefaultListableBeanFactory();
+ p = new Properties();
+ p.setProperty("wife.(class)", "org.springframework.beans.TestBean");
+ p.setProperty("wife.name", "kerry");
+ p.setProperty("wife.(singleton)", "false");
+ p.setProperty("kerry.(parent)", "wife");
+ p.setProperty("kerry.(singleton)", "false");
+ p.setProperty("kerry.age", "35");
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+ assertFalse(lbf.isSingleton("kerry"));
+ kerry1 = (TestBean) lbf.getBean("kerry");
+ kerry2 = (TestBean) lbf.getBean("kerry");
+ assertTrue("Non null", kerry1 != null);
+ assertTrue("Prototypes NOT equal", kerry1 != kerry2);
+
+ lbf = new DefaultListableBeanFactory();
+ p = new Properties();
+ p.setProperty("kerry.(class)", "org.springframework.beans.TestBean");
+ p.setProperty("kerry.(singleton)", "true");
+ p.setProperty("kerry.age", "35");
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+ kerry1 = (TestBean) lbf.getBean("kerry");
+ kerry2 = (TestBean) lbf.getBean("kerry");
+ assertTrue("Non null", kerry1 != null);
+ assertTrue("Specified singletons equal", kerry1 == kerry2);
+ }
+
+ public void testCanReferenceParentBeanFromChildViaAlias() {
+ final String EXPECTED_NAME = "Juergen";
+ final int EXPECTED_AGE = 41;
+
+ RootBeanDefinition parentDefinition = new RootBeanDefinition(TestBean.class);
+ parentDefinition.setAbstract(true);
+ parentDefinition.getPropertyValues().addPropertyValue("name", EXPECTED_NAME);
+ parentDefinition.getPropertyValues().addPropertyValue("age", new Integer(EXPECTED_AGE));
+
+ ChildBeanDefinition childDefinition = new ChildBeanDefinition("alias");
+
+ DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
+ factory.registerBeanDefinition("parent", parentDefinition);
+ factory.registerBeanDefinition("child", childDefinition);
+ factory.registerAlias("parent", "alias");
+
+ TestBean child = (TestBean) factory.getBean("child");
+ assertEquals(EXPECTED_NAME, child.getName());
+ assertEquals(EXPECTED_AGE, child.getAge());
+
+ assertEquals("Use cached merged bean definition",
+ factory.getMergedBeanDefinition("child"), factory.getMergedBeanDefinition("child"));
+ }
+
+ public void testNameAlreadyBound() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+ p.setProperty("kerry.(class)", "org.springframework.beans.TestBean");
+ p.setProperty("kerry.age", "35");
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+ try {
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+ }
+ catch (BeanDefinitionStoreException ex) {
+ assertEquals("kerry", ex.getBeanName());
+ // expected
+ }
+ }
+
+ private void testSingleTestBean(ListableBeanFactory lbf) {
+ assertTrue("1 beans defined", lbf.getBeanDefinitionCount() == 1);
+ String[] names = lbf.getBeanDefinitionNames();
+ assertTrue("Array length == 1", names.length == 1);
+ assertTrue("0th element == test", names[0].equals("test"));
+ TestBean tb = (TestBean) lbf.getBean("test");
+ assertTrue("Test is non null", tb != null);
+ assertTrue("Test bean name is Tony", "Tony".equals(tb.getName()));
+ assertTrue("Test bean age is 48", tb.getAge() == 48);
+ }
+
+ public void testBeanDefinitionOverriding() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ lbf.registerBeanDefinition("test", new RootBeanDefinition(TestBean.class));
+ lbf.registerBeanDefinition("test", new RootBeanDefinition(NestedTestBean.class));
+ lbf.registerAlias("otherTest", "test2");
+ lbf.registerAlias("test", "test2");
+ assertTrue(lbf.getBean("test") instanceof NestedTestBean);
+ assertTrue(lbf.getBean("test2") instanceof NestedTestBean);
+ }
+
+ public void testBeanDefinitionRemoval() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ lbf.setAllowBeanDefinitionOverriding(false);
+ lbf.registerBeanDefinition("test", new RootBeanDefinition(TestBean.class));
+ lbf.registerAlias("test", "test2");
+ lbf.preInstantiateSingletons();
+ lbf.removeBeanDefinition("test");
+ lbf.removeAlias("test2");
+ lbf.registerBeanDefinition("test", new RootBeanDefinition(NestedTestBean.class));
+ lbf.registerAlias("test", "test2");
+ assertTrue(lbf.getBean("test") instanceof NestedTestBean);
+ assertTrue(lbf.getBean("test2") instanceof NestedTestBean);
+ }
+
+ public void testBeanDefinitionOverridingNotAllowed() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ lbf.setAllowBeanDefinitionOverriding(false);
+ lbf.registerBeanDefinition("test", new RootBeanDefinition(TestBean.class));
+ try {
+ lbf.registerBeanDefinition("test", new RootBeanDefinition(NestedTestBean.class));
+ fail("Should have thrown BeanDefinitionStoreException");
+ }
+ catch (BeanDefinitionStoreException ex) {
+ assertEquals("test", ex.getBeanName());
+ // expected
+ }
+ }
+
+ public void testBeanDefinitionOverridingWithAlias() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ lbf.registerBeanDefinition("test", new RootBeanDefinition(TestBean.class));
+ lbf.registerAlias("test", "testAlias");
+ lbf.registerBeanDefinition("test", new RootBeanDefinition(NestedTestBean.class));
+ lbf.registerAlias("test", "testAlias");
+ assertTrue(lbf.getBean("test") instanceof NestedTestBean);
+ assertTrue(lbf.getBean("testAlias") instanceof NestedTestBean);
+ }
+
+ public void testAliasChaining() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ lbf.registerBeanDefinition("test", new RootBeanDefinition(NestedTestBean.class));
+ lbf.registerAlias("test", "testAlias");
+ lbf.registerAlias("testAlias", "testAlias2");
+ lbf.registerAlias("testAlias2", "testAlias3");
+ Object bean = lbf.getBean("test");
+ assertSame(bean, lbf.getBean("testAlias"));
+ assertSame(bean, lbf.getBean("testAlias2"));
+ assertSame(bean, lbf.getBean("testAlias3"));
+ }
+
+ public void testBeanReferenceWithNewSyntax() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+ p.setProperty("r.(class)", TestBean.class.getName());
+ p.setProperty("r.name", "rod");
+ p.setProperty("k.(class)", TestBean.class.getName());
+ p.setProperty("k.name", "kerry");
+ p.setProperty("k.spouse", "*r");
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+ TestBean k = (TestBean) lbf.getBean("k");
+ TestBean r = (TestBean) lbf.getBean("r");
+ assertTrue(k.getSpouse() == r);
+ }
+
+ public void testCanEscapeBeanReferenceSyntax() {
+ String name = "*name";
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+ p.setProperty("r.(class)", TestBean.class.getName());
+ p.setProperty("r.name", "*" + name);
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+ TestBean r = (TestBean) lbf.getBean("r");
+ assertTrue(r.getName().equals(name));
+ }
+
+ public void testCustomEditor() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ NumberFormat nf = NumberFormat.getInstance(Locale.GERMAN);
+ lbf.registerCustomEditor(Float.class, new CustomNumberEditor(Float.class, nf, true));
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("myFloat", "1,1");
+ lbf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class, pvs));
+ TestBean testBean = (TestBean) lbf.getBean("testBean");
+ assertTrue(testBean.getMyFloat().floatValue() == 1.1f);
+ }
+
+ public void testCustomEditorWithBeanReference() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ NumberFormat nf = NumberFormat.getInstance(Locale.GERMAN);
+ lbf.registerCustomEditor(Float.class, new CustomNumberEditor(Float.class, nf, true));
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("myFloat", new RuntimeBeanReference("myFloat"));
+ lbf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class, pvs));
+ lbf.registerSingleton("myFloat", "1,1");
+ TestBean testBean = (TestBean) lbf.getBean("testBean");
+ assertTrue(testBean.getMyFloat().floatValue() == 1.1f);
+ }
+
+ public void testCustomTypeConverter() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ NumberFormat nf = NumberFormat.getInstance(Locale.GERMAN);
+ lbf.setTypeConverter(new CustomTypeConverter(nf));
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("myFloat", "1,1");
+ ConstructorArgumentValues cav = new ConstructorArgumentValues();
+ cav.addIndexedArgumentValue(0, "myName");
+ cav.addIndexedArgumentValue(1, "myAge");
+ lbf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class, cav, pvs));
+ TestBean testBean = (TestBean) lbf.getBean("testBean");
+ assertEquals("myName", testBean.getName());
+ assertEquals(5, testBean.getAge());
+ assertTrue(testBean.getMyFloat().floatValue() == 1.1f);
+ }
+
+ public void testCustomTypeConverterWithBeanReference() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ NumberFormat nf = NumberFormat.getInstance(Locale.GERMAN);
+ lbf.setTypeConverter(new CustomTypeConverter(nf));
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("myFloat", new RuntimeBeanReference("myFloat"));
+ ConstructorArgumentValues cav = new ConstructorArgumentValues();
+ cav.addIndexedArgumentValue(0, "myName");
+ cav.addIndexedArgumentValue(1, "myAge");
+ lbf.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class, cav, pvs));
+ lbf.registerSingleton("myFloat", "1,1");
+ TestBean testBean = (TestBean) lbf.getBean("testBean");
+ assertEquals("myName", testBean.getName());
+ assertEquals(5, testBean.getAge());
+ assertTrue(testBean.getMyFloat().floatValue() == 1.1f);
+ }
+
+ public void testRegisterExistingSingletonWithReference() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+ p.setProperty("test.(class)", "org.springframework.beans.TestBean");
+ p.setProperty("test.name", "Tony");
+ p.setProperty("test.age", "48");
+ p.setProperty("test.spouse(ref)", "singletonObject");
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+ Object singletonObject = new TestBean();
+ lbf.registerSingleton("singletonObject", singletonObject);
+
+ assertTrue(lbf.isSingleton("singletonObject"));
+ assertEquals(TestBean.class, lbf.getType("singletonObject"));
+ TestBean test = (TestBean) lbf.getBean("test");
+ assertEquals(singletonObject, lbf.getBean("singletonObject"));
+ assertEquals(singletonObject, test.getSpouse());
+
+ Map beansOfType = lbf.getBeansOfType(TestBean.class, false, true);
+ assertEquals(2, beansOfType.size());
+ assertTrue(beansOfType.containsValue(test));
+ assertTrue(beansOfType.containsValue(singletonObject));
+
+ beansOfType = lbf.getBeansOfType(null, false, true);
+ assertEquals(2, beansOfType.size());
+ }
+
+ public void testRegisterExistingSingletonWithNameOverriding() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+ p.setProperty("test.(class)", "org.springframework.beans.TestBean");
+ p.setProperty("test.name", "Tony");
+ p.setProperty("test.age", "48");
+ p.setProperty("test.spouse(ref)", "singletonObject");
+ p.setProperty("singletonObject.(class)", "org.springframework.beans.factory.config.PropertiesFactoryBean");
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p);
+ Object singletonObject = new TestBean();
+ lbf.registerSingleton("singletonObject", singletonObject);
+ lbf.preInstantiateSingletons();
+
+ assertTrue(lbf.isSingleton("singletonObject"));
+ assertEquals(TestBean.class, lbf.getType("singletonObject"));
+ TestBean test = (TestBean) lbf.getBean("test");
+ assertEquals(singletonObject, lbf.getBean("singletonObject"));
+ assertEquals(singletonObject, test.getSpouse());
+
+ Map beansOfType = lbf.getBeansOfType(TestBean.class, false, true);
+ assertEquals(2, beansOfType.size());
+ assertTrue(beansOfType.containsValue(test));
+ assertTrue(beansOfType.containsValue(singletonObject));
+
+ beansOfType = lbf.getBeansOfType(null, false, true);
+ assertEquals(2, beansOfType.size());
+ }
+
+ public void testRegisterExistingSingletonWithAutowire() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "Tony");
+ pvs.addPropertyValue("age", "48");
+ RootBeanDefinition bd = new RootBeanDefinition(DependenciesBean.class, pvs);
+ bd.setDependencyCheck(RootBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
+ bd.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE);
+ lbf.registerBeanDefinition("test", bd);
+ Object singletonObject = new TestBean();
+ lbf.registerSingleton("singletonObject", singletonObject);
+
+ assertTrue(lbf.containsBean("singletonObject"));
+ assertTrue(lbf.isSingleton("singletonObject"));
+ assertEquals(TestBean.class, lbf.getType("singletonObject"));
+ assertEquals(0, lbf.getAliases("singletonObject").length);
+ DependenciesBean test = (DependenciesBean) lbf.getBean("test");
+ assertEquals(singletonObject, lbf.getBean("singletonObject"));
+ assertEquals(singletonObject, test.getSpouse());
+ }
+
+ public void testRegisterExistingSingletonWithAlreadyBound() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Object singletonObject = new TestBean();
+ lbf.registerSingleton("singletonObject", singletonObject);
+ try {
+ lbf.registerSingleton("singletonObject", singletonObject);
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ public void testReregisterBeanDefinition() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
+ bd1.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
+ lbf.registerBeanDefinition("testBean", bd1);
+ assertTrue(lbf.getBean("testBean") instanceof TestBean);
+ RootBeanDefinition bd2 = new RootBeanDefinition(NestedTestBean.class);
+ bd2.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
+ lbf.registerBeanDefinition("testBean", bd2);
+ assertTrue(lbf.getBean("testBean") instanceof NestedTestBean);
+ }
+
+ public void testArrayPropertyWithAutowiring() throws MalformedURLException {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ bf.registerSingleton("resource1", new UrlResource("http://localhost:8080"));
+ bf.registerSingleton("resource2", new UrlResource("http://localhost:9090"));
+
+ RootBeanDefinition rbd = new RootBeanDefinition(ArrayBean.class, RootBeanDefinition.AUTOWIRE_BY_TYPE);
+ bf.registerBeanDefinition("arrayBean", rbd);
+ ArrayBean ab = (ArrayBean) bf.getBean("arrayBean");
+
+ assertEquals(new UrlResource("http://localhost:8080"), ab.getResourceArray()[0]);
+ assertEquals(new UrlResource("http://localhost:9090"), ab.getResourceArray()[1]);
+ }
+
+ public void testArrayPropertyWithOptionalAutowiring() throws MalformedURLException {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+
+ RootBeanDefinition rbd = new RootBeanDefinition(ArrayBean.class, RootBeanDefinition.AUTOWIRE_BY_TYPE);
+ bf.registerBeanDefinition("arrayBean", rbd);
+ ArrayBean ab = (ArrayBean) bf.getBean("arrayBean");
+
+ assertNull(ab.getResourceArray());
+ }
+
+ public void testArrayConstructorWithAutowiring() {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ bf.registerSingleton("integer1", new Integer(4));
+ bf.registerSingleton("integer2", new Integer(5));
+
+ RootBeanDefinition rbd = new RootBeanDefinition(ArrayBean.class, RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
+ bf.registerBeanDefinition("arrayBean", rbd);
+ ArrayBean ab = (ArrayBean) bf.getBean("arrayBean");
+
+ assertEquals(new Integer(4), ab.getIntegerArray()[0]);
+ assertEquals(new Integer(5), ab.getIntegerArray()[1]);
+ }
+
+ public void testArrayConstructorWithOptionalAutowiring() {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+
+ RootBeanDefinition rbd = new RootBeanDefinition(ArrayBean.class, RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
+ bf.registerBeanDefinition("arrayBean", rbd);
+ ArrayBean ab = (ArrayBean) bf.getBean("arrayBean");
+
+ assertNull(ab.getIntegerArray());
+ }
+
+ public void testDoubleArrayConstructorWithAutowiring() throws MalformedURLException {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ bf.registerSingleton("integer1", new Integer(4));
+ bf.registerSingleton("integer2", new Integer(5));
+ bf.registerSingleton("resource1", new UrlResource("http://localhost:8080"));
+ bf.registerSingleton("resource2", new UrlResource("http://localhost:9090"));
+
+ RootBeanDefinition rbd = new RootBeanDefinition(ArrayBean.class, RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
+ bf.registerBeanDefinition("arrayBean", rbd);
+ ArrayBean ab = (ArrayBean) bf.getBean("arrayBean");
+
+ assertEquals(new Integer(4), ab.getIntegerArray()[0]);
+ assertEquals(new Integer(5), ab.getIntegerArray()[1]);
+ assertEquals(new UrlResource("http://localhost:8080"), ab.getResourceArray()[0]);
+ assertEquals(new UrlResource("http://localhost:9090"), ab.getResourceArray()[1]);
+ }
+
+ public void testDoubleArrayConstructorWithOptionalAutowiring() throws MalformedURLException {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ bf.registerSingleton("resource1", new UrlResource("http://localhost:8080"));
+ bf.registerSingleton("resource2", new UrlResource("http://localhost:9090"));
+
+ RootBeanDefinition rbd = new RootBeanDefinition(ArrayBean.class, RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
+ bf.registerBeanDefinition("arrayBean", rbd);
+ ArrayBean ab = (ArrayBean) bf.getBean("arrayBean");
+
+ assertNull(ab.getIntegerArray());
+ assertNull(ab.getResourceArray());
+ }
+
+ public void testAutowireWithNoDependencies() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
+ lbf.registerBeanDefinition("rod", bd);
+ assertEquals(1, lbf.getBeanDefinitionCount());
+ Object registered = lbf.autowire(NoDependencies.class, AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT, false);
+ assertEquals(1, lbf.getBeanDefinitionCount());
+ assertTrue(registered instanceof NoDependencies);
+ }
+
+ public void testAutowireWithSatisfiedJavaBeanDependency() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "Rod");
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, pvs);
+ lbf.registerBeanDefinition("rod", bd);
+ assertEquals(1, lbf.getBeanDefinitionCount());
+ // Depends on age, name and spouse (TestBean)
+ Object registered = lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT, true);
+ assertEquals(1, lbf.getBeanDefinitionCount());
+ DependenciesBean kerry = (DependenciesBean) registered;
+ TestBean rod = (TestBean) lbf.getBean("rod");
+ assertSame(rod, kerry.getSpouse());
+ }
+
+ public void testAutowireWithSatisfiedConstructorDependency() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "Rod");
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, pvs);
+ lbf.registerBeanDefinition("rod", bd);
+ assertEquals(1, lbf.getBeanDefinitionCount());
+ Object registered = lbf.autowire(ConstructorDependency.class, AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT, false);
+ assertEquals(1, lbf.getBeanDefinitionCount());
+ ConstructorDependency kerry = (ConstructorDependency) registered;
+ TestBean rod = (TestBean) lbf.getBean("rod");
+ assertSame(rod, kerry.spouse);
+ }
+
+ public void testAutowireWithTwoMatchesForConstructorDependency() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
+ lbf.registerBeanDefinition("rod", bd);
+ RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
+ lbf.registerBeanDefinition("rod2", bd2);
+ try {
+ lbf.autowire(ConstructorDependency.class, AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT, false);
+ fail("Should have thrown UnsatisfiedDependencyException");
+ }
+ catch (UnsatisfiedDependencyException ex) {
+ // expected
+ assertTrue(ex.getMessage().indexOf("rod") != -1);
+ assertTrue(ex.getMessage().indexOf("rod2") != -1);
+ }
+ }
+
+ public void testAutowireWithUnsatisfiedConstructorDependency() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue(new PropertyValue("name", "Rod"));
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, pvs);
+ lbf.registerBeanDefinition("rod", bd);
+ assertEquals(1, lbf.getBeanDefinitionCount());
+ try {
+ lbf.autowire(UnsatisfiedConstructorDependency.class, AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT, true);
+ fail("Should have unsatisfied constructor dependency on SideEffectBean");
+ }
+ catch (UnsatisfiedDependencyException ex) {
+ // expected
+ }
+ }
+
+ public void testAutowireConstructor() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
+ lbf.registerBeanDefinition("spouse", bd);
+ ConstructorDependenciesBean bean = (ConstructorDependenciesBean)
+ lbf.autowire(ConstructorDependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, true);
+ Object spouse = lbf.getBean("spouse");
+ assertTrue(bean.getSpouse1() == spouse);
+ assertTrue(BeanFactoryUtils.beanOfType(lbf, TestBean.class) == spouse);
+ }
+
+ public void testAutowireBeanByName() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
+ lbf.registerBeanDefinition("spouse", bd);
+ DependenciesBean bean = (DependenciesBean)
+ lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true);
+ TestBean spouse = (TestBean) lbf.getBean("spouse");
+ assertEquals(spouse, bean.getSpouse());
+ assertTrue(BeanFactoryUtils.beanOfType(lbf, TestBean.class) == spouse);
+ }
+
+ public void testAutowireBeanByNameWithDependencyCheck() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
+ lbf.registerBeanDefinition("spous", bd);
+ try {
+ lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true);
+ fail("Should have thrown UnsatisfiedDependencyException");
+ }
+ catch (UnsatisfiedDependencyException ex) {
+ // expected
+ }
+ }
+
+ public void testAutowireBeanByNameWithNoDependencyCheck() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
+ lbf.registerBeanDefinition("spous", bd);
+ DependenciesBean bean = (DependenciesBean)
+ lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false);
+ assertNull(bean.getSpouse());
+ }
+
+ public void testAutowireBeanByType() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
+ lbf.registerBeanDefinition("test", bd);
+ DependenciesBean bean = (DependenciesBean)
+ lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
+ TestBean test = (TestBean) lbf.getBean("test");
+ assertEquals(test, bean.getSpouse());
+ }
+
+ /**
+ * Verifies that a dependency on a {@link FactoryBean} can be autowired
+ * by type, specifically addressing the JIRA issue raised in SPR-4040.
+ */
+ public void testAutowireBeanWithFactoryBeanByType() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition bd = new RootBeanDefinition(LazyInitFactory.class, new MutablePropertyValues());
+ lbf.registerBeanDefinition("factoryBean", bd);
+ LazyInitFactory factoryBean = (LazyInitFactory) lbf.getBean("&factoryBean");
+ assertNotNull("The FactoryBean should have been registered.", factoryBean);
+ FactoryBeanDependentBean bean = (FactoryBeanDependentBean) lbf.autowire(FactoryBeanDependentBean.class,
+ AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
+ assertEquals("The FactoryBeanDependentBean should have been autowired 'by type' with the LazyInitFactory.",
+ factoryBean, bean.getFactoryBean());
+ }
+
+ /**
+ * Verifies that a dependency on a {@link FactoryBean} can not
+ * be autowired by name, as & is an illegal character in
+ * Java method names. In other words, you can't name a method
+ * set&FactoryBean(...).
+ */
+ public void testAutowireBeanWithFactoryBeanByName() {
+ new AssertThrows(TypeMismatchException.class) {
+ public void test() throws Exception {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition bd = new RootBeanDefinition(LazyInitFactory.class, new MutablePropertyValues());
+ lbf.registerBeanDefinition("factoryBean", bd);
+ LazyInitFactory factoryBean = (LazyInitFactory) lbf.getBean("&factoryBean");
+ assertNotNull("The FactoryBean should have been registered.", factoryBean);
+ lbf.autowire(FactoryBeanDependentBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true);
+ }
+ }.runTest();
+ }
+
+ public void testAutowireBeanByTypeWithTwoMatches() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
+ RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
+ lbf.registerBeanDefinition("test", bd);
+ lbf.registerBeanDefinition("test2", bd2);
+ try {
+ lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
+ fail("Should have thrown UnsatisfiedDependencyException");
+ }
+ catch (UnsatisfiedDependencyException ex) {
+ // expected
+ assertTrue(ex.getMessage().indexOf("test") != -1);
+ assertTrue(ex.getMessage().indexOf("test2") != -1);
+ }
+ }
+
+ public void testAutowireBeanByTypeWithDependencyCheck() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ try {
+ lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
+ fail("Should have thrown UnsatisfiedDependencyException");
+ }
+ catch (UnsatisfiedDependencyException ex) {
+ // expected
+ }
+ }
+
+ public void testAutowireBeanByTypeWithNoDependencyCheck() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ DependenciesBean bean = (DependenciesBean)
+ lbf.autowire(DependenciesBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
+ assertNull(bean.getSpouse());
+ }
+
+ public void testAutowireExistingBeanByName() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
+ lbf.registerBeanDefinition("spouse", bd);
+ DependenciesBean existingBean = new DependenciesBean();
+ lbf.autowireBeanProperties(existingBean, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true);
+ TestBean spouse = (TestBean) lbf.getBean("spouse");
+ assertEquals(existingBean.getSpouse(), spouse);
+ assertSame(spouse, BeanFactoryUtils.beanOfType(lbf, TestBean.class));
+ }
+
+ public void testAutowireExistingBeanByNameWithDependencyCheck() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
+ lbf.registerBeanDefinition("spous", bd);
+ DependenciesBean existingBean = new DependenciesBean();
+ try {
+ lbf.autowireBeanProperties(existingBean, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true);
+ fail("Should have thrown UnsatisfiedDependencyException");
+ }
+ catch (UnsatisfiedDependencyException ex) {
+ // expected
+ }
+ }
+
+ public void testAutowireExistingBeanByNameWithNoDependencyCheck() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
+ lbf.registerBeanDefinition("spous", bd);
+ DependenciesBean existingBean = new DependenciesBean();
+ lbf.autowireBeanProperties(existingBean, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false);
+ assertNull(existingBean.getSpouse());
+ }
+
+ public void testAutowireExistingBeanByType() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
+ lbf.registerBeanDefinition("test", bd);
+ DependenciesBean existingBean = new DependenciesBean();
+ lbf.autowireBeanProperties(existingBean, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
+ TestBean test = (TestBean) lbf.getBean("test");
+ assertEquals(existingBean.getSpouse(), test);
+ }
+
+ public void testAutowireExistingBeanByTypeWithDependencyCheck() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ DependenciesBean existingBean = new DependenciesBean();
+ try {
+ lbf.autowireBeanProperties(existingBean, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
+ fail("Should have thrown UnsatisfiedDependencyException");
+ }
+ catch (UnsatisfiedDependencyException expected) {
+ }
+ }
+
+ public void testAutowireExistingBeanByTypeWithNoDependencyCheck() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ DependenciesBean existingBean = new DependenciesBean();
+ lbf.autowireBeanProperties(existingBean, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
+ assertNull(existingBean.getSpouse());
+ }
+
+ public void testInvalidAutowireMode() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ try {
+ lbf.autowireBeanProperties(new TestBean(), AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testApplyBeanPropertyValues() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("age", "99");
+ lbf.registerBeanDefinition("test", new RootBeanDefinition(TestBean.class, pvs));
+ TestBean tb = new TestBean();
+ assertEquals(0, tb.getAge());
+ lbf.applyBeanPropertyValues(tb, "test");
+ assertEquals(99, tb.getAge());
+ }
+
+ public void testApplyBeanPropertyValuesWithIncompleteDefinition() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("age", "99");
+ lbf.registerBeanDefinition("test", new RootBeanDefinition(null, pvs));
+ TestBean tb = new TestBean();
+ assertEquals(0, tb.getAge());
+ lbf.applyBeanPropertyValues(tb, "test");
+ assertEquals(99, tb.getAge());
+ assertNull(tb.getBeanFactory());
+ assertNull(tb.getSpouse());
+ }
+
+ public void testConfigureBean() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("age", "99");
+ lbf.registerBeanDefinition("test", new RootBeanDefinition(TestBean.class, pvs));
+ TestBean tb = new TestBean();
+ assertEquals(0, tb.getAge());
+ lbf.configureBean(tb, "test");
+ assertEquals(99, tb.getAge());
+ assertSame(lbf, tb.getBeanFactory());
+ assertNull(tb.getSpouse());
+ }
+
+ public void testConfigureBeanWithAutowiring() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, new MutablePropertyValues());
+ lbf.registerBeanDefinition("spouse", bd);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("age", "99");
+ lbf.registerBeanDefinition("test", new RootBeanDefinition(TestBean.class, RootBeanDefinition.AUTOWIRE_BY_NAME));
+ TestBean tb = new TestBean();
+ lbf.configureBean(tb, "test");
+ assertSame(lbf, tb.getBeanFactory());
+ TestBean spouse = (TestBean) lbf.getBean("spouse");
+ assertEquals(spouse, tb.getSpouse());
+ }
+
+ public void testExtensiveCircularReference() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ for (int i = 0; i < 1000; i++) {
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue(new PropertyValue("spouse", new RuntimeBeanReference("bean" + (i < 99 ? i + 1 : 0))));
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, pvs);
+ lbf.registerBeanDefinition("bean" + i, bd);
+ }
+ lbf.preInstantiateSingletons();
+ for (int i = 0; i < 1000; i++) {
+ TestBean bean = (TestBean) lbf.getBean("bean" + i);
+ TestBean otherBean = (TestBean) lbf.getBean("bean" + (i < 99 ? i + 1 : 0));
+ assertTrue(bean.getSpouse() == otherBean);
+ }
+ }
+
+ public void testCircularReferenceThroughAutowiring() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ lbf.registerBeanDefinition("test", new RootBeanDefinition(ConstructorDependencyBean.class, RootBeanDefinition.AUTOWIRE_CONSTRUCTOR));
+ try {
+ lbf.preInstantiateSingletons();
+ fail("Should have thrown UnsatisfiedDependencyException");
+ }
+ catch (UnsatisfiedDependencyException expected) {
+ }
+ }
+
+ public void testCircularReferenceThroughFactoryBeanAutowiring() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ lbf.registerBeanDefinition("test", new RootBeanDefinition(ConstructorDependencyFactoryBean.class, RootBeanDefinition.AUTOWIRE_CONSTRUCTOR));
+ try {
+ lbf.preInstantiateSingletons();
+ fail("Should have thrown UnsatisfiedDependencyException");
+ }
+ catch (UnsatisfiedDependencyException expected) {
+ }
+ }
+
+ public void testCircularReferenceThroughFactoryBeanTypeCheck() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ lbf.registerBeanDefinition("test", new RootBeanDefinition(ConstructorDependencyFactoryBean.class, RootBeanDefinition.AUTOWIRE_CONSTRUCTOR));
+ try {
+ lbf.getBeansOfType(String.class);
+ fail("Should have thrown UnsatisfiedDependencyException");
+ }
+ catch (UnsatisfiedDependencyException expected) {
+ }
+ }
+
+ public void testAvoidCircularReferenceThroughAutowiring() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ lbf.registerBeanDefinition("test", new RootBeanDefinition(ConstructorDependencyFactoryBean.class, RootBeanDefinition.AUTOWIRE_CONSTRUCTOR));
+ lbf.registerBeanDefinition("string",
+ new RootBeanDefinition(String.class, RootBeanDefinition.AUTOWIRE_CONSTRUCTOR));
+ lbf.preInstantiateSingletons();
+ }
+
+ public void testBeanDefinitionWithInterface() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ lbf.registerBeanDefinition("test", new RootBeanDefinition(ITestBean.class));
+ try {
+ lbf.getBean("test");
+ fail("Should have thrown BeanCreationException");
+ }
+ catch (BeanCreationException ex) {
+ assertEquals("test", ex.getBeanName());
+ assertTrue(ex.getMessage().toLowerCase().indexOf("interface") != -1);
+ }
+ }
+
+ public void testBeanDefinitionWithAbstractClass() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ lbf.registerBeanDefinition("test", new RootBeanDefinition(AbstractBeanFactory.class));
+ try {
+ lbf.getBean("test");
+ fail("Should have thrown BeanCreationException");
+ }
+ catch (BeanCreationException ex) {
+ assertEquals("test", ex.getBeanName());
+ assertTrue(ex.getMessage().toLowerCase().indexOf("abstract") != -1);
+ }
+ }
+
+ public void testPrototypeFactoryBeanNotEagerlyCalled() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ lbf.registerBeanDefinition("test", new RootBeanDefinition(FactoryBeanThatShouldntBeCalled.class));
+ lbf.preInstantiateSingletons();
+ }
+
+ public void testLazyInitFactory() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ lbf.registerBeanDefinition("test", new RootBeanDefinition(LazyInitFactory.class));
+ lbf.preInstantiateSingletons();
+ LazyInitFactory factory = (LazyInitFactory) lbf.getBean("&test");
+ assertFalse(factory.initialized);
+ }
+
+ public void testSmartInitFactory() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ lbf.registerBeanDefinition("test", new RootBeanDefinition(EagerInitFactory.class));
+ lbf.preInstantiateSingletons();
+ EagerInitFactory factory = (EagerInitFactory) lbf.getBean("&test");
+ assertTrue(factory.initialized);
+ }
+
+ public void testPrototypeFactoryBeanNotEagerlyCalledInCaseOfBeanClassName() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ lbf.registerBeanDefinition("test",
+ new RootBeanDefinition(FactoryBeanThatShouldntBeCalled.class.getName(), null, null));
+ lbf.preInstantiateSingletons();
+ }
+
+ public void testPrototypeWithArrayConversionForConstructor() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ List list = new ManagedList();
+ list.add("myName");
+ list.add("myBeanName");
+ RootBeanDefinition bd = new RootBeanDefinition(DerivedTestBean.class);
+ bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
+ bd.getConstructorArgumentValues().addGenericArgumentValue(list);
+ lbf.registerBeanDefinition("test", bd);
+ DerivedTestBean tb = (DerivedTestBean) lbf.getBean("test");
+ assertEquals("myName", tb.getName());
+ assertEquals("myBeanName", tb.getBeanName());
+ DerivedTestBean tb2 = (DerivedTestBean) lbf.getBean("test");
+ assertTrue(tb != tb2);
+ assertEquals("myName", tb2.getName());
+ assertEquals("myBeanName", tb2.getBeanName());
+ }
+
+ public void testPrototypeWithArrayConversionForFactoryMethod() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ List list = new ManagedList();
+ list.add("myName");
+ list.add("myBeanName");
+ RootBeanDefinition bd = new RootBeanDefinition(DerivedTestBean.class);
+ bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
+ bd.setFactoryMethodName("create");
+ bd.getConstructorArgumentValues().addGenericArgumentValue(list);
+ lbf.registerBeanDefinition("test", bd);
+ DerivedTestBean tb = (DerivedTestBean) lbf.getBean("test");
+ assertEquals("myName", tb.getName());
+ assertEquals("myBeanName", tb.getBeanName());
+ DerivedTestBean tb2 = (DerivedTestBean) lbf.getBean("test");
+ assertTrue(tb != tb2);
+ assertEquals("myName", tb2.getName());
+ assertEquals("myBeanName", tb2.getBeanName());
+ }
+
+ public void testPrototypeCreationIsFastEnough() {
+ if (factoryLog.isTraceEnabled() || factoryLog.isDebugEnabled()) {
+ // Skip this test: Trace logging blows the time limit.
+ return;
+ }
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class);
+ rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
+ lbf.registerBeanDefinition("test", rbd);
+ StopWatch sw = new StopWatch();
+ sw.start("prototype");
+ for (int i = 0; i < 100000; i++) {
+ lbf.getBean("test");
+ }
+ sw.stop();
+ // System.out.println(sw.getTotalTimeMillis());
+ assertTrue("Prototype creation took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 3000);
+ }
+
+ public void testPrototypeCreationWithDependencyCheckIsFastEnough() {
+ if (factoryLog.isTraceEnabled() || factoryLog.isDebugEnabled()) {
+ // Skip this test: Trace logging blows the time limit.
+ return;
+ }
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition rbd = new RootBeanDefinition(LifecycleBean.class);
+ rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
+ rbd.setDependencyCheck(RootBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
+ lbf.registerBeanDefinition("test", rbd);
+ lbf.addBeanPostProcessor(new LifecycleBean.PostProcessor());
+ StopWatch sw = new StopWatch();
+ sw.start("prototype");
+ for (int i = 0; i < 100000; i++) {
+ lbf.getBean("test");
+ }
+ sw.stop();
+ // System.out.println(sw.getTotalTimeMillis());
+ assertTrue("Prototype creation took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 3000);
+ }
+
+ /**
+ * public void testPrototypeCreationIsFastEnough2() throws Exception {
+ * if (factoryLog.isTraceEnabled() || factoryLog.isDebugEnabled()) {
+ * // Skip this test: Trace logging blows the time limit.
+ * return;
+ * }
+ * DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ * Method setBeanNameMethod = TestBean.class.getMethod("setBeanName", String.class);
+ * Method setBeanFactoryMethod = TestBean.class.getMethod("setBeanFactory", BeanFactory.class);
+ * StopWatch sw = new StopWatch();
+ * sw.start("prototype");
+ * for (int i = 0; i < 100000; i++) {
+ * TestBean tb = TestBean.class.newInstance();
+ * setBeanNameMethod.invoke(tb, "test");
+ * setBeanFactoryMethod.invoke(tb, lbf);
+ * }
+ * sw.stop();
+ * // System.out.println(sw.getTotalTimeMillis());
+ * assertTrue("Prototype creation took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 500);
+ * }
+ */
+
+ public void testPrototypeCreationWithConstructorArgumentsIsFastEnough() {
+ if (factoryLog.isTraceEnabled() || factoryLog.isDebugEnabled()) {
+ // Skip this test: Trace logging blows the time limit.
+ return;
+ }
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class);
+ rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
+ rbd.getConstructorArgumentValues().addGenericArgumentValue("juergen");
+ rbd.getConstructorArgumentValues().addGenericArgumentValue("99");
+ lbf.registerBeanDefinition("test", rbd);
+ StopWatch sw = new StopWatch();
+ sw.start("prototype");
+ for (int i = 0; i < 100000; i++) {
+ TestBean tb = (TestBean) lbf.getBean("test");
+ assertEquals("juergen", tb.getName());
+ assertEquals(99, tb.getAge());
+ }
+ sw.stop();
+ // System.out.println(sw.getTotalTimeMillis());
+ assertTrue("Prototype creation took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 3000);
+ }
+
+ /**
+ * public void testPrototypeCreationWithConstructorArgumentsIsFastEnough2() throws Exception {
+ * if (factoryLog.isTraceEnabled() || factoryLog.isDebugEnabled()) {
+ * // Skip this test: Trace logging blows the time limit.
+ * return;
+ * }
+ * DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ * Constructor ctor = TestBean.class.getConstructor(String.class, int.class);
+ * Method setBeanNameMethod = TestBean.class.getMethod("setBeanName", String.class);
+ * Method setBeanFactoryMethod = TestBean.class.getMethod("setBeanFactory", BeanFactory.class);
+ * StopWatch sw = new StopWatch();
+ * sw.start("prototype");
+ * for (int i = 0; i < 100000; i++) {
+ * TestBean tb = ctor.newInstance("juergen", 99);
+ * setBeanNameMethod.invoke(tb, "test");
+ * setBeanFactoryMethod.invoke(tb, lbf);
+ * assertEquals("juergen", tb.getName());
+ * assertEquals(99, tb.getAge());
+ * }
+ * sw.stop();
+ * // System.out.println(sw.getTotalTimeMillis());
+ * assertTrue("Prototype creation took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 1500);
+ * }
+ */
+
+ public void testPrototypeCreationWithResolvedConstructorArgumentsIsFastEnough() {
+ if (factoryLog.isTraceEnabled() || factoryLog.isDebugEnabled()) {
+ // Skip this test: Trace logging blows the time limit.
+ return;
+ }
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class);
+ rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
+ rbd.getConstructorArgumentValues().addGenericArgumentValue(new RuntimeBeanReference("spouse"));
+ lbf.registerBeanDefinition("test", rbd);
+ lbf.registerBeanDefinition("spouse", new RootBeanDefinition(TestBean.class));
+ TestBean spouse = (TestBean) lbf.getBean("spouse");
+ StopWatch sw = new StopWatch();
+ sw.start("prototype");
+ for (int i = 0; i < 100000; i++) {
+ TestBean tb = (TestBean) lbf.getBean("test");
+ assertSame(spouse, tb.getSpouse());
+ }
+ sw.stop();
+ // System.out.println(sw.getTotalTimeMillis());
+ assertTrue("Prototype creation took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 4000);
+ }
+
+ public void testPrototypeCreationWithPropertiesIsFastEnough() {
+ if (factoryLog.isTraceEnabled() || factoryLog.isDebugEnabled()) {
+ // Skip this test: Trace logging blows the time limit.
+ return;
+ }
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class);
+ rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
+ rbd.getPropertyValues().addPropertyValue("name", "juergen");
+ rbd.getPropertyValues().addPropertyValue("age", "99");
+ lbf.registerBeanDefinition("test", rbd);
+ StopWatch sw = new StopWatch();
+ sw.start("prototype");
+ for (int i = 0; i < 100000; i++) {
+ TestBean tb = (TestBean) lbf.getBean("test");
+ assertEquals("juergen", tb.getName());
+ assertEquals(99, tb.getAge());
+ }
+ sw.stop();
+ // System.out.println(sw.getTotalTimeMillis());
+ assertTrue("Prototype creation took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 3000);
+ }
+
+ /**
+ * public void testPrototypeCreationWithPropertiesIsFastEnough2() throws Exception {
+ * if (factoryLog.isTraceEnabled() || factoryLog.isDebugEnabled()) {
+ * // Skip this test: Trace logging blows the time limit.
+ * return;
+ * }
+ * DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ * StopWatch sw = new StopWatch();
+ * Method setBeanNameMethod = TestBean.class.getMethod("setBeanName", String.class);
+ * Method setBeanFactoryMethod = TestBean.class.getMethod("setBeanFactory", BeanFactory.class);
+ * Method setNameMethod = TestBean.class.getMethod("setName", String.class);
+ * Method setAgeMethod = TestBean.class.getMethod("setAge", int.class);
+ * sw.start("prototype");
+ * for (int i = 0; i < 100000; i++) {
+ * TestBean tb = TestBean.class.newInstance();
+ * setBeanNameMethod.invoke(tb, "test");
+ * setBeanFactoryMethod.invoke(tb, lbf);
+ * setNameMethod.invoke(tb, "juergen");
+ * setAgeMethod.invoke(tb, 99);
+ * }
+ * sw.stop();
+ * // System.out.println(sw.getTotalTimeMillis());
+ * assertTrue("Prototype creation took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 750);
+ * }
+ */
+
+ public void testPrototypeCreationWithResolvedPropertiesIsFastEnough() {
+ if (factoryLog.isTraceEnabled() || factoryLog.isDebugEnabled()) {
+ // Skip this test: Trace logging blows the time limit.
+ return;
+ }
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class);
+ rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
+ rbd.getPropertyValues().addPropertyValue("spouse", new RuntimeBeanReference("spouse"));
+ lbf.registerBeanDefinition("test", rbd);
+ lbf.registerBeanDefinition("spouse", new RootBeanDefinition(TestBean.class));
+ TestBean spouse = (TestBean) lbf.getBean("spouse");
+ StopWatch sw = new StopWatch();
+ sw.start("prototype");
+ for (int i = 0; i < 100000; i++) {
+ TestBean tb = (TestBean) lbf.getBean("test");
+ assertSame(spouse, tb.getSpouse());
+ }
+ sw.stop();
+ // System.out.println(sw.getTotalTimeMillis());
+ assertTrue("Prototype creation took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 4000);
+ }
+
+ public void testBeanPostProcessorWithWrappedObjectAndDisposableBean() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition bd = new RootBeanDefinition(BeanWithDisposableBean.class);
+ lbf.registerBeanDefinition("test", bd);
+ lbf.addBeanPostProcessor(new BeanPostProcessor() {
+ public Object postProcessBeforeInitialization(Object bean, String beanName) {
+ return new TestBean();
+ }
+
+ public Object postProcessAfterInitialization(Object bean, String beanName) {
+ return bean;
+ }
+ });
+ BeanWithDisposableBean.closed = false;
+ lbf.preInstantiateSingletons();
+ lbf.destroySingletons();
+ assertTrue("Destroy method invoked", BeanWithDisposableBean.closed);
+ }
+
+ public void testBeanPostProcessorWithWrappedObjectAndDestroyMethod() {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition bd = new RootBeanDefinition(BeanWithDestroyMethod.class);
+ bd.setDestroyMethodName("close");
+ lbf.registerBeanDefinition("test", bd);
+ lbf.addBeanPostProcessor(new BeanPostProcessor() {
+ public Object postProcessBeforeInitialization(Object bean, String beanName) {
+ return new TestBean();
+ }
+
+ public Object postProcessAfterInitialization(Object bean, String beanName) {
+ return bean;
+ }
+ });
+ BeanWithDestroyMethod.closed = false;
+ lbf.preInstantiateSingletons();
+ lbf.destroySingletons();
+ assertTrue("Destroy method invoked", BeanWithDestroyMethod.closed);
+ }
+
+ public void testFindTypeOfSingletonFactoryMethodOnBeanInstance() {
+ findTypeOfPrototypeFactoryMethodOnBeanInstance(true);
+ }
+
+ public void testFindTypeOfPrototypeFactoryMethodOnBeanInstance() {
+ findTypeOfPrototypeFactoryMethodOnBeanInstance(false);
+ }
+
+ /**
+ * @param singleton whether the bean created from the factory method on
+ * the bean instance should be a singleton or prototype. This flag is
+ * used to allow checking of the new ability in 1.2.4 to determine the type
+ * of a prototype created from invoking a factory method on a bean instance
+ * in the factory.
+ */
+ private void findTypeOfPrototypeFactoryMethodOnBeanInstance(boolean singleton) {
+ String expectedNameFromProperties = "tony";
+ String expectedNameFromArgs = "gordon";
+
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition instanceFactoryDefinition = new RootBeanDefinition(BeanWithFactoryMethod.class);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", expectedNameFromProperties);
+ instanceFactoryDefinition.setPropertyValues(pvs);
+ lbf.registerBeanDefinition("factoryBeanInstance", instanceFactoryDefinition);
+
+ RootBeanDefinition factoryMethodDefinitionWithProperties = new RootBeanDefinition();
+ factoryMethodDefinitionWithProperties.setFactoryBeanName("factoryBeanInstance");
+ factoryMethodDefinitionWithProperties.setFactoryMethodName("create");
+ if (!singleton) {
+ factoryMethodDefinitionWithProperties.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
+ }
+ lbf.registerBeanDefinition("fmWithProperties", factoryMethodDefinitionWithProperties);
+
+ RootBeanDefinition factoryMethodDefinitionGeneric = new RootBeanDefinition();
+ factoryMethodDefinitionGeneric.setFactoryBeanName("factoryBeanInstance");
+ factoryMethodDefinitionGeneric.setFactoryMethodName("createGeneric");
+ if (!singleton) {
+ factoryMethodDefinitionGeneric.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
+ }
+ lbf.registerBeanDefinition("fmGeneric", factoryMethodDefinitionGeneric);
+
+ RootBeanDefinition factoryMethodDefinitionWithArgs = new RootBeanDefinition();
+ factoryMethodDefinitionWithArgs.setFactoryBeanName("factoryBeanInstance");
+ factoryMethodDefinitionWithArgs.setFactoryMethodName("createWithArgs");
+ ConstructorArgumentValues cvals = new ConstructorArgumentValues();
+ cvals.addGenericArgumentValue(expectedNameFromArgs);
+ factoryMethodDefinitionWithArgs.setConstructorArgumentValues(cvals);
+ if (!singleton) {
+ factoryMethodDefinitionWithArgs.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
+ }
+ lbf.registerBeanDefinition("fmWithArgs", factoryMethodDefinitionWithArgs);
+
+ assertEquals(4, lbf.getBeanDefinitionCount());
+ List tbNames = Arrays.asList(lbf.getBeanNamesForType(TestBean.class));
+ assertTrue(tbNames.contains("fmWithProperties"));
+ assertTrue(tbNames.contains("fmWithArgs"));
+ assertEquals(2, tbNames.size());
+
+ TestBean tb = (TestBean) lbf.getBean("fmWithProperties");
+ TestBean second = (TestBean) lbf.getBean("fmWithProperties");
+ if (singleton) {
+ assertSame(tb, second);
+ }
+ else {
+ assertNotSame(tb, second);
+ }
+ assertEquals(expectedNameFromProperties, tb.getName());
+
+ tb = (TestBean) lbf.getBean("fmGeneric");
+ second = (TestBean) lbf.getBean("fmGeneric");
+ if (singleton) {
+ assertSame(tb, second);
+ }
+ else {
+ assertNotSame(tb, second);
+ }
+ assertEquals(expectedNameFromProperties, tb.getName());
+
+ TestBean tb2 = (TestBean) lbf.getBean("fmWithArgs");
+ second = (TestBean) lbf.getBean("fmWithArgs");
+ if (singleton) {
+ assertSame(tb2, second);
+ }
+ else {
+ assertNotSame(tb2, second);
+ }
+ assertEquals(expectedNameFromArgs, tb2.getName());
+ }
+
+ public void testScopingBeanToUnregisteredScopeResultsInAnException() throws Exception {
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(TestBean.class);
+ AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
+ beanDefinition.setScope("he put himself so low could hardly look me in the face");
+
+ final DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
+ factory.registerBeanDefinition("testBean", beanDefinition);
+ new AssertThrows(IllegalStateException.class) {
+ public void test() throws Exception {
+ factory.getBean("testBean");
+ }
+ }.runTest();
+ }
+
+ public void testExplicitScopeInheritanceForChildBeanDefinitions() throws Exception {
+ String theChildScope = "bonanza!";
+
+ RootBeanDefinition parent = new RootBeanDefinition();
+ parent.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
+
+ AbstractBeanDefinition child = BeanDefinitionBuilder
+ .childBeanDefinition("parent").getBeanDefinition();
+ child.setBeanClass(TestBean.class);
+ child.setScope(theChildScope);
+
+ DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
+ factory.registerBeanDefinition("parent", parent);
+ factory.registerBeanDefinition("child", child);
+
+ AbstractBeanDefinition def = (AbstractBeanDefinition) factory.getBeanDefinition("child");
+ assertEquals("Child 'scope' not overriding parent scope (it must).", theChildScope, def.getScope());
+ }
+
+ public void testImplicitScopeInheritanceForChildBeanDefinitions() throws Exception {
+ RootBeanDefinition parent = new RootBeanDefinition();
+ parent.setScope("bonanza!");
+
+ AbstractBeanDefinition child = new ChildBeanDefinition("parent");
+ child.setBeanClass(TestBean.class);
+
+ DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
+ factory.registerBeanDefinition("parent", parent);
+ factory.registerBeanDefinition("child", child);
+
+ BeanDefinition def = factory.getMergedBeanDefinition("child");
+ assertTrue("Child 'scope' not overriding parent scope (it must).", def.isSingleton());
+ }
+
+ public void testFieldSettingWithInstantiationAwarePostProcessorNoShortCircuit() {
+ doTestFieldSettingWithInstantiationAwarePostProcessor(false);
+ }
+
+ public void testFieldSettingWithInstantiationAwarePostProcessorWithShortCircuit() {
+ doTestFieldSettingWithInstantiationAwarePostProcessor(true);
+ }
+
+ private void doTestFieldSettingWithInstantiationAwarePostProcessor(final boolean skipPropertyPopulation) {
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
+ int ageSetByPropertyValue = 27;
+ bd.getPropertyValues().addPropertyValue(new PropertyValue("age", new Integer(ageSetByPropertyValue)));
+ lbf.registerBeanDefinition("test", bd);
+ final String nameSetOnField = "nameSetOnField";
+ lbf.addBeanPostProcessor(new InstantiationAwareBeanPostProcessorAdapter() {
+ public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
+ TestBean tb = (TestBean) bean;
+ try {
+ Field f = TestBean.class.getDeclaredField("name");
+ f.setAccessible(true);
+ f.set(tb, nameSetOnField);
+ return !skipPropertyPopulation;
+ }
+ catch (Exception ex) {
+ fail("Unexpected exception: " + ex);
+ // Keep compiler happy about return
+ throw new IllegalStateException();
+ }
+ }
+ });
+ lbf.preInstantiateSingletons();
+ TestBean tb = (TestBean) lbf.getBean("test");
+ assertEquals("Name was set on field by IAPP", nameSetOnField, tb.getName());
+ if (!skipPropertyPopulation) {
+ assertEquals("Property value still set", ageSetByPropertyValue, tb.getAge());
+ }
+ else {
+ assertEquals("Property value was NOT set and still has default value", 0, tb.getAge());
+ }
+ }
+
+ public void testInitSecurityAwarePrototypeBean() {
+ final DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ RootBeanDefinition bd = new RootBeanDefinition(TestSecuredBean.class);
+ bd.setScope(ConfigurableBeanFactory.SCOPE_PROTOTYPE);
+ bd.setInitMethodName("init");
+ lbf.registerBeanDefinition("test", bd);
+ final Subject subject = new Subject();
+ subject.getPrincipals().add(new TestPrincipal("user1"));
+ TestSecuredBean bean = (TestSecuredBean) Subject.doAsPrivileged(subject,
+ new PrivilegedAction() {
+ public Object run() {
+ return lbf.getBean("test");
+ }
+ }, null);
+ assertNotNull(bean);
+ assertEquals("user1", bean.getUserName());
+ }
+
+
+ public static class NoDependencies {
+
+ private NoDependencies() {
+ }
+ }
+
+
+ public static class ConstructorDependency {
+
+ public TestBean spouse;
+
+ public ConstructorDependency(TestBean spouse) {
+ this.spouse = spouse;
+ }
+
+ private ConstructorDependency(TestBean spouse, TestBean otherSpouse) {
+ throw new IllegalArgumentException("Should never be called");
+ }
+ }
+
+
+ public static class UnsatisfiedConstructorDependency {
+
+ public UnsatisfiedConstructorDependency(TestBean t, SideEffectBean b) {
+ }
+ }
+
+
+ public static class ConstructorDependencyBean {
+
+ public ConstructorDependencyBean(ConstructorDependencyBean dependency) {
+ }
+ }
+
+
+ public static class ConstructorDependencyFactoryBean implements FactoryBean {
+
+ public ConstructorDependencyFactoryBean(String dependency) {
+ }
+
+ public Object getObject() {
+ return "test";
+ }
+
+ public Class getObjectType() {
+ return String.class;
+ }
+
+ public boolean isSingleton() {
+ return true;
+ }
+ }
+
+
+ public static class BeanWithDisposableBean implements DisposableBean {
+
+ private static boolean closed;
+
+ public void destroy() {
+ closed = true;
+ }
+ }
+
+
+ public static class BeanWithDestroyMethod {
+
+ private static boolean closed;
+
+ public void close() {
+ closed = true;
+ }
+ }
+
+
+ public static class BeanWithFactoryMethod {
+
+ private String name;
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public TestBean create() {
+ TestBean tb = new TestBean();
+ tb.setName(this.name);
+ return tb;
+ }
+
+ public TestBean createWithArgs(String arg) {
+ TestBean tb = new TestBean();
+ tb.setName(arg);
+ return tb;
+ }
+
+ public Object createGeneric() {
+ return create();
+ }
+ }
+
+
+ public static class FactoryBeanThatShouldntBeCalled implements FactoryBean {
+
+ public Object getObject() {
+ throw new IllegalStateException();
+ }
+
+ public Class getObjectType() {
+ return null;
+ }
+
+ public boolean isSingleton() {
+ return false;
+ }
+ }
+
+
+ public static class LazyInitFactory implements FactoryBean {
+
+ public boolean initialized = false;
+
+ public Object getObject() throws Exception {
+ this.initialized = true;
+ return "";
+ }
+
+ public Class getObjectType() {
+ return String.class;
+ }
+
+ public boolean isSingleton() {
+ return true;
+ }
+ }
+
+
+ public static class EagerInitFactory implements SmartFactoryBean {
+
+ public boolean initialized = false;
+
+ public Object getObject() throws Exception {
+ this.initialized = true;
+ return "";
+ }
+
+ public Class getObjectType() {
+ return String.class;
+ }
+
+ public boolean isSingleton() {
+ return true;
+ }
+
+ public boolean isPrototype() {
+ return false;
+ }
+
+ public boolean isEagerInit() {
+ return true;
+ }
+ }
+
+
+ public static class TestBeanFactory {
+
+ public static boolean initialized = false;
+
+ public TestBeanFactory() {
+ initialized = true;
+ }
+
+ public static TestBean createTestBean() {
+ return new TestBean();
+ }
+
+ public TestBean createTestBeanNonStatic() {
+ return new TestBean();
+ }
+ }
+
+
+ public static class ArrayBean {
+
+ private Integer[] integerArray;
+
+ private Resource[] resourceArray;
+
+ public ArrayBean() {
+ }
+
+ public ArrayBean(Integer[] integerArray) {
+ this.integerArray = integerArray;
+ }
+
+ public ArrayBean(Integer[] integerArray, Resource[] resourceArray) {
+ this.integerArray = integerArray;
+ this.resourceArray = resourceArray;
+ }
+
+ public Integer[] getIntegerArray() {
+ return this.integerArray;
+ }
+
+ public void setResourceArray(Resource[] resourceArray) {
+ this.resourceArray = resourceArray;
+ }
+
+ public Resource[] getResourceArray() {
+ return this.resourceArray;
+ }
+ }
+
+
+ /**
+ * Bean with a dependency on a {@link FactoryBean}.
+ */
+ private static class FactoryBeanDependentBean {
+
+ private FactoryBean factoryBean;
+
+
+ public final FactoryBean getFactoryBean() {
+ return this.factoryBean;
+ }
+
+ public final void setFactoryBean(final FactoryBean factoryBean) {
+ this.factoryBean = factoryBean;
+ }
+ }
+
+
+ private static class CustomTypeConverter implements TypeConverter {
+
+ private final NumberFormat numberFormat;
+
+ public CustomTypeConverter(NumberFormat numberFormat) {
+ this.numberFormat = numberFormat;
+ }
+
+ public Object convertIfNecessary(Object value, Class requiredType) {
+ return convertIfNecessary(value, requiredType, null);
+ }
+
+ public Object convertIfNecessary(Object value, Class requiredType, MethodParameter methodParam) {
+ if (value instanceof String && Float.class.isAssignableFrom(requiredType)) {
+ try {
+ return new Float(this.numberFormat.parse((String) value).floatValue());
+ }
+ catch (ParseException ex) {
+ throw new TypeMismatchException(value, requiredType, ex);
+ }
+ }
+ else if (value instanceof String && int.class.isAssignableFrom(requiredType)) {
+ return new Integer(5);
+ }
+ else {
+ return value;
+ }
+ }
+ }
+
+
+ private static class TestPrincipal implements Principal {
+
+ private String name;
+
+ public TestPrincipal(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof TestPrincipal)) {
+ return false;
+ }
+ TestPrincipal p = (TestPrincipal) obj;
+ return this.name.equals(p.name);
+ }
+
+ public int hashCode() {
+ return this.name.hashCode();
+ }
+ }
+
+
+ private static class TestSecuredBean {
+
+ private String userName;
+
+ public void init() {
+ Subject subject = Subject.getSubject(AccessController.getContext());
+ if (subject == null) {
+ return;
+ }
+ setNameFromPrincipal(subject.getPrincipals());
+ }
+
+ private void setNameFromPrincipal(Set principals) {
+ if (principals == null) {
+ return;
+ }
+ for (Iterator it = principals.iterator(); it.hasNext();) {
+ Principal p = (Principal) it.next();
+ this.userName = p.getName();
+ return;
+ }
+ }
+
+ public String getUserName() {
+ return this.userName;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/DummyFactory.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/DummyFactory.java
new file mode 100644
index 00000000000..020e683d7d8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/DummyFactory.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
+
+/**
+ * Simple factory to allow testing of FactoryBean support in AbstractBeanFactory.
+ * Depending on whether its singleton property is set, it will return a singleton
+ * or a prototype instance.
+ *
+ *
Implements InitializingBean interface, so we can check that
+ * factories get this lifecycle callback if they want.
+ *
+ * @author Rod Johnson
+ * @since 10.03.2003
+ */
+public class DummyFactory
+ implements FactoryBean, BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean {
+
+ public static final String SINGLETON_NAME = "Factory singleton";
+
+ private static boolean prototypeCreated;
+
+ /**
+ * Clear static state.
+ */
+ public static void reset() {
+ prototypeCreated = false;
+ }
+
+
+ /**
+ * Default is for factories to return a singleton instance.
+ */
+ private boolean singleton = true;
+
+ private String beanName;
+
+ private AutowireCapableBeanFactory beanFactory;
+
+ private boolean postProcessed;
+
+ private boolean initialized;
+
+ private TestBean testBean;
+
+ private TestBean otherTestBean;
+
+
+ public DummyFactory() {
+ this.testBean = new TestBean();
+ this.testBean.setName(SINGLETON_NAME);
+ this.testBean.setAge(25);
+ }
+
+ /**
+ * Return if the bean managed by this factory is a singleton.
+ * @see org.springframework.beans.factory.FactoryBean#isSingleton()
+ */
+ public boolean isSingleton() {
+ return this.singleton;
+ }
+
+ /**
+ * Set if the bean managed by this factory is a singleton.
+ */
+ public void setSingleton(boolean singleton) {
+ this.singleton = singleton;
+ }
+
+ public void setBeanName(String beanName) {
+ this.beanName = beanName;
+ }
+
+ public String getBeanName() {
+ return beanName;
+ }
+
+ public void setBeanFactory(BeanFactory beanFactory) {
+ this.beanFactory = (AutowireCapableBeanFactory) beanFactory;
+ this.beanFactory.applyBeanPostProcessorsBeforeInitialization(this.testBean, this.beanName);
+ }
+
+ public BeanFactory getBeanFactory() {
+ return beanFactory;
+ }
+
+ public void setPostProcessed(boolean postProcessed) {
+ this.postProcessed = postProcessed;
+ }
+
+ public boolean isPostProcessed() {
+ return postProcessed;
+ }
+
+ public void setOtherTestBean(TestBean otherTestBean) {
+ this.otherTestBean = otherTestBean;
+ this.testBean.setSpouse(otherTestBean);
+ }
+
+ public TestBean getOtherTestBean() {
+ return otherTestBean;
+ }
+
+ public void afterPropertiesSet() {
+ if (initialized) {
+ throw new RuntimeException("Cannot call afterPropertiesSet twice on the one bean");
+ }
+ this.initialized = true;
+ }
+
+ /**
+ * Was this initialized by invocation of the
+ * afterPropertiesSet() method from the InitializingBean interface?
+ */
+ public boolean wasInitialized() {
+ return initialized;
+ }
+
+ public static boolean wasPrototypeCreated() {
+ return prototypeCreated;
+ }
+
+
+ /**
+ * Return the managed object, supporting both singleton
+ * and prototype mode.
+ * @see org.springframework.beans.factory.FactoryBean#getObject()
+ */
+ public Object getObject() throws BeansException {
+ if (isSingleton()) {
+ return this.testBean;
+ }
+ else {
+ TestBean prototype = new TestBean("prototype created at " + System.currentTimeMillis(), 11);
+ if (this.beanFactory != null) {
+ this.beanFactory.applyBeanPostProcessorsBeforeInitialization(prototype, this.beanName);
+ }
+ prototypeCreated = true;
+ return prototype;
+ }
+ }
+
+ public Class getObjectType() {
+ return TestBean.class;
+ }
+
+
+ public void destroy() {
+ if (this.testBean != null) {
+ this.testBean.setName(null);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/FactoryBeanTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/FactoryBeanTests.java
new file mode 100644
index 00000000000..d2f306333b1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/FactoryBeanTests.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.util.Assert;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class FactoryBeanTests extends TestCase {
+
+ public void testFactoryBeanReturnsNull() throws Exception {
+ XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("factoryBeanReturnsNull.xml", getClass()));
+ Object result = factory.getBean("factoryBean");
+ assertNull(result);
+ }
+
+ public void testFactoryBeansWithAutowiring() throws Exception {
+ ClassPathXmlApplicationContext factory =
+ new ClassPathXmlApplicationContext("factoryBeansWithAutowiring.xml", getClass());
+ Alpha alpha = (Alpha) factory.getBean("alpha");
+ Beta beta = (Beta) factory.getBean("beta");
+ Gamma gamma = (Gamma) factory.getBean("gamma");
+ Gamma gamma2 = (Gamma) factory.getBean("gammaFactory");
+ assertSame(beta, alpha.getBeta());
+ assertSame(gamma, beta.getGamma());
+ assertSame(gamma2, beta.getGamma());
+ assertEquals("yourName", beta.getName());
+ }
+
+ public void testFactoryBeansWithIntermediateFactoryBeanAutowiringFailure() throws Exception {
+ ClassPathXmlApplicationContext factory =
+ new ClassPathXmlApplicationContext("factoryBeansWithAutowiring.xml", getClass());
+ Beta beta = (Beta) factory.getBean("beta");
+ Alpha alpha = (Alpha) factory.getBean("alpha");
+ Gamma gamma = (Gamma) factory.getBean("gamma");
+ assertSame(beta, alpha.getBeta());
+ assertSame(gamma, beta.getGamma());
+ }
+
+
+ public static class NullReturningFactoryBean implements FactoryBean {
+
+ public Object getObject() {
+ return null;
+ }
+
+ public Class getObjectType() {
+ return null;
+ }
+
+ public boolean isSingleton() {
+ return true;
+ }
+ }
+
+
+ public static class Alpha implements InitializingBean {
+
+ private Beta beta;
+
+ public void setBeta(Beta beta) {
+ this.beta = beta;
+ }
+
+ public Beta getBeta() {
+ return beta;
+ }
+
+ public void afterPropertiesSet() {
+ Assert.notNull(beta, "'beta' property is required");
+ }
+ }
+
+
+ public static class Beta implements InitializingBean {
+
+ private Gamma gamma;
+
+ private String name;
+
+ public void setGamma(Gamma gamma) {
+ this.gamma = gamma;
+ }
+
+ public Gamma getGamma() {
+ return gamma;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void afterPropertiesSet() {
+ Assert.notNull(gamma, "'gamma' property is required");
+ }
+ }
+
+
+ public static class Gamma {
+ }
+
+
+ public static class BetaFactoryBean implements FactoryBean {
+
+ private Beta beta;
+
+ public void setBeta(Beta beta) {
+ this.beta = beta;
+ }
+
+ public Object getObject() {
+ return this.beta;
+ }
+
+ public Class getObjectType() {
+ return null;
+ }
+
+ public boolean isSingleton() {
+ return true;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/HasMap.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/HasMap.java
new file mode 100644
index 00000000000..3bac49498b5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/HasMap.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.factory;
+
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * Bean exposing a map. Used for bean factory tests.
+ *
+ * @author Rod Johnson
+ * @since 05.06.2003
+ */
+public class HasMap {
+
+ private Map map;
+
+ private Set set;
+
+ private Properties props;
+
+ private Object[] objectArray;
+
+ private Class[] classArray;
+
+ private Integer[] intArray;
+
+ private HasMap() {
+ }
+
+ public Map getMap() {
+ return map;
+ }
+
+ public void setMap(Map map) {
+ this.map = map;
+ }
+
+ public Set getSet() {
+ return set;
+ }
+
+ public void setSet(Set set) {
+ this.set = set;
+ }
+
+ public Properties getProps() {
+ return props;
+ }
+
+ public void setProps(Properties props) {
+ this.props = props;
+ }
+
+ public Object[] getObjectArray() {
+ return objectArray;
+ }
+
+ public void setObjectArray(Object[] objectArray) {
+ this.objectArray = objectArray;
+ }
+
+ public Class[] getClassArray() {
+ return classArray;
+ }
+
+ public void setClassArray(Class[] classArray) {
+ this.classArray = classArray;
+ }
+
+ public Integer[] getIntegerArray() {
+ return intArray;
+ }
+
+ public void setIntegerArray(Integer[] is) {
+ intArray = is;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/KnowsIfInstantiated.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/KnowsIfInstantiated.java
new file mode 100644
index 00000000000..1bb269dfb7f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/KnowsIfInstantiated.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.factory;
+
+public class KnowsIfInstantiated {
+
+ private static boolean instantiated;
+
+ public static void clearInstantiationRecord() {
+ instantiated = false;
+ }
+
+ public static boolean wasInstantiated() {
+ return instantiated;
+ }
+
+ public KnowsIfInstantiated() {
+ instantiated = true;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/LifecycleBean.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/LifecycleBean.java
new file mode 100644
index 00000000000..ebbbf1c7f86
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/LifecycleBean.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+
+/**
+ * Simple test of BeanFactory initialization and lifecycle callbacks.
+ *
+ * @author Rod Johnson
+ * @author Colin Sampaleanu
+ * @since 12.03.2003
+ */
+public class LifecycleBean implements BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean {
+
+ protected boolean initMethodDeclared = false;
+
+ protected String beanName;
+
+ protected BeanFactory owningFactory;
+
+ protected boolean postProcessedBeforeInit;
+
+ protected boolean inited;
+
+ protected boolean initedViaDeclaredInitMethod;
+
+ protected boolean postProcessedAfterInit;
+
+ protected boolean destroyed;
+
+
+ public void setInitMethodDeclared(boolean initMethodDeclared) {
+ this.initMethodDeclared = initMethodDeclared;
+ }
+
+ public boolean isInitMethodDeclared() {
+ return initMethodDeclared;
+ }
+
+ public void setBeanName(String name) {
+ this.beanName = name;
+ }
+
+ public String getBeanName() {
+ return beanName;
+ }
+
+ public void setBeanFactory(BeanFactory beanFactory) {
+ this.owningFactory = beanFactory;
+ }
+
+ public void postProcessBeforeInit() {
+ if (this.inited || this.initedViaDeclaredInitMethod) {
+ throw new RuntimeException("Factory called postProcessBeforeInit after afterPropertiesSet");
+ }
+ if (this.postProcessedBeforeInit) {
+ throw new RuntimeException("Factory called postProcessBeforeInit twice");
+ }
+ this.postProcessedBeforeInit = true;
+ }
+
+ public void afterPropertiesSet() {
+ if (this.owningFactory == null) {
+ throw new RuntimeException("Factory didn't call setBeanFactory before afterPropertiesSet on lifecycle bean");
+ }
+ if (!this.postProcessedBeforeInit) {
+ throw new RuntimeException("Factory didn't call postProcessBeforeInit before afterPropertiesSet on lifecycle bean");
+ }
+ if (this.initedViaDeclaredInitMethod) {
+ throw new RuntimeException("Factory initialized via declared init method before initializing via afterPropertiesSet");
+ }
+ if (this.inited) {
+ throw new RuntimeException("Factory called afterPropertiesSet twice");
+ }
+ this.inited = true;
+ }
+
+ public void declaredInitMethod() {
+ if (!this.inited) {
+ throw new RuntimeException("Factory didn't call afterPropertiesSet before declared init method");
+ }
+
+ if (this.initedViaDeclaredInitMethod) {
+ throw new RuntimeException("Factory called declared init method twice");
+ }
+ this.initedViaDeclaredInitMethod = true;
+ }
+
+ public void postProcessAfterInit() {
+ if (!this.inited) {
+ throw new RuntimeException("Factory called postProcessAfterInit before afterPropertiesSet");
+ }
+ if (this.initMethodDeclared && !this.initedViaDeclaredInitMethod) {
+ throw new RuntimeException("Factory called postProcessAfterInit before calling declared init method");
+ }
+ if (this.postProcessedAfterInit) {
+ throw new RuntimeException("Factory called postProcessAfterInit twice");
+ }
+ this.postProcessedAfterInit = true;
+ }
+
+ /**
+ * Dummy business method that will fail unless the factory
+ * managed the bean's lifecycle correctly
+ */
+ public void businessMethod() {
+ if (!this.inited || (this.initMethodDeclared && !this.initedViaDeclaredInitMethod) ||
+ !this.postProcessedAfterInit) {
+ throw new RuntimeException("Factory didn't initialize lifecycle object correctly");
+ }
+ }
+
+ public void destroy() {
+ if (this.destroyed) {
+ throw new IllegalStateException("Already destroyed");
+ }
+ this.destroyed = true;
+ }
+
+ public boolean isDestroyed() {
+ return destroyed;
+ }
+
+
+ public static class PostProcessor implements BeanPostProcessor {
+
+ public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
+ if (bean instanceof LifecycleBean) {
+ ((LifecycleBean) bean).postProcessBeforeInit();
+ }
+ return bean;
+ }
+
+ public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
+ if (bean instanceof LifecycleBean) {
+ ((LifecycleBean) bean).postProcessAfterInit();
+ }
+ return bean;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/MustBeInitialized.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/MustBeInitialized.java
new file mode 100644
index 00000000000..1dedf6624c2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/MustBeInitialized.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.factory;
+
+/**
+ * Simple test of BeanFactory initialization
+ * @author Rod Johnson
+ * @since 12.03.2003
+ */
+public class MustBeInitialized implements InitializingBean {
+
+ private boolean inited;
+
+ /**
+ * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
+ */
+ public void afterPropertiesSet() throws Exception {
+ this.inited = true;
+ }
+
+ /**
+ * Dummy business method that will fail unless the factory
+ * managed the bean's lifecycle correctly
+ */
+ public void businessMethod() {
+ if (!this.inited)
+ throw new RuntimeException("Factory didn't call afterPropertiesSet() on MustBeInitialized object");
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/PackageLevelVisibleBean.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/PackageLevelVisibleBean.java
new file mode 100644
index 00000000000..6172590caab
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/PackageLevelVisibleBean.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory;
+
+/**
+ * Used in the tests for the FieldRetrievingFactoryBean class
+ * (c.f. FieldRetrievingFactoryBeanTests)
+ *
+ * @author Rick Evans
+ */
+class PackageLevelVisibleBean {
+
+ public static final String CONSTANT = "Wuby";
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/SharedBeanRegistryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/SharedBeanRegistryTests.java
new file mode 100644
index 00000000000..0b960a36eab
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/SharedBeanRegistryTests.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory;
+
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.DerivedTestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;
+
+/**
+ * @author Juergen Hoeller
+ * @since 04.07.2006
+ */
+public class SharedBeanRegistryTests extends TestCase {
+
+ public void testSingletons() {
+ DefaultSingletonBeanRegistry beanRegistry = new DefaultSingletonBeanRegistry();
+
+ TestBean tb = new TestBean();
+ beanRegistry.registerSingleton("tb", tb);
+ assertSame(tb, beanRegistry.getSingleton("tb"));
+
+ TestBean tb2 = (TestBean) beanRegistry.getSingleton("tb2", new ObjectFactory() {
+ public Object getObject() throws BeansException {
+ return new TestBean();
+ }
+ });
+ assertSame(tb2, beanRegistry.getSingleton("tb2"));
+
+ assertSame(tb, beanRegistry.getSingleton("tb"));
+ assertSame(tb2, beanRegistry.getSingleton("tb2"));
+ assertEquals(2, beanRegistry.getSingletonCount());
+ assertEquals(2, beanRegistry.getSingletonNames().length);
+ assertTrue(Arrays.asList(beanRegistry.getSingletonNames()).contains("tb"));
+ assertTrue(Arrays.asList(beanRegistry.getSingletonNames()).contains("tb2"));
+
+ beanRegistry.destroySingletons();
+ assertEquals(0, beanRegistry.getSingletonCount());
+ assertEquals(0, beanRegistry.getSingletonNames().length);
+ }
+
+ public void testDisposableBean() {
+ DefaultSingletonBeanRegistry beanRegistry = new DefaultSingletonBeanRegistry();
+
+ DerivedTestBean tb = new DerivedTestBean();
+ beanRegistry.registerSingleton("tb", tb);
+ beanRegistry.registerDisposableBean("tb", tb);
+ assertSame(tb, beanRegistry.getSingleton("tb"));
+
+ assertSame(tb, beanRegistry.getSingleton("tb"));
+ assertEquals(1, beanRegistry.getSingletonCount());
+ assertEquals(1, beanRegistry.getSingletonNames().length);
+ assertTrue(Arrays.asList(beanRegistry.getSingletonNames()).contains("tb"));
+ assertFalse(tb.wasDestroyed());
+
+ beanRegistry.destroySingletons();
+ assertEquals(0, beanRegistry.getSingletonCount());
+ assertEquals(0, beanRegistry.getSingletonNames().length);
+ assertTrue(tb.wasDestroyed());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/access/SingletonBeanFactoryLocatorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/access/SingletonBeanFactoryLocatorTests.java
new file mode 100644
index 00000000000..cf9f7f071b8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/access/SingletonBeanFactoryLocatorTests.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.access;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.util.ClassUtils;
+
+/**
+ * @author Colin Sampaleanu
+ */
+public class SingletonBeanFactoryLocatorTests extends TestCase {
+
+ public void testBaseBeanFactoryDefs() {
+ // Just test the base BeanFactory/AppContext defs we are going to work with
+ // in other tests.
+ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
+ "/org/springframework/beans/factory/access/beans*.xml");
+ }
+
+ public void testBasicFunctionality() {
+ SingletonBeanFactoryLocator facLoc = new SingletonBeanFactoryLocator(
+ "classpath*:" + ClassUtils.addResourcePathToPackagePath(getClass(), "ref1.xml"));
+
+ basicFunctionalityTest(facLoc);
+ }
+
+ /**
+ * Worker method so subclass can use it too.
+ */
+ protected void basicFunctionalityTest(SingletonBeanFactoryLocator facLoc) {
+ BeanFactoryReference bfr = facLoc.useBeanFactory("a.qualified.name.of.some.sort");
+ BeanFactory fac = bfr.getFactory();
+ BeanFactoryReference bfr2 = facLoc.useBeanFactory("another.qualified.name");
+ fac = bfr2.getFactory();
+ // verify that the same instance is returned
+ TestBean tb = (TestBean) fac.getBean("beans1.bean1");
+ assertTrue(tb.getName().equals("beans1.bean1"));
+ tb.setName("was beans1.bean1");
+ BeanFactoryReference bfr3 = facLoc.useBeanFactory("another.qualified.name");
+ fac = bfr3.getFactory();
+ tb = (TestBean) fac.getBean("beans1.bean1");
+ assertTrue(tb.getName().equals("was beans1.bean1"));
+ BeanFactoryReference bfr4 = facLoc.useBeanFactory("a.qualified.name.which.is.an.alias");
+ fac = bfr4.getFactory();
+ tb = (TestBean) fac.getBean("beans1.bean1");
+ assertTrue(tb.getName().equals("was beans1.bean1"));
+ // Now verify that we can call release in any order.
+ // Unfortunately this doesn't validate complete release after the last one.
+ bfr2.release();
+ bfr3.release();
+ bfr.release();
+ bfr4.release();
+ }
+
+ /**
+ * This test can run multiple times, but due to static keyed lookup of the locators,
+ * 2nd and subsequent calls will actuall get back same locator instance. This is not
+ * an issue really, since the contained beanfactories will still be loaded and released.
+ */
+ public void testGetInstance() {
+ // Try with and without 'classpath*:' prefix, and with 'classpath:' prefix.
+ BeanFactoryLocator facLoc = SingletonBeanFactoryLocator.getInstance(
+ ClassUtils.addResourcePathToPackagePath(getClass(), "ref1.xml"));
+ getInstanceTest1(facLoc);
+
+ facLoc = SingletonBeanFactoryLocator.getInstance(
+ "classpath*:/" + ClassUtils.addResourcePathToPackagePath(getClass(), "ref1.xml"));
+ getInstanceTest2(facLoc);
+
+ // This will actually get another locator instance, as the key is the resource name.
+ facLoc = SingletonBeanFactoryLocator.getInstance(
+ "classpath:" + ClassUtils.addResourcePathToPackagePath(getClass(), "ref1.xml"));
+ getInstanceTest3(facLoc);
+
+ }
+
+ /**
+ * Worker method so subclass can use it too
+ */
+ protected void getInstanceTest1(BeanFactoryLocator facLoc) {
+ BeanFactoryReference bfr = facLoc.useBeanFactory("a.qualified.name.of.some.sort");
+ BeanFactory fac = bfr.getFactory();
+ BeanFactoryReference bfr2 = facLoc.useBeanFactory("another.qualified.name");
+ fac = bfr2.getFactory();
+ // verify that the same instance is returned
+ TestBean tb = (TestBean) fac.getBean("beans1.bean1");
+ assertTrue(tb.getName().equals("beans1.bean1"));
+ tb.setName("was beans1.bean1");
+ BeanFactoryReference bfr3 = facLoc.useBeanFactory("another.qualified.name");
+ fac = bfr3.getFactory();
+ tb = (TestBean) fac.getBean("beans1.bean1");
+ assertTrue(tb.getName().equals("was beans1.bean1"));
+
+ BeanFactoryReference bfr4 = facLoc.useBeanFactory("a.qualified.name.which.is.an.alias");
+ fac = bfr4.getFactory();
+ tb = (TestBean) fac.getBean("beans1.bean1");
+ assertTrue(tb.getName().equals("was beans1.bean1"));
+
+ bfr.release();
+ bfr3.release();
+ bfr2.release();
+ bfr4.release();
+ }
+
+ /**
+ * Worker method so subclass can use it too
+ */
+ protected void getInstanceTest2(BeanFactoryLocator facLoc) {
+ BeanFactoryReference bfr;
+ BeanFactory fac;
+ BeanFactoryReference bfr2;
+ TestBean tb;
+ BeanFactoryReference bfr3;
+ BeanFactoryReference bfr4;
+ bfr = facLoc.useBeanFactory("a.qualified.name.of.some.sort");
+ fac = bfr.getFactory();
+ bfr2 = facLoc.useBeanFactory("another.qualified.name");
+ fac = bfr2.getFactory();
+ // verify that the same instance is returned
+ tb = (TestBean) fac.getBean("beans1.bean1");
+ assertTrue(tb.getName().equals("beans1.bean1"));
+ tb.setName("was beans1.bean1");
+ bfr3 = facLoc.useBeanFactory("another.qualified.name");
+ fac = bfr3.getFactory();
+ tb = (TestBean) fac.getBean("beans1.bean1");
+ assertTrue(tb.getName().equals("was beans1.bean1"));
+ bfr4 = facLoc.useBeanFactory("a.qualified.name.which.is.an.alias");
+ fac = bfr4.getFactory();
+ tb = (TestBean) fac.getBean("beans1.bean1");
+ assertTrue(tb.getName().equals("was beans1.bean1"));
+ bfr.release();
+ bfr2.release();
+ bfr4.release();
+ bfr3.release();
+ }
+
+ /**
+ * Worker method so subclass can use it too
+ */
+ protected void getInstanceTest3(BeanFactoryLocator facLoc) {
+ BeanFactoryReference bfr;
+ BeanFactory fac;
+ BeanFactoryReference bfr2;
+ TestBean tb;
+ BeanFactoryReference bfr3;
+ BeanFactoryReference bfr4;
+ bfr = facLoc.useBeanFactory("a.qualified.name.of.some.sort");
+ fac = bfr.getFactory();
+ bfr2 = facLoc.useBeanFactory("another.qualified.name");
+ fac = bfr2.getFactory();
+ // verify that the same instance is returned
+ tb = (TestBean) fac.getBean("beans1.bean1");
+ assertTrue(tb.getName().equals("beans1.bean1"));
+ tb.setName("was beans1.bean1");
+ bfr3 = facLoc.useBeanFactory("another.qualified.name");
+ fac = bfr3.getFactory();
+ tb = (TestBean) fac.getBean("beans1.bean1");
+ assertTrue(tb.getName().equals("was beans1.bean1"));
+ bfr4 = facLoc.useBeanFactory("a.qualified.name.which.is.an.alias");
+ fac = bfr4.getFactory();
+ tb = (TestBean) fac.getBean("beans1.bean1");
+ assertTrue(tb.getName().equals("was beans1.bean1"));
+ bfr4.release();
+ bfr3.release();
+ bfr2.release();
+ bfr.release();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/access/TestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/access/TestBean.java
new file mode 100644
index 00000000000..27cccb45603
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/access/TestBean.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.factory.access;
+
+import java.util.List;
+
+/**
+ * Scrap bean for use in tests.
+ *
+ * @author Colin Sampaleanu
+ */
+public class TestBean {
+
+ private String name;
+
+ private List list;
+
+ private Object objRef;
+
+ /**
+ * @return Returns the name.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @param name The name to set.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @return Returns the list.
+ */
+ public List getList() {
+ return list;
+ }
+
+ /**
+ * @param list The list to set.
+ */
+ public void setList(List list) {
+ this.list = list;
+ }
+
+ /**
+ * @return Returns the object.
+ */
+ public Object getObjRef() {
+ return objRef;
+ }
+
+ /**
+ * @param object The object to set.
+ */
+ public void setObjRef(Object object) {
+ this.objRef = object;
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/access/beans1.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/access/beans1.xml
new file mode 100644
index 00000000000..10581610497
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/access/beans1.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+ beans1.bean1
+
+
+
+ bean2
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/access/beans2.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/access/beans2.xml
new file mode 100644
index 00000000000..a5167f6bfe6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/access/beans2.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+ beans2.bean1
+
+
+
+ beans2.bean2
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/access/ref1.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/access/ref1.xml
new file mode 100644
index 00000000000..a90e6063ed6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/access/ref1.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/concurrent.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/concurrent.xml
new file mode 100644
index 00000000000..c88fd668a30
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/concurrent.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/BeanFactoryPostProcessorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/BeanFactoryPostProcessorTests.java
new file mode 100644
index 00000000000..71382d98470
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/BeanFactoryPostProcessorTests.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.factory.config;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.context.support.StaticApplicationContext;
+
+/**
+ * @author Colin Sampaleanu
+ * @author Juergen Hoeller
+ * @since 02.10.2003
+ */
+public class BeanFactoryPostProcessorTests extends TestCase {
+
+ public void testRegisteredBeanFactoryPostProcessor() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ ac.registerSingleton("tb1", TestBean.class);
+ ac.registerSingleton("tb2", TestBean.class);
+ TestBeanFactoryPostProcessor bfpp = new TestBeanFactoryPostProcessor();
+ ac.addBeanFactoryPostProcessor(bfpp);
+ assertFalse(bfpp.wasCalled);
+ ac.refresh();
+ assertTrue(bfpp.wasCalled);
+ }
+
+ public void testDefinedBeanFactoryPostProcessor() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ ac.registerSingleton("tb1", TestBean.class);
+ ac.registerSingleton("tb2", TestBean.class);
+ ac.registerSingleton("bfpp", TestBeanFactoryPostProcessor.class);
+ ac.refresh();
+ TestBeanFactoryPostProcessor bfpp = (TestBeanFactoryPostProcessor) ac.getBean("bfpp");
+ assertTrue(bfpp.wasCalled);
+ }
+
+ public void testMultipleDefinedBeanFactoryPostProcessors() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ ac.registerSingleton("tb1", TestBean.class);
+ ac.registerSingleton("tb2", TestBean.class);
+ MutablePropertyValues pvs1 = new MutablePropertyValues();
+ pvs1.addPropertyValue("initValue", "${key}");
+ ac.registerSingleton("bfpp1", TestBeanFactoryPostProcessor.class, pvs1);
+ MutablePropertyValues pvs2 = new MutablePropertyValues();
+ pvs2.addPropertyValue("properties", "key=value");
+ ac.registerSingleton("bfpp2", PropertyPlaceholderConfigurer.class, pvs2);
+ ac.refresh();
+ TestBeanFactoryPostProcessor bfpp = (TestBeanFactoryPostProcessor) ac.getBean("bfpp1");
+ assertEquals("value", bfpp.initValue);
+ assertTrue(bfpp.wasCalled);
+ }
+
+ public void testBeanFactoryPostProcessorNotExecutedByBeanFactory() {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ bf.registerBeanDefinition("tb1", new RootBeanDefinition(TestBean.class));
+ bf.registerBeanDefinition("tb2", new RootBeanDefinition(TestBean.class));
+ bf.registerBeanDefinition("bfpp", new RootBeanDefinition(TestBeanFactoryPostProcessor.class));
+ TestBeanFactoryPostProcessor bfpp = (TestBeanFactoryPostProcessor) bf.getBean("bfpp");
+ assertFalse(bfpp.wasCalled);
+ }
+
+
+ public static class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
+
+ public String initValue;
+
+ public void setInitValue(String initValue) {
+ this.initValue = initValue;
+ }
+
+ public boolean wasCalled = false;
+
+ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
+ wasCalled = true;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/CommonsLogFactoryBeanTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/CommonsLogFactoryBeanTests.java
new file mode 100644
index 00000000000..b7afe8f4d0e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/CommonsLogFactoryBeanTests.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory.config;
+
+import junit.framework.TestCase;
+import org.apache.commons.logging.Log;
+import org.springframework.test.AssertThrows;
+
+/**
+ * Unit tests for the {@link CommonsLogFactoryBean} class.
+ *
+ * @author Rick Evans
+ */
+public final class CommonsLogFactoryBeanTests extends TestCase {
+
+ public void testIsSingleton() throws Exception {
+ CommonsLogFactoryBean factory = new CommonsLogFactoryBean();
+ assertTrue(factory.isSingleton());
+ }
+
+ public void testGetObjectTypeDefaultsToPlainResourceInterfaceifLookupResourceIsNotSupplied() throws Exception {
+ CommonsLogFactoryBean factory = new CommonsLogFactoryBean();
+ assertEquals(Log.class, factory.getObjectType());
+ }
+
+ public void testWhenLogNameIsMissing() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ CommonsLogFactoryBean factory = new CommonsLogFactoryBean();
+ factory.afterPropertiesSet();
+ }
+ }.runTest();
+ }
+
+ public void testSunnyDayPath() throws Exception {
+ CommonsLogFactoryBean factory = new CommonsLogFactoryBean();
+ factory.setLogName("The Tin Drum");
+ factory.afterPropertiesSet();
+ Object object = factory.getObject();
+
+ assertNotNull("As per FactoryBean contract, the return value of getObject() cannot be null.", object);
+ assertTrue("Obviously not getting a Log back", Log.class.isAssignableFrom(object.getClass()));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/CustomEditorConfigurerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/CustomEditorConfigurerTests.java
new file mode 100644
index 00000000000..df3faa10a56
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/CustomEditorConfigurerTests.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.beans.factory.config;
+
+import java.beans.PropertyEditorSupport;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.FatalBeanException;
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.beans.propertyeditors.CustomDateEditor;
+
+/**
+ * @author Juergen Hoeller
+ * @since 31.07.2004
+ */
+public class CustomEditorConfigurerTests extends TestCase {
+
+ public void testCustomEditorConfigurerWithRequiredTypeAsClassName() throws ParseException {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ CustomEditorConfigurer cec = new CustomEditorConfigurer();
+ Map editors = new HashMap();
+ DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.GERMAN);
+ editors.put(Date.class.getName(), new CustomDateEditor(df, true));
+ cec.setCustomEditors(editors);
+ cec.postProcessBeanFactory(bf);
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("date", "2.12.1975");
+ bf.registerBeanDefinition("tb1", new RootBeanDefinition(TestBean.class, pvs));
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("someMap[myKey]", new TypedStringValue("2.12.1975", Date.class));
+ bf.registerBeanDefinition("tb2", new RootBeanDefinition(TestBean.class, pvs));
+
+ TestBean tb1 = (TestBean) bf.getBean("tb1");
+ assertEquals(df.parse("2.12.1975"), tb1.getDate());
+ TestBean tb2 = (TestBean) bf.getBean("tb2");
+ assertEquals(df.parse("2.12.1975"), tb2.getSomeMap().get("myKey"));
+ }
+
+ public void testCustomEditorConfigurerWithRequiredTypeAsClass() throws ParseException {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ CustomEditorConfigurer cec = new CustomEditorConfigurer();
+ Map editors = new HashMap();
+ DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.GERMAN);
+ editors.put(Date.class, new CustomDateEditor(df, true));
+ cec.setCustomEditors(editors);
+ cec.postProcessBeanFactory(bf);
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("date", "2.12.1975");
+ bf.registerBeanDefinition("tb", new RootBeanDefinition(TestBean.class, pvs));
+
+ TestBean tb = (TestBean) bf.getBean("tb");
+ assertEquals(df.parse("2.12.1975"), tb.getDate());
+ }
+
+ public void testCustomEditorConfigurerWithEditorAsClassName() throws ParseException {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ CustomEditorConfigurer cec = new CustomEditorConfigurer();
+ Map editors = new HashMap();
+ editors.put(Date.class, MyDateEditor.class.getName());
+ cec.setCustomEditors(editors);
+ cec.postProcessBeanFactory(bf);
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("date", "2.12.1975");
+ bf.registerBeanDefinition("tb", new RootBeanDefinition(TestBean.class, pvs));
+
+ TestBean tb = (TestBean) bf.getBean("tb");
+ DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.GERMAN);
+ assertEquals(df.parse("2.12.1975"), tb.getDate());
+ }
+
+ public void testCustomEditorConfigurerWithEditorAsClass() throws ParseException {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ CustomEditorConfigurer cec = new CustomEditorConfigurer();
+ Map editors = new HashMap();
+ editors.put(Date.class, MyDateEditor.class);
+ cec.setCustomEditors(editors);
+ cec.postProcessBeanFactory(bf);
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("date", "2.12.1975");
+ bf.registerBeanDefinition("tb", new RootBeanDefinition(TestBean.class, pvs));
+
+ TestBean tb = (TestBean) bf.getBean("tb");
+ DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.GERMAN);
+ assertEquals(df.parse("2.12.1975"), tb.getDate());
+ }
+
+ public void testCustomEditorConfigurerWithRequiredTypeArray() throws ParseException {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ CustomEditorConfigurer cec = new CustomEditorConfigurer();
+ Map editors = new HashMap();
+ editors.put("java.lang.String[]", new PropertyEditorSupport() {
+ public void setAsText(String text) {
+ setValue(new String[] {"test"});
+ }
+ });
+ cec.setCustomEditors(editors);
+ cec.postProcessBeanFactory(bf);
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("stringArray", "xxx");
+ bf.registerBeanDefinition("tb", new RootBeanDefinition(TestBean.class, pvs));
+
+ TestBean tb = (TestBean) bf.getBean("tb");
+ assertTrue(tb.getStringArray() != null && tb.getStringArray().length == 1);
+ assertEquals("test", tb.getStringArray()[0]);
+ }
+
+ public void testCustomEditorConfigurerWithUnresolvableEditor() throws ParseException {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ CustomEditorConfigurer cec = new CustomEditorConfigurer();
+ Map editors = new HashMap();
+ editors.put(Date.class, "MyNonExistingEditor");
+ editors.put("MyNonExistingType", "MyNonExistingEditor");
+ cec.setCustomEditors(editors);
+ try {
+ cec.postProcessBeanFactory(bf);
+ fail("Should have thrown FatalBeanException");
+ }
+ catch (FatalBeanException ex) {
+ assertTrue(ex.getCause() instanceof ClassNotFoundException);
+ }
+ }
+
+ public void testCustomEditorConfigurerWithIgnoredUnresolvableEditor() throws ParseException {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ CustomEditorConfigurer cec = new CustomEditorConfigurer();
+ Map editors = new HashMap();
+ editors.put(Date.class, "MyNonExistingEditor");
+ editors.put("MyNonExistingType", "MyNonExistingEditor");
+ cec.setCustomEditors(editors);
+ cec.setIgnoreUnresolvableEditors(true);
+ cec.postProcessBeanFactory(bf);
+ }
+
+
+ public static class MyDateEditor extends CustomDateEditor {
+
+ public MyDateEditor() {
+ super(DateFormat.getDateInstance(DateFormat.SHORT, Locale.GERMAN), true);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/CustomScopeConfigurerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/CustomScopeConfigurerTests.java
new file mode 100644
index 00000000000..4c727011112
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/CustomScopeConfigurerTests.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.beans.factory.config;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.mock.easymock.AbstractScalarMockTemplate;
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class CustomScopeConfigurerTests extends TestCase {
+
+ private static final String FOO_SCOPE = "fooScope";
+
+
+ public void testWithNoScopes() throws Exception {
+ new ConfigurableListableBeanFactoryMockTemplate() {
+ protected void doTest(ConfigurableListableBeanFactory factory) {
+ CustomScopeConfigurer figurer = new CustomScopeConfigurer();
+ figurer.postProcessBeanFactory(factory);
+ }
+ }.test();
+ }
+
+ public void testSunnyDayWithBonaFideScopeInstance() throws Exception {
+ MockControl mockScope = MockControl.createControl(Scope.class);
+ final Scope scope = (Scope) mockScope.getMock();
+ mockScope.replay();
+ new ConfigurableListableBeanFactoryMockTemplate() {
+ public void setupExpectations(MockControl mockControl, ConfigurableListableBeanFactory factory) {
+ factory.registerScope(FOO_SCOPE, scope);
+ }
+ protected void doTest(ConfigurableListableBeanFactory factory) {
+ Map scopes = new HashMap();
+ scopes.put(FOO_SCOPE, scope);
+ CustomScopeConfigurer figurer = new CustomScopeConfigurer();
+ figurer.setScopes(scopes);
+ figurer.postProcessBeanFactory(factory);
+ }
+ }.test();
+ mockScope.verify();
+ }
+
+ public void testSunnyDayWithBonaFideScopeClass() throws Exception {
+ DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
+ Map scopes = new HashMap();
+ scopes.put(FOO_SCOPE, NoOpScope.class);
+ CustomScopeConfigurer figurer = new CustomScopeConfigurer();
+ figurer.setScopes(scopes);
+ figurer.postProcessBeanFactory(factory);
+ assertTrue(factory.getRegisteredScope(FOO_SCOPE) instanceof NoOpScope);
+ }
+
+ public void testSunnyDayWithBonaFideScopeClassname() throws Exception {
+ DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
+ Map scopes = new HashMap();
+ scopes.put(FOO_SCOPE, NoOpScope.class.getName());
+ CustomScopeConfigurer figurer = new CustomScopeConfigurer();
+ figurer.setScopes(scopes);
+ figurer.postProcessBeanFactory(factory);
+ assertTrue(factory.getRegisteredScope(FOO_SCOPE) instanceof NoOpScope);
+ }
+
+ public void testWhereScopeMapHasNullScopeValueInEntrySet() throws Exception {
+ new ConfigurableListableBeanFactoryMockTemplate() {
+ protected void doTest(final ConfigurableListableBeanFactory factory) {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ Map scopes = new HashMap();
+ scopes.put(FOO_SCOPE, null);
+ CustomScopeConfigurer figurer = new CustomScopeConfigurer();
+ figurer.setScopes(scopes);
+ figurer.postProcessBeanFactory(factory);
+ }
+ }.runTest();
+ }
+ }.test();
+ }
+
+ public void testWhereScopeMapHasNonScopeInstanceInEntrySet() throws Exception {
+ new ConfigurableListableBeanFactoryMockTemplate() {
+ protected void doTest(final ConfigurableListableBeanFactory factory) {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ Map scopes = new HashMap();
+ scopes.put(FOO_SCOPE, this); // <-- not a valid value...
+ CustomScopeConfigurer figurer = new CustomScopeConfigurer();
+ figurer.setScopes(scopes);
+ figurer.postProcessBeanFactory(factory);
+ }
+ }.runTest();
+ }
+ }.test();
+ }
+
+ public void testWhereScopeMapHasNonStringTypedScopeNameInKeySet() throws Exception {
+ new ConfigurableListableBeanFactoryMockTemplate() {
+ protected void doTest(final ConfigurableListableBeanFactory factory) {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ Map scopes = new HashMap();
+ scopes.put(this, new NoOpScope()); // <-- not a valid value (the key)...
+ CustomScopeConfigurer figurer = new CustomScopeConfigurer();
+ figurer.setScopes(scopes);
+ figurer.postProcessBeanFactory(factory);
+ }
+ }.runTest();
+ }
+ }.test();
+ }
+
+
+ private abstract class ConfigurableListableBeanFactoryMockTemplate extends AbstractScalarMockTemplate {
+
+ public ConfigurableListableBeanFactoryMockTemplate() {
+ super(ConfigurableListableBeanFactory.class);
+ }
+
+ public final void setupExpectations(MockControl mockControl, Object mockObject) throws Exception {
+ setupExpectations(mockControl, (ConfigurableListableBeanFactory) mockObject);
+ }
+
+ public final void doTest(Object mockObject) throws Exception {
+ doTest((ConfigurableListableBeanFactory) mockObject);
+ }
+
+ public void setupExpectations(MockControl mockControl, ConfigurableListableBeanFactory factory) throws Exception {
+ }
+
+ protected abstract void doTest(ConfigurableListableBeanFactory factory) throws Exception;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/FieldRetrievingFactoryBeanTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/FieldRetrievingFactoryBeanTests.java
new file mode 100644
index 00000000000..a51b2a662fe
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/FieldRetrievingFactoryBeanTests.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.config;
+
+import java.sql.Connection;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Juergen Hoeller
+ * @since 31.07.2004
+ */
+public class FieldRetrievingFactoryBeanTests extends TestCase {
+
+ public void testStaticField() throws Exception {
+ FieldRetrievingFactoryBean fr = new FieldRetrievingFactoryBean();
+ fr.setStaticField("java.sql.Connection.TRANSACTION_SERIALIZABLE");
+ fr.afterPropertiesSet();
+ assertEquals(new Integer(Connection.TRANSACTION_SERIALIZABLE), fr.getObject());
+ }
+
+ public void testStaticFieldWithWhitespace() throws Exception {
+ FieldRetrievingFactoryBean fr = new FieldRetrievingFactoryBean();
+ fr.setStaticField(" java.sql.Connection.TRANSACTION_SERIALIZABLE ");
+ fr.afterPropertiesSet();
+ assertEquals(new Integer(Connection.TRANSACTION_SERIALIZABLE), fr.getObject());
+ }
+
+ public void testStaticFieldViaClassAndFieldName() throws Exception {
+ FieldRetrievingFactoryBean fr = new FieldRetrievingFactoryBean();
+ fr.setTargetClass(Connection.class);
+ fr.setTargetField("TRANSACTION_SERIALIZABLE");
+ fr.afterPropertiesSet();
+ assertEquals(new Integer(Connection.TRANSACTION_SERIALIZABLE), fr.getObject());
+ }
+
+ public void testNonStaticField() throws Exception {
+ FieldRetrievingFactoryBean fr = new FieldRetrievingFactoryBean();
+ PublicFieldHolder target = new PublicFieldHolder();
+ fr.setTargetObject(target);
+ fr.setTargetField("publicField");
+ fr.afterPropertiesSet();
+ assertEquals(target.publicField, fr.getObject());
+ }
+
+ public void testNothingButBeanName() throws Exception {
+ FieldRetrievingFactoryBean fr = new FieldRetrievingFactoryBean();
+ fr.setBeanName("java.sql.Connection.TRANSACTION_SERIALIZABLE");
+ fr.afterPropertiesSet();
+ assertEquals(new Integer(Connection.TRANSACTION_SERIALIZABLE), fr.getObject());
+ }
+
+ public void testJustTargetField() throws Exception {
+ FieldRetrievingFactoryBean fr = new FieldRetrievingFactoryBean();
+ fr.setTargetField("TRANSACTION_SERIALIZABLE");
+ try {
+ fr.afterPropertiesSet();
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testJustTargetClass() throws Exception {
+ FieldRetrievingFactoryBean fr = new FieldRetrievingFactoryBean();
+ fr.setTargetClass(Connection.class);
+ try {
+ fr.afterPropertiesSet();
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testJustTargetObject() throws Exception {
+ FieldRetrievingFactoryBean fr = new FieldRetrievingFactoryBean();
+ fr.setTargetObject(new PublicFieldHolder());
+ try {
+ fr.afterPropertiesSet();
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testWithConstantOnClassWithPackageLevelVisibility() throws Exception {
+ FieldRetrievingFactoryBean fr = new FieldRetrievingFactoryBean();
+ fr.setBeanName("org.springframework.beans.factory.PackageLevelVisibleBean.CONSTANT");
+ fr.afterPropertiesSet();
+ assertEquals("Wuby", fr.getObject());
+ }
+
+ public void testBeanNameSyntaxWithBeanFactory() throws Exception {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ new XmlBeanDefinitionReader(bf).loadBeanDefinitions(new ClassPathResource("fieldRetrieving.xml", getClass()));
+ TestBean testBean = (TestBean) bf.getBean("testBean");
+ assertEquals(new Integer(Connection.TRANSACTION_SERIALIZABLE), testBean.getSomeIntegerArray()[0]);
+ assertEquals(new Integer(Connection.TRANSACTION_SERIALIZABLE), testBean.getSomeIntegerArray()[1]);
+ }
+
+
+ private static class PublicFieldHolder {
+
+ public String publicField = "test";
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/MethodInvokingFactoryBeanTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/MethodInvokingFactoryBeanTests.java
new file mode 100644
index 00000000000..7ef5d085704
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/MethodInvokingFactoryBeanTests.java
@@ -0,0 +1,339 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.beans.factory.config;
+
+import java.util.ArrayList;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.propertyeditors.StringTrimmerEditor;
+import org.springframework.beans.support.ArgumentConvertingMethodInvoker;
+import org.springframework.util.MethodInvoker;
+import org.springframework.util.MethodInvokerTests;
+
+/**
+ * @author Colin Sampaleanu
+ * @author Juergen Hoeller
+ * @since 21.11.2003
+ */
+public class MethodInvokingFactoryBeanTests extends TestCase {
+
+ public void testParameterValidation() throws Exception {
+ String validationError = "improper validation of input properties";
+
+ // assert that only static OR non static are set, but not both or none
+ MethodInvokingFactoryBean mcfb = new MethodInvokingFactoryBean();
+ try {
+ mcfb.afterPropertiesSet();
+ fail(validationError);
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+
+ mcfb = new MethodInvokingFactoryBean();
+ mcfb.setTargetObject(this);
+ mcfb.setTargetMethod("whatever");
+ try {
+ mcfb.afterPropertiesSet();
+ fail(validationError);
+ }
+ catch (NoSuchMethodException ex) {
+ // expected
+ }
+
+ // bogus static method
+ mcfb = new MethodInvokingFactoryBean();
+ mcfb.setTargetClass(MethodInvokerTests.TestClass1.class);
+ mcfb.setTargetMethod("some.bogus.Method.name");
+ try {
+ mcfb.afterPropertiesSet();
+ fail(validationError);
+ }
+ catch (NoSuchMethodException ex) {
+ // expected
+ }
+
+ // bogus static method
+ mcfb = new MethodInvokingFactoryBean();
+ mcfb.setTargetClass(MethodInvokerTests.TestClass1.class);
+ mcfb.setTargetMethod("method1");
+ try {
+ mcfb.afterPropertiesSet();
+ fail(validationError);
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+
+ // missing method
+ mcfb = new MethodInvokingFactoryBean();
+ mcfb.setTargetObject(this);
+ try {
+ mcfb.afterPropertiesSet();
+ fail(validationError);
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+
+ // bogus method
+ mcfb = new MethodInvokingFactoryBean();
+ mcfb.setTargetObject(this);
+ mcfb.setTargetMethod("bogus");
+ try {
+ mcfb.afterPropertiesSet();
+ fail(validationError);
+ }
+ catch (NoSuchMethodException ex) {
+ // expected
+ }
+
+ // static method
+ MethodInvokerTests.TestClass1._staticField1 = 0;
+ mcfb = new MethodInvokingFactoryBean();
+ mcfb.setTargetClass(MethodInvokerTests.TestClass1.class);
+ mcfb.setTargetMethod("staticMethod1");
+ mcfb.afterPropertiesSet();
+
+ // non-static method
+ MethodInvokerTests.TestClass1 tc1 = new MethodInvokerTests.TestClass1();
+ mcfb = new MethodInvokingFactoryBean();
+ mcfb.setTargetObject(tc1);
+ mcfb.setTargetMethod("method1");
+ mcfb.afterPropertiesSet();
+ }
+
+ public void testGetObjectType() throws Exception {
+ MethodInvokerTests.TestClass1 tc1 = new MethodInvokerTests.TestClass1();
+ MethodInvokingFactoryBean mcfb = new MethodInvokingFactoryBean();
+ mcfb = new MethodInvokingFactoryBean();
+ mcfb.setTargetObject(tc1);
+ mcfb.setTargetMethod("method1");
+ mcfb.afterPropertiesSet();
+ assertTrue(int.class.equals(mcfb.getObjectType()));
+
+ mcfb = new MethodInvokingFactoryBean();
+ mcfb.setTargetClass(MethodInvokerTests.TestClass1.class);
+ mcfb.setTargetMethod("voidRetvalMethod");
+ mcfb.afterPropertiesSet();
+ Class objType = mcfb.getObjectType();
+ assertTrue(objType.equals(void.class));
+
+ // verify that we can call a method with args that are subtypes of the
+ // target method arg types
+ MethodInvokerTests.TestClass1._staticField1 = 0;
+ mcfb = new MethodInvokingFactoryBean();
+ mcfb.setTargetClass(MethodInvokerTests.TestClass1.class);
+ mcfb.setTargetMethod("supertypes");
+ mcfb.setArguments(new Object[] {new ArrayList(), new ArrayList(), "hello"});
+ mcfb.afterPropertiesSet();
+ mcfb.getObjectType();
+
+ // fail on improper argument types at afterPropertiesSet
+ mcfb = new MethodInvokingFactoryBean();
+ mcfb.registerCustomEditor(String.class, new StringTrimmerEditor(false));
+ mcfb.setTargetClass(MethodInvokerTests.TestClass1.class);
+ mcfb.setTargetMethod("supertypes");
+ mcfb.setArguments(new Object[] {"1", new Object()});
+ try {
+ mcfb.afterPropertiesSet();
+ fail("Should have thrown NoSuchMethodException");
+ }
+ catch (NoSuchMethodException ex) {
+ // expected
+ }
+ }
+
+ public void testGetObject() throws Exception {
+ // singleton, non-static
+ MethodInvokerTests.TestClass1 tc1 = new MethodInvokerTests.TestClass1();
+ MethodInvokingFactoryBean mcfb = new MethodInvokingFactoryBean();
+ mcfb.setTargetObject(tc1);
+ mcfb.setTargetMethod("method1");
+ mcfb.afterPropertiesSet();
+ Integer i = (Integer) mcfb.getObject();
+ assertEquals(1, i.intValue());
+ i = (Integer) mcfb.getObject();
+ assertEquals(1, i.intValue());
+
+ // non-singleton, non-static
+ tc1 = new MethodInvokerTests.TestClass1();
+ mcfb = new MethodInvokingFactoryBean();
+ mcfb.setTargetObject(tc1);
+ mcfb.setTargetMethod("method1");
+ mcfb.setSingleton(false);
+ mcfb.afterPropertiesSet();
+ i = (Integer) mcfb.getObject();
+ assertEquals(1, i.intValue());
+ i = (Integer) mcfb.getObject();
+ assertEquals(2, i.intValue());
+
+ // singleton, static
+ MethodInvokerTests.TestClass1._staticField1 = 0;
+ mcfb = new MethodInvokingFactoryBean();
+ mcfb.setTargetClass(MethodInvokerTests.TestClass1.class);
+ mcfb.setTargetMethod("staticMethod1");
+ mcfb.afterPropertiesSet();
+ i = (Integer) mcfb.getObject();
+ assertEquals(1, i.intValue());
+ i = (Integer) mcfb.getObject();
+ assertEquals(1, i.intValue());
+
+ // non-singleton, static
+ MethodInvokerTests.TestClass1._staticField1 = 0;
+ mcfb = new MethodInvokingFactoryBean();
+ mcfb.setStaticMethod("org.springframework.util.MethodInvokerTests$TestClass1.staticMethod1");
+ mcfb.setSingleton(false);
+ mcfb.afterPropertiesSet();
+ i = (Integer) mcfb.getObject();
+ assertEquals(1, i.intValue());
+ i = (Integer) mcfb.getObject();
+ assertEquals(2, i.intValue());
+
+ // void return value
+ mcfb = new MethodInvokingFactoryBean();
+ mcfb.setTargetClass(MethodInvokerTests.TestClass1.class);
+ mcfb.setTargetMethod("voidRetvalMethod");
+ mcfb.afterPropertiesSet();
+ assertNull(mcfb.getObject());
+
+ // now see if we can match methods with arguments that have supertype arguments
+ mcfb = new MethodInvokingFactoryBean();
+ mcfb.setTargetClass(MethodInvokerTests.TestClass1.class);
+ mcfb.setTargetMethod("supertypes");
+ mcfb.setArguments(new Object[] {new ArrayList(), new ArrayList(), "hello"});
+ // should pass
+ mcfb.afterPropertiesSet();
+ }
+
+ public void testArgumentConversion() throws Exception {
+ MethodInvokingFactoryBean mcfb = new MethodInvokingFactoryBean();
+ mcfb.setTargetClass(MethodInvokerTests.TestClass1.class);
+ mcfb.setTargetMethod("supertypes");
+ mcfb.setArguments(new Object[] {new ArrayList(), new ArrayList(), "hello", "bogus"});
+ try {
+ mcfb.afterPropertiesSet();
+ fail("Matched method with wrong number of args");
+ }
+ catch (NoSuchMethodException ex) {
+ // expected
+ }
+
+ mcfb = new MethodInvokingFactoryBean();
+ mcfb.setTargetClass(MethodInvokerTests.TestClass1.class);
+ mcfb.setTargetMethod("supertypes");
+ mcfb.setArguments(new Object[] {new Integer(1), new Object()});
+ try {
+ mcfb.afterPropertiesSet();
+ mcfb.getObject();
+ fail("Should have failed on getObject with mismatched argument types");
+ }
+ catch (NoSuchMethodException ex) {
+ // expected
+ }
+
+ mcfb = new MethodInvokingFactoryBean();
+ mcfb.setTargetClass(MethodInvokerTests.TestClass1.class);
+ mcfb.setTargetMethod("supertypes2");
+ mcfb.setArguments(new Object[] {new ArrayList(), new ArrayList(), "hello", "bogus"});
+ mcfb.afterPropertiesSet();
+ assertEquals("hello", mcfb.getObject());
+
+ mcfb = new MethodInvokingFactoryBean();
+ mcfb.setTargetClass(MethodInvokerTests.TestClass1.class);
+ mcfb.setTargetMethod("supertypes2");
+ mcfb.setArguments(new Object[] {new ArrayList(), new ArrayList(), new Object()});
+ try {
+ mcfb.afterPropertiesSet();
+ fail("Matched method when shouldn't have matched");
+ }
+ catch (NoSuchMethodException ex) {
+ // expected
+ }
+ }
+
+ public void testInvokeWithNullArgument() throws Exception {
+ MethodInvoker methodInvoker = new MethodInvoker();
+ methodInvoker.setTargetClass(MethodInvokerTests.TestClass1.class);
+ methodInvoker.setTargetMethod("nullArgument");
+ methodInvoker.setArguments(new Object[] {null});
+ methodInvoker.prepare();
+ methodInvoker.invoke();
+ }
+
+ public void testInvokeWithIntArgument() throws Exception {
+ ArgumentConvertingMethodInvoker methodInvoker = new ArgumentConvertingMethodInvoker();
+ methodInvoker.setTargetClass(MethodInvokerTests.TestClass1.class);
+ methodInvoker.setTargetMethod("intArgument");
+ methodInvoker.setArguments(new Object[] {new Integer(5)});
+ methodInvoker.prepare();
+ methodInvoker.invoke();
+
+ methodInvoker = new ArgumentConvertingMethodInvoker();
+ methodInvoker.setTargetClass(MethodInvokerTests.TestClass1.class);
+ methodInvoker.setTargetMethod("intArgument");
+ methodInvoker.setArguments(new Object[] {"5"});
+ methodInvoker.prepare();
+ methodInvoker.invoke();
+ }
+
+ public void testInvokeWithIntArguments() throws Exception {
+ ArgumentConvertingMethodInvoker methodInvoker = new ArgumentConvertingMethodInvoker();
+ methodInvoker.setTargetClass(MethodInvokerTests.TestClass1.class);
+ methodInvoker.setTargetMethod("intArguments");
+ methodInvoker.setArguments(new Object[] {new Integer[] {new Integer(5), new Integer(10)}});
+ methodInvoker.prepare();
+ methodInvoker.invoke();
+
+ methodInvoker = new ArgumentConvertingMethodInvoker();
+ methodInvoker.setTargetClass(MethodInvokerTests.TestClass1.class);
+ methodInvoker.setTargetMethod("intArguments");
+ methodInvoker.setArguments(new Object[] {new String[] {"5", "10"}});
+ methodInvoker.prepare();
+ methodInvoker.invoke();
+
+ methodInvoker = new ArgumentConvertingMethodInvoker();
+ methodInvoker.setTargetClass(MethodInvokerTests.TestClass1.class);
+ methodInvoker.setTargetMethod("intArguments");
+ methodInvoker.setArguments(new Integer[] {new Integer(5), new Integer(10)});
+ methodInvoker.prepare();
+ methodInvoker.invoke();
+
+ methodInvoker = new ArgumentConvertingMethodInvoker();
+ methodInvoker.setTargetClass(MethodInvokerTests.TestClass1.class);
+ methodInvoker.setTargetMethod("intArguments");
+ methodInvoker.setArguments(new String[] {"5", "10"});
+ methodInvoker.prepare();
+ methodInvoker.invoke();
+
+ methodInvoker = new ArgumentConvertingMethodInvoker();
+ methodInvoker.setTargetClass(MethodInvokerTests.TestClass1.class);
+ methodInvoker.setTargetMethod("intArguments");
+ methodInvoker.setArguments(new Object[] {new Integer(5), new Integer(10)});
+ methodInvoker.prepare();
+ methodInvoker.invoke();
+
+ methodInvoker = new ArgumentConvertingMethodInvoker();
+ methodInvoker.setTargetClass(MethodInvokerTests.TestClass1.class);
+ methodInvoker.setTargetMethod("intArguments");
+ methodInvoker.setArguments(new Object[] {"5", "10"});
+ methodInvoker.prepare();
+ methodInvoker.invoke();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/NoOpScope.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/NoOpScope.java
new file mode 100644
index 00000000000..c681dabc7a1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/NoOpScope.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.config;
+
+import org.springframework.beans.factory.ObjectFactory;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class NoOpScope implements Scope {
+
+ public Object get(String name, ObjectFactory objectFactory) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object remove(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void registerDestructionCallback(String name, Runnable callback) {
+ }
+
+ public String getConversationId() {
+ return null;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/ObjectFactoryCreatingFactoryBeanTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/ObjectFactoryCreatingFactoryBeanTests.java
new file mode 100644
index 00000000000..b5a2d687b86
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/ObjectFactoryCreatingFactoryBeanTests.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory.config;
+
+import java.util.Date;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.ObjectFactory;
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+import org.easymock.MockControl;
+
+/**
+ * Unit tests for the ObjectFactoryCreatingFactoryBean class.
+ *
+ * @author Colin Sampaleanu
+ * @author Rick Evans
+ * @since 2004-05-11
+ */
+public final class ObjectFactoryCreatingFactoryBeanTests extends TestCase {
+
+ private BeanFactory beanFactory;
+
+
+ protected void setUp() throws Exception {
+ this.beanFactory = new XmlBeanFactory(new ClassPathResource(
+ "ObjectFactoryCreatingFactoryBeanTests.xml", getClass()));
+ }
+
+
+ public void testBasicOperation() throws BeansException {
+ TestBean testBean = (TestBean) beanFactory.getBean("testBean");
+ ObjectFactory objectFactory = testBean.getObjectFactory();
+
+ Date date1 = (Date) objectFactory.getObject();
+ Date date2 = (Date) objectFactory.getObject();
+ assertTrue(date1 != date2);
+ }
+
+ public void testDoesNotComplainWhenTargetBeanNameRefersToSingleton() throws Exception {
+ final String targetBeanName = "singleton";
+ final String expectedSingleton = "Alicia Keys";
+
+ MockControl mock = MockControl.createControl(BeanFactory.class);
+ BeanFactory beanFactory = (BeanFactory) mock.getMock();
+ beanFactory.getBean(targetBeanName);
+ mock.setReturnValue(expectedSingleton);
+ mock.replay();
+
+ ObjectFactoryCreatingFactoryBean factory = new ObjectFactoryCreatingFactoryBean();
+ factory.setTargetBeanName(targetBeanName);
+ factory.setBeanFactory(beanFactory);
+ factory.afterPropertiesSet();
+ ObjectFactory objectFactory = (ObjectFactory) factory.getObject();
+ Object actualSingleton = objectFactory.getObject();
+ assertSame(expectedSingleton, actualSingleton);
+
+ mock.verify();
+ }
+
+ public void testWhenTargetBeanNameIsNull() throws Exception {
+ try {
+ new ObjectFactoryCreatingFactoryBean().afterPropertiesSet();
+ fail("Must have thrown an IllegalArgumentException; 'targetBeanName' property not set.");
+ }
+ catch (IllegalArgumentException expected) {}
+ }
+
+ public void testWhenTargetBeanNameIsEmptyString() throws Exception {
+ try {
+ ObjectFactoryCreatingFactoryBean factory = new ObjectFactoryCreatingFactoryBean();
+ factory.setTargetBeanName("");
+ factory.afterPropertiesSet();
+ fail("Must have thrown an IllegalArgumentException; 'targetBeanName' property set to (invalid) empty string.");
+ }
+ catch (IllegalArgumentException expected) {}
+ }
+
+ public void testWhenTargetBeanNameIsWhitespacedString() throws Exception {
+ try {
+ ObjectFactoryCreatingFactoryBean factory = new ObjectFactoryCreatingFactoryBean();
+ factory.setTargetBeanName(" \t");
+ factory.afterPropertiesSet();
+ fail("Must have thrown an IllegalArgumentException; 'targetBeanName' property set to (invalid) only-whitespace string.");
+ }
+ catch (IllegalArgumentException expected) {}
+ }
+
+ public void testEnsureOFBFBReportsThatItActuallyCreatesObjectFactoryInstances() throws Exception {
+ assertEquals("Must be reporting that it creates ObjectFactory instances (as per class contract).",
+ ObjectFactory.class, new ObjectFactoryCreatingFactoryBean().getObjectType());
+ }
+
+
+ public static class TestBean {
+
+ public ObjectFactory objectFactory;
+
+
+ public ObjectFactory getObjectFactory() {
+ return objectFactory;
+ }
+
+ public void setObjectFactory(ObjectFactory objectFactory) {
+ this.objectFactory = objectFactory;
+ }
+
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/ObjectFactoryCreatingFactoryBeanTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/ObjectFactoryCreatingFactoryBeanTests.xml
new file mode 100644
index 00000000000..92a011c3437
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/ObjectFactoryCreatingFactoryBeanTests.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/PropertiesFactoryBeanTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/PropertiesFactoryBeanTests.java
new file mode 100644
index 00000000000..d01ef9002fb
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/PropertiesFactoryBeanTests.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory.config;
+
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+import org.springframework.core.JdkVersion;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Juergen Hoeller
+ * @since 01.11.2003
+ */
+public class PropertiesFactoryBeanTests extends TestCase {
+
+ public void testWithPropertiesFile() throws Exception {
+ PropertiesFactoryBean pfb = new PropertiesFactoryBean();
+ pfb.setLocation(new ClassPathResource("/org/springframework/beans/factory/config/test.properties"));
+ pfb.afterPropertiesSet();
+ Properties props = (Properties) pfb.getObject();
+ assertEquals("99", props.getProperty("tb.array[0].age"));
+ }
+
+ public void testWithPropertiesXmlFile() throws Exception {
+ // ignore for JDK < 1.5
+ if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_15) {
+ return;
+ }
+
+ PropertiesFactoryBean pfb = new PropertiesFactoryBean();
+ pfb.setLocation(new ClassPathResource("/org/springframework/beans/factory/config/test-properties.xml"));
+ pfb.afterPropertiesSet();
+ Properties props = (Properties) pfb.getObject();
+ assertEquals("99", props.getProperty("tb.array[0].age"));
+ }
+
+ public void testWithLocalProperties() throws Exception {
+ PropertiesFactoryBean pfb = new PropertiesFactoryBean();
+ Properties localProps = new Properties();
+ localProps.setProperty("key2", "value2");
+ pfb.setProperties(localProps);
+ pfb.afterPropertiesSet();
+ Properties props = (Properties) pfb.getObject();
+ assertEquals("value2", props.getProperty("key2"));
+ }
+
+ public void testWithPropertiesFileAndLocalProperties() throws Exception {
+ PropertiesFactoryBean pfb = new PropertiesFactoryBean();
+ pfb.setLocation(new ClassPathResource("/org/springframework/beans/factory/config/test.properties"));
+ Properties localProps = new Properties();
+ localProps.setProperty("key2", "value2");
+ localProps.setProperty("tb.array[0].age", "0");
+ pfb.setProperties(localProps);
+ pfb.afterPropertiesSet();
+ Properties props = (Properties) pfb.getObject();
+ assertEquals("99", props.getProperty("tb.array[0].age"));
+ assertEquals("value2", props.getProperty("key2"));
+ }
+
+ public void testWithPropertiesFileAndMultipleLocalProperties() throws Exception {
+ PropertiesFactoryBean pfb = new PropertiesFactoryBean();
+ pfb.setLocation(new ClassPathResource("/org/springframework/beans/factory/config/test.properties"));
+
+ Properties props1 = new Properties();
+ props1.setProperty("key2", "value2");
+ props1.setProperty("tb.array[0].age", "0");
+
+ Properties props2 = new Properties();
+ props2.setProperty("spring", "framework");
+ props2.setProperty("Don", "Mattingly");
+
+ Properties props3 = new Properties();
+ props3.setProperty("spider", "man");
+ props3.setProperty("bat", "man");
+
+ pfb.setPropertiesArray(new Properties[] {props1, props2, props3});
+ pfb.afterPropertiesSet();
+
+ Properties props = (Properties) pfb.getObject();
+ assertEquals("99", props.getProperty("tb.array[0].age"));
+ assertEquals("value2", props.getProperty("key2"));
+ assertEquals("framework", props.getProperty("spring"));
+ assertEquals("Mattingly", props.getProperty("Don"));
+ assertEquals("man", props.getProperty("spider"));
+ assertEquals("man", props.getProperty("bat"));
+ }
+
+ public void testWithPropertiesFileAndLocalPropertiesAndLocalOverride() throws Exception {
+ PropertiesFactoryBean pfb = new PropertiesFactoryBean();
+ pfb.setLocation(new ClassPathResource("/org/springframework/beans/factory/config/test.properties"));
+ Properties localProps = new Properties();
+ localProps.setProperty("key2", "value2");
+ localProps.setProperty("tb.array[0].age", "0");
+ pfb.setProperties(localProps);
+ pfb.setLocalOverride(true);
+ pfb.afterPropertiesSet();
+ Properties props = (Properties) pfb.getObject();
+ assertEquals("0", props.getProperty("tb.array[0].age"));
+ assertEquals("value2", props.getProperty("key2"));
+ }
+
+ public void testWithPrototype() throws Exception {
+ PropertiesFactoryBean pfb = new PropertiesFactoryBean();
+ pfb.setSingleton(false);
+ pfb.setLocation(new ClassPathResource("/org/springframework/beans/factory/config/test.properties"));
+ Properties localProps = new Properties();
+ localProps.setProperty("key2", "value2");
+ pfb.setProperties(localProps);
+ pfb.afterPropertiesSet();
+ Properties props = (Properties) pfb.getObject();
+ assertEquals("99", props.getProperty("tb.array[0].age"));
+ assertEquals("value2", props.getProperty("key2"));
+ Properties newProps = (Properties) pfb.getObject();
+ assertTrue(props != newProps);
+ assertEquals("99", newProps.getProperty("tb.array[0].age"));
+ assertEquals("value2", newProps.getProperty("key2"));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/PropertyPathFactoryBeanTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/PropertyPathFactoryBeanTests.java
new file mode 100644
index 00000000000..ec6fae46b5e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/PropertyPathFactoryBeanTests.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.config;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Juergen Hoeller
+ * @since 04.10.2004
+ */
+public class PropertyPathFactoryBeanTests extends TestCase {
+
+ public void testPropertyPathFactoryBeanWithSingletonResult() {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("propertyPath.xml", getClass()));
+ assertEquals(new Integer(12), xbf.getBean("propertyPath1"));
+ assertEquals(new Integer(11), xbf.getBean("propertyPath2"));
+ assertEquals(new Integer(10), xbf.getBean("tb.age"));
+ assertEquals(ITestBean.class, xbf.getType("otb.spouse"));
+ Object result1 = xbf.getBean("otb.spouse");
+ Object result2 = xbf.getBean("otb.spouse");
+ assertTrue(result1 instanceof TestBean);
+ assertTrue(result1 == result2);
+ assertEquals(99, ((TestBean) result1).getAge());
+ }
+
+ public void testPropertyPathFactoryBeanWithPrototypeResult() {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("propertyPath.xml", getClass()));
+ assertNull(xbf.getType("tb.spouse"));
+ assertEquals(TestBean.class, xbf.getType("propertyPath3"));
+ Object result1 = xbf.getBean("tb.spouse");
+ Object result2 = xbf.getBean("propertyPath3");
+ Object result3 = xbf.getBean("propertyPath3");
+ assertTrue(result1 instanceof TestBean);
+ assertTrue(result2 instanceof TestBean);
+ assertTrue(result3 instanceof TestBean);
+ assertEquals(11, ((TestBean) result1).getAge());
+ assertEquals(11, ((TestBean) result2).getAge());
+ assertEquals(11, ((TestBean) result3).getAge());
+ assertTrue(result1 != result2);
+ assertTrue(result1 != result3);
+ assertTrue(result2 != result3);
+ }
+
+ public void testPropertyPathFactoryBeanWithNullResult() {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("propertyPath.xml", getClass()));
+ assertNull(xbf.getType("tb.spouse.spouse"));
+ assertNull(xbf.getBean("tb.spouse.spouse"));
+ }
+
+ public void testPropertyPathFactoryBeanAsInnerBean() {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("propertyPath.xml", getClass()));
+ TestBean spouse = (TestBean) xbf.getBean("otb.spouse");
+ TestBean tbWithInner = (TestBean) xbf.getBean("tbWithInner");
+ assertSame(spouse, tbWithInner.getSpouse());
+ assertTrue(!tbWithInner.getFriends().isEmpty());
+ assertSame(spouse, tbWithInner.getFriends().iterator().next());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/PropertyResourceConfigurerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/PropertyResourceConfigurerTests.java
new file mode 100644
index 00000000000..2296d5bcf27
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/PropertyResourceConfigurerTests.java
@@ -0,0 +1,715 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.beans.factory.config;
+
+import java.io.FileNotFoundException;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.prefs.Preferences;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.framework.ProxyFactoryBean;
+import org.springframework.beans.IndexedTestBean;
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.BeanDefinitionStoreException;
+import org.springframework.beans.factory.BeanInitializationException;
+import org.springframework.beans.factory.support.ChildBeanDefinition;
+import org.springframework.beans.factory.support.ManagedList;
+import org.springframework.beans.factory.support.ManagedMap;
+import org.springframework.beans.factory.support.ManagedSet;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.context.support.StaticApplicationContext;
+import org.springframework.core.JdkVersion;
+import org.springframework.mail.javamail.JavaMailSenderImpl;
+import org.springframework.util.StringUtils;
+
+/**
+ * @author Juergen Hoeller
+ * @since 02.10.2003
+ */
+public class PropertyResourceConfigurerTests extends TestCase {
+
+ public void testPropertyOverrideConfigurer() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ ac.registerSingleton("tb1", TestBean.class);
+ ac.registerSingleton("tb2", TestBean.class);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", "tb1.age=99\ntb2.name=test");
+ ac.registerSingleton("configurer1", PropertyOverrideConfigurer.class, pvs);
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", "tb2.age=99\ntb2.name=test2");
+ pvs.addPropertyValue("order", "0");
+ ac.registerSingleton("configurer2", PropertyOverrideConfigurer.class, pvs);
+ ac.refresh();
+ TestBean tb1 = (TestBean) ac.getBean("tb1");
+ TestBean tb2 = (TestBean) ac.getBean("tb2");
+ assertEquals(99, tb1.getAge());
+ assertEquals(99, tb2.getAge());
+ assertEquals(null, tb1.getName());
+ assertEquals("test", tb2.getName());
+ }
+
+ public void testPropertyOverrideConfigurerWithNestedProperty() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ ac.registerSingleton("tb", IndexedTestBean.class);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", "tb.array[0].age=99\ntb.list[1].name=test");
+ ac.registerSingleton("configurer", PropertyOverrideConfigurer.class, pvs);
+ ac.refresh();
+ IndexedTestBean tb = (IndexedTestBean) ac.getBean("tb");
+ assertEquals(99, tb.getArray()[0].getAge());
+ assertEquals("test", ((TestBean) tb.getList().get(1)).getName());
+ }
+
+ public void testPropertyOverrideConfigurerWithNestedPropertyAndDotInBeanName() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ ac.registerSingleton("my.tb", IndexedTestBean.class);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", "my.tb_array[0].age=99\nmy.tb_list[1].name=test");
+ pvs.addPropertyValue("beanNameSeparator", "_");
+ ac.registerSingleton("configurer", PropertyOverrideConfigurer.class, pvs);
+ ac.refresh();
+ IndexedTestBean tb = (IndexedTestBean) ac.getBean("my.tb");
+ assertEquals(99, tb.getArray()[0].getAge());
+ assertEquals("test", ((TestBean) tb.getList().get(1)).getName());
+ }
+
+ public void testPropertyOverrideConfigurerWithNestedMapPropertyAndDotInMapKey() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ ac.registerSingleton("tb", IndexedTestBean.class);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", "tb.map[key1]=99\ntb.map[key2.ext]=test");
+ ac.registerSingleton("configurer", PropertyOverrideConfigurer.class, pvs);
+ ac.refresh();
+ IndexedTestBean tb = (IndexedTestBean) ac.getBean("tb");
+ assertEquals("99", tb.getMap().get("key1"));
+ assertEquals("test", tb.getMap().get("key2.ext"));
+ }
+
+ public void testPropertyOverrideConfigurerWithJavaMailProperties() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ ac.registerSingleton("tb", JavaMailSenderImpl.class);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", "tb.javaMailProperties[mail.smtp.auth]=true");
+ ac.registerSingleton("configurer", PropertyOverrideConfigurer.class, pvs);
+ ac.refresh();
+ JavaMailSenderImpl tb = (JavaMailSenderImpl) ac.getBean("tb");
+ assertEquals("true", tb.getJavaMailProperties().getProperty("mail.smtp.auth"));
+ }
+
+ public void testPropertyOverrideConfigurerWithPropertiesFile() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ ac.registerSingleton("tb", IndexedTestBean.class);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("location", "classpath:org/springframework/beans/factory/config/test.properties");
+ ac.registerSingleton("configurer", PropertyOverrideConfigurer.class, pvs);
+ ac.refresh();
+ IndexedTestBean tb = (IndexedTestBean) ac.getBean("tb");
+ assertEquals(99, tb.getArray()[0].getAge());
+ assertEquals("test", ((TestBean) tb.getList().get(1)).getName());
+ }
+
+ public void testPropertyOverrideConfigurerWithInvalidPropertiesFile() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ ac.registerSingleton("tb", IndexedTestBean.class);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("locations",
+ new String[] {"classpath:org/springframework/beans/factory/config/test.properties",
+ "classpath:org/springframework/beans/factory/config/xtest.properties"});
+ pvs.addPropertyValue("ignoreResourceNotFound", Boolean.TRUE);
+ ac.registerSingleton("configurer", PropertyOverrideConfigurer.class, pvs);
+ ac.refresh();
+ IndexedTestBean tb = (IndexedTestBean) ac.getBean("tb");
+ assertEquals(99, tb.getArray()[0].getAge());
+ assertEquals("test", ((TestBean) tb.getList().get(1)).getName());
+ }
+
+ public void testPropertyOverrideConfigurerWithPropertiesXmlFile() {
+ // ignore for JDK < 1.5
+ if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_15) {
+ return;
+ }
+
+ StaticApplicationContext ac = new StaticApplicationContext();
+ ac.registerSingleton("tb", IndexedTestBean.class);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("location", "classpath:org/springframework/beans/factory/config/test-properties.xml");
+ ac.registerSingleton("configurer", PropertyOverrideConfigurer.class, pvs);
+ ac.refresh();
+ IndexedTestBean tb = (IndexedTestBean) ac.getBean("tb");
+ assertEquals(99, tb.getArray()[0].getAge());
+ assertEquals("test", ((TestBean) tb.getList().get(1)).getName());
+ }
+
+ public void testPropertyOverrideConfigurerWithConvertProperties() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ ac.registerSingleton("tb", IndexedTestBean.class);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", "tb.array[0].name=99\ntb.list[1].name=test");
+ ac.registerSingleton("configurer", ConvertingOverrideConfigurer.class, pvs);
+ ac.refresh();
+ IndexedTestBean tb = (IndexedTestBean) ac.getBean("tb");
+ assertEquals("X99", tb.getArray()[0].getName());
+ assertEquals("Xtest", ((TestBean) tb.getList().get(1)).getName());
+ }
+
+ public void testPropertyOverrideConfigurerWithInvalidKey() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ ac.registerSingleton("tb1", TestBean.class);
+ ac.registerSingleton("tb2", TestBean.class);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", "argh=hgra\ntb1.age=99\ntb2.name=test");
+ pvs.addPropertyValue("ignoreInvalidKeys", "true");
+ ac.registerSingleton("configurer1", PropertyOverrideConfigurer.class, pvs);
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", "tb2.age=99\ntb2.name=test2");
+ pvs.addPropertyValue("order", "0");
+ ac.registerSingleton("configurer2", PropertyOverrideConfigurer.class, pvs);
+ try {
+ ac.refresh();
+ }
+ catch (BeanInitializationException ex) {
+ assertTrue(ex.getMessage().toLowerCase().indexOf("argh") != -1);
+ }
+ }
+
+ public void testPropertyOverrideConfigurerWithIgnoreInvalidKeys() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ ac.registerSingleton("tb1", TestBean.class);
+ ac.registerSingleton("tb2", TestBean.class);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", "argh=hgra\ntb1.age=99\ntb2.name=test");
+ pvs.addPropertyValue("ignoreInvalidKeys", "true");
+ ac.registerSingleton("configurer1", PropertyOverrideConfigurer.class, pvs);
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", "tb2.age=99\ntb2.name=test2");
+ pvs.addPropertyValue("order", "0");
+ ac.registerSingleton("configurer2", PropertyOverrideConfigurer.class, pvs);
+ ac.refresh();
+ TestBean tb1 = (TestBean) ac.getBean("tb1");
+ TestBean tb2 = (TestBean) ac.getBean("tb2");
+ assertEquals(99, tb1.getAge());
+ assertEquals(99, tb2.getAge());
+ assertEquals(null, tb1.getName());
+ assertEquals("test", tb2.getName());
+ }
+
+ public void testPropertyPlaceholderConfigurer() {
+ doTestPropertyPlaceholderConfigurer(false);
+ }
+
+ public void testPropertyPlaceholderConfigurerWithParentChildSeparation() {
+ doTestPropertyPlaceholderConfigurer(true);
+ }
+
+ private void doTestPropertyPlaceholderConfigurer(boolean parentChildSeparation) {
+ StaticApplicationContext ac = new StaticApplicationContext();
+
+ if (parentChildSeparation) {
+ MutablePropertyValues pvs1 = new MutablePropertyValues();
+ pvs1.addPropertyValue("age", "${age}");
+ MutablePropertyValues pvs2 = new MutablePropertyValues();
+ pvs2.addPropertyValue("name", "name${var}${var}${");
+ pvs2.addPropertyValue("spouse", new RuntimeBeanReference("${ref}"));
+
+ RootBeanDefinition parent = new RootBeanDefinition(TestBean.class, pvs1);
+ ChildBeanDefinition bd = new ChildBeanDefinition("${parent}", pvs2);
+ ac.getDefaultListableBeanFactory().registerBeanDefinition("parent1", parent);
+ ac.getDefaultListableBeanFactory().registerBeanDefinition("tb1", bd);
+ }
+ else {
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("age", "${age}");
+ pvs.addPropertyValue("name", "name${var}${var}${");
+ pvs.addPropertyValue("spouse", new RuntimeBeanReference("${ref}"));
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, pvs);
+ ac.getDefaultListableBeanFactory().registerBeanDefinition("tb1", bd);
+ }
+
+ ConstructorArgumentValues cas = new ConstructorArgumentValues();
+ cas.addIndexedArgumentValue(1, "${age}");
+ cas.addGenericArgumentValue("${var}name${age}");
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ List friends = new ManagedList();
+ friends.add("na${age}me");
+ friends.add(new RuntimeBeanReference("${ref}"));
+ pvs.addPropertyValue("friends", friends);
+
+ Set someSet = new ManagedSet();
+ someSet.add("na${age}me");
+ someSet.add(new RuntimeBeanReference("${ref}"));
+ someSet.add(new TypedStringValue("${age}", Integer.class));
+ pvs.addPropertyValue("someSet", someSet);
+
+ Map someMap = new ManagedMap();
+ someMap.put(new TypedStringValue("key${age}"), new TypedStringValue("${age}"));
+ someMap.put(new TypedStringValue("key${age}ref"), new RuntimeBeanReference("${ref}"));
+ someMap.put("key1", new RuntimeBeanReference("${ref}"));
+ someMap.put("key2", "${age}name");
+ MutablePropertyValues innerPvs = new MutablePropertyValues();
+ innerPvs.addPropertyValue("touchy", "${os.name}");
+ someMap.put("key3", new RootBeanDefinition(TestBean.class, innerPvs));
+ MutablePropertyValues innerPvs2 = new MutablePropertyValues(innerPvs);
+ someMap.put("${key4}", new BeanDefinitionHolder(new ChildBeanDefinition("tb1", innerPvs2), "child"));
+ pvs.addPropertyValue("someMap", someMap);
+
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, cas, pvs);
+ ac.getDefaultListableBeanFactory().registerBeanDefinition("tb2", bd);
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", "age=98\nvar=${m}var\nref=tb2\nm=my\nkey4=mykey4\nparent=parent1");
+ ac.registerSingleton("configurer", PropertyPlaceholderConfigurer.class, pvs);
+ ac.refresh();
+
+ TestBean tb1 = (TestBean) ac.getBean("tb1");
+ TestBean tb2 = (TestBean) ac.getBean("tb2");
+ assertEquals(98, tb1.getAge());
+ assertEquals(98, tb2.getAge());
+ assertEquals("namemyvarmyvar${", tb1.getName());
+ assertEquals("myvarname98", tb2.getName());
+ assertEquals(tb2, tb1.getSpouse());
+ assertEquals(2, tb2.getFriends().size());
+ assertEquals("na98me", tb2.getFriends().iterator().next());
+ assertEquals(tb2, tb2.getFriends().toArray()[1]);
+ assertEquals(3, tb2.getSomeSet().size());
+ assertTrue(tb2.getSomeSet().contains("na98me"));
+ assertTrue(tb2.getSomeSet().contains(tb2));
+ assertTrue(tb2.getSomeSet().contains(new Integer(98)));
+ assertEquals(6, tb2.getSomeMap().size());
+ assertEquals("98", tb2.getSomeMap().get("key98"));
+ assertEquals(tb2, tb2.getSomeMap().get("key98ref"));
+ assertEquals(tb2, tb2.getSomeMap().get("key1"));
+ assertEquals("98name", tb2.getSomeMap().get("key2"));
+ TestBean inner1 = (TestBean) tb2.getSomeMap().get("key3");
+ TestBean inner2 = (TestBean) tb2.getSomeMap().get("mykey4");
+ assertEquals(0, inner1.getAge());
+ assertEquals(null, inner1.getName());
+ assertEquals(System.getProperty("os.name"), inner1.getTouchy());
+ assertEquals(98, inner2.getAge());
+ assertEquals("namemyvarmyvar${", inner2.getName());
+ assertEquals(System.getProperty("os.name"), inner2.getTouchy());
+ }
+
+ public void testPropertyPlaceholderConfigurerWithSystemPropertyFallback() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("touchy", "${os.name}");
+ ac.registerSingleton("tb", TestBean.class, pvs);
+ pvs = new MutablePropertyValues();
+ ac.registerSingleton("configurer", PropertyPlaceholderConfigurer.class, pvs);
+ ac.refresh();
+ TestBean tb = (TestBean) ac.getBean("tb");
+ assertEquals(System.getProperty("os.name"), tb.getTouchy());
+ }
+
+ public void testPropertyPlaceholderConfigurerWithSystemPropertyNotUsed() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("touchy", "${os.name}");
+ ac.registerSingleton("tb", TestBean.class, pvs);
+ pvs = new MutablePropertyValues();
+ Properties props = new Properties();
+ props.put("os.name", "myos");
+ pvs.addPropertyValue("properties", props);
+ ac.registerSingleton("configurer", PropertyPlaceholderConfigurer.class, pvs);
+ ac.refresh();
+ TestBean tb = (TestBean) ac.getBean("tb");
+ assertEquals("myos", tb.getTouchy());
+ }
+
+ public void testPropertyPlaceholderConfigurerWithOverridingSystemProperty() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("touchy", "${os.name}");
+ ac.registerSingleton("tb", TestBean.class, pvs);
+ pvs = new MutablePropertyValues();
+ Properties props = new Properties();
+ props.put("os.name", "myos");
+ pvs.addPropertyValue("properties", props);
+ pvs.addPropertyValue("systemPropertiesModeName", "SYSTEM_PROPERTIES_MODE_OVERRIDE");
+ ac.registerSingleton("configurer", PropertyPlaceholderConfigurer.class, pvs);
+ ac.refresh();
+ TestBean tb = (TestBean) ac.getBean("tb");
+ assertEquals(System.getProperty("os.name"), tb.getTouchy());
+ }
+
+ public void testPropertyPlaceholderConfigurerWithUnresolvableSystemProperty() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("touchy", "${user.dir}");
+ ac.registerSingleton("tb", TestBean.class, pvs);
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("systemPropertiesModeName", "SYSTEM_PROPERTIES_MODE_NEVER");
+ ac.registerSingleton("configurer", PropertyPlaceholderConfigurer.class, pvs);
+ try {
+ ac.refresh();
+ fail("Should have thrown BeanDefinitionStoreException");
+ }
+ catch (BeanDefinitionStoreException ex) {
+ // expected
+ assertTrue(ex.getMessage().indexOf("user.dir") != -1);
+ }
+ }
+
+ public void testPropertyPlaceholderConfigurerWithUnresolvablePlaceholder() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "${ref}");
+ ac.registerSingleton("tb", TestBean.class, pvs);
+ ac.registerSingleton("configurer", PropertyPlaceholderConfigurer.class, null);
+ try {
+ ac.refresh();
+ fail("Should have thrown BeanDefinitionStoreException");
+ }
+ catch (BeanDefinitionStoreException ex) {
+ // expected
+ assertTrue(ex.getMessage().indexOf("ref") != -1);
+ }
+ }
+
+ public void testPropertyPlaceholderConfigurerWithIgnoreUnresolvablePlaceholder() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "${ref}");
+ ac.registerSingleton("tb", TestBean.class, pvs);
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("ignoreUnresolvablePlaceholders", Boolean.TRUE);
+ ac.registerSingleton("configurer", PropertyPlaceholderConfigurer.class, pvs);
+ ac.refresh();
+ TestBean tb = (TestBean) ac.getBean("tb");
+ assertEquals("${ref}", tb.getName());
+ }
+
+ public void testPropertyPlaceholderConfigurerWithEmptyStringAsNull() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "");
+ ac.registerSingleton("tb", TestBean.class, pvs);
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("nullValue", "");
+ ac.registerSingleton("configurer", PropertyPlaceholderConfigurer.class, pvs);
+ ac.refresh();
+ TestBean tb = (TestBean) ac.getBean("tb");
+ assertNull(tb.getName());
+ }
+
+ public void testPropertyPlaceholderConfigurerWithEmptyStringInPlaceholderAsNull() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "${ref}");
+ ac.registerSingleton("tb", TestBean.class, pvs);
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("nullValue", "");
+ Properties props = new Properties();
+ props.put("ref", "");
+ pvs.addPropertyValue("properties", props);
+ ac.registerSingleton("configurer", PropertyPlaceholderConfigurer.class, pvs);
+ ac.refresh();
+ TestBean tb = (TestBean) ac.getBean("tb");
+ assertNull(tb.getName());
+ }
+
+ public void testPropertyPlaceholderConfigurerWithNestedPlaceholderInKey() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "${my${key}key}");
+ ac.registerSingleton("tb", TestBean.class, pvs);
+ pvs = new MutablePropertyValues();
+ Properties props = new Properties();
+ props.put("key", "new");
+ props.put("mynewkey", "myname");
+ pvs.addPropertyValue("properties", props);
+ ac.registerSingleton("configurer", PropertyPlaceholderConfigurer.class, pvs);
+ ac.refresh();
+ TestBean tb = (TestBean) ac.getBean("tb");
+ assertEquals("myname", tb.getName());
+ }
+
+ public void testPropertyPlaceholderConfigurerWithSystemPropertyInLocation() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("spouse", new RuntimeBeanReference("${ref}"));
+ ac.registerSingleton("tb", TestBean.class, pvs);
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("location", "${user.dir}/test");
+ ac.registerSingleton("configurer", PropertyPlaceholderConfigurer.class, pvs);
+ try {
+ ac.refresh();
+ fail("Should have thrown BeanInitializationException");
+ }
+ catch (BeanInitializationException ex) {
+ // expected
+ assertTrue(ex.getCause() instanceof FileNotFoundException);
+ // slight hack for Linux/Unix systems
+ String userDir = StringUtils.cleanPath(System.getProperty("user.dir"));
+ if (userDir.startsWith("/")) {
+ userDir = userDir.substring(1);
+ }
+ assertTrue(ex.getMessage().indexOf(userDir) != -1);
+ }
+ }
+
+ public void testPropertyPlaceholderConfigurerWithSystemPropertiesInLocation() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("spouse", new RuntimeBeanReference("${ref}"));
+ ac.registerSingleton("tb", TestBean.class, pvs);
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("location", "${user.dir}/test/${user.dir}");
+ ac.registerSingleton("configurer", PropertyPlaceholderConfigurer.class, pvs);
+ try {
+ ac.refresh();
+ fail("Should have thrown BeanInitializationException");
+ }
+ catch (BeanInitializationException ex) {
+ // expected
+ assertTrue(ex.getCause() instanceof FileNotFoundException);
+ // slight hack for Linux/Unix systems
+ String userDir = StringUtils.cleanPath(System.getProperty("user.dir"));
+ if (userDir.startsWith("/")) {
+ userDir = userDir.substring(1);
+ }
+ /* the above hack doesn't work since the exception message is created without
+ the leading / stripped so the test fails. Changed 17/11/04. DD */
+ //assertTrue(ex.getMessage().indexOf(userDir + "/test/" + userDir) != -1);
+ assertTrue(ex.getMessage().indexOf(userDir + "/test/" + userDir) != -1 ||
+ ex.getMessage().indexOf(userDir + "/test//" + userDir) != -1);
+ }
+ }
+
+ public void testPropertyPlaceholderConfigurerWithUnresolvableSystemPropertiesInLocation() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("spouse", new RuntimeBeanReference("${ref}"));
+ ac.registerSingleton("tb", TestBean.class, pvs);
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("location", "${myprop}/test/${myprop}");
+ ac.registerSingleton("configurer", PropertyPlaceholderConfigurer.class, pvs);
+ try {
+ ac.refresh();
+ fail("Should have thrown BeanDefinitionStoreException");
+ }
+ catch (BeanInitializationException ex) {
+ // expected
+ assertTrue(ex.getCause() instanceof FileNotFoundException);
+ assertTrue(ex.getMessage().indexOf("myprop") != -1);
+ }
+ }
+
+ public void testPropertyPlaceholderConfigurerWithCircularReference() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("age", "${age}");
+ pvs.addPropertyValue("name", "name${var}");
+ ac.registerSingleton("tb", TestBean.class, pvs);
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", "age=99\nvar=${m}var\nm=${var}");
+ ac.registerSingleton("configurer1", PropertyPlaceholderConfigurer.class, pvs);
+ try {
+ ac.refresh();
+ fail("Should have thrown BeanDefinitionStoreException");
+ }
+ catch (BeanDefinitionStoreException ex) {
+ // expected
+ }
+ }
+
+ public void testPropertyPlaceholderConfigurerWithMultiLevelCircularReference() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "name${var}");
+ ac.registerSingleton("tb1", TestBean.class, pvs);
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", "var=${m}var\nm=${var2}\nvar2=${var}");
+ ac.registerSingleton("configurer1", PropertyPlaceholderConfigurer.class, pvs);
+ try {
+ ac.refresh();
+ fail("Should have thrown BeanDefinitionStoreException");
+ }
+ catch (BeanDefinitionStoreException ex) {
+ // expected
+ }
+ }
+
+ public void testPropertyPlaceholderConfigurerWithNestedCircularReference() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "name${var}");
+ ac.registerSingleton("tb1", TestBean.class, pvs);
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", "var=${m}var\nm=${var2}\nvar2=${m}");
+ ac.registerSingleton("configurer1", PropertyPlaceholderConfigurer.class, pvs);
+ try {
+ ac.refresh();
+ fail("Should have thrown BeanDefinitionStoreException");
+ }
+ catch (BeanDefinitionStoreException ex) {
+ // expected
+ }
+ }
+
+ public void testPropertyPlaceholderConfigurerWithDefaultProperties() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("touchy", "${test}");
+ ac.registerSingleton("tb", TestBean.class, pvs);
+ pvs = new MutablePropertyValues();
+ Properties props = new Properties();
+ props.put("test", "mytest");
+ pvs.addPropertyValue("properties", new Properties(props));
+ ac.registerSingleton("configurer", PropertyPlaceholderConfigurer.class, pvs);
+ ac.refresh();
+ TestBean tb = (TestBean) ac.getBean("tb");
+ assertEquals("mytest", tb.getTouchy());
+ }
+
+ public void testPropertyPlaceholderConfigurerWithAutowireByType() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("touchy", "${test}");
+ ac.registerSingleton("tb", TestBean.class, pvs);
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("target", new RuntimeBeanReference("tb"));
+ ac.registerSingleton("tbProxy", ProxyFactoryBean.class, pvs);
+ pvs = new MutablePropertyValues();
+ Properties props = new Properties();
+ props.put("test", "mytest");
+ pvs.addPropertyValue("properties", new Properties(props));
+ RootBeanDefinition ppcDef = new RootBeanDefinition(PropertyPlaceholderConfigurer.class, pvs);
+ ppcDef.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE);
+ ac.registerBeanDefinition("configurer", ppcDef);
+ ac.refresh();
+ TestBean tb = (TestBean) ac.getBean("tb");
+ assertEquals("mytest", tb.getTouchy());
+ }
+
+ public void testPropertyPlaceholderConfigurerWithAliases() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("touchy", "${test}");
+ ac.registerSingleton("tb", TestBean.class, pvs);
+ ac.registerAlias("tb", "${myAlias}");
+ ac.registerAlias("${myTarget}", "alias2");
+ pvs = new MutablePropertyValues();
+ Properties props = new Properties();
+ props.put("test", "mytest");
+ props.put("myAlias", "alias");
+ props.put("myTarget", "tb");
+ pvs.addPropertyValue("properties", new Properties(props));
+ ac.registerSingleton("configurer", PropertyPlaceholderConfigurer.class, pvs);
+ ac.refresh();
+ TestBean tb = (TestBean) ac.getBean("tb");
+ assertEquals("mytest", tb.getTouchy());
+ tb = (TestBean) ac.getBean("alias");
+ assertEquals("mytest", tb.getTouchy());
+ tb = (TestBean) ac.getBean("alias2");
+ assertEquals("mytest", tb.getTouchy());
+ }
+
+ public void testPreferencesPlaceholderConfigurer() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "${myName}");
+ pvs.addPropertyValue("age", "${myAge}");
+ pvs.addPropertyValue("touchy", "${myTouchy}");
+ ac.registerSingleton("tb", TestBean.class, pvs);
+ pvs = new MutablePropertyValues();
+ Properties props = new Properties();
+ props.put("myAge", "99");
+ pvs.addPropertyValue("properties", props);
+ ac.registerSingleton("configurer", PreferencesPlaceholderConfigurer.class, pvs);
+ Preferences.systemRoot().put("myName", "myNameValue");
+ Preferences.systemRoot().put("myTouchy", "myTouchyValue");
+ Preferences.userRoot().put("myTouchy", "myOtherTouchyValue");
+ ac.refresh();
+ TestBean tb = (TestBean) ac.getBean("tb");
+ assertEquals("myNameValue", tb.getName());
+ assertEquals(99, tb.getAge());
+ assertEquals("myOtherTouchyValue", tb.getTouchy());
+ Preferences.userRoot().remove("myTouchy");
+ Preferences.systemRoot().remove("myTouchy");
+ Preferences.systemRoot().remove("myName");
+ }
+
+ public void testPreferencesPlaceholderConfigurerWithCustomTreePaths() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "${myName}");
+ pvs.addPropertyValue("age", "${myAge}");
+ pvs.addPropertyValue("touchy", "${myTouchy}");
+ ac.registerSingleton("tb", TestBean.class, pvs);
+ pvs = new MutablePropertyValues();
+ Properties props = new Properties();
+ props.put("myAge", "99");
+ pvs.addPropertyValue("properties", props);
+ pvs.addPropertyValue("systemTreePath", "mySystemPath");
+ pvs.addPropertyValue("userTreePath", "myUserPath");
+ ac.registerSingleton("configurer", PreferencesPlaceholderConfigurer.class, pvs);
+ Preferences.systemRoot().node("mySystemPath").put("myName", "myNameValue");
+ Preferences.systemRoot().node("mySystemPath").put("myTouchy", "myTouchyValue");
+ Preferences.userRoot().node("myUserPath").put("myTouchy", "myOtherTouchyValue");
+ ac.refresh();
+ TestBean tb = (TestBean) ac.getBean("tb");
+ assertEquals("myNameValue", tb.getName());
+ assertEquals(99, tb.getAge());
+ assertEquals("myOtherTouchyValue", tb.getTouchy());
+ Preferences.userRoot().node("myUserPath").remove("myTouchy");
+ Preferences.systemRoot().node("mySystemPath").remove("myTouchy");
+ Preferences.systemRoot().node("mySystemPath").remove("myName");
+ }
+
+ public void testPreferencesPlaceholderConfigurerWithPathInPlaceholder() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "${mypath/myName}");
+ pvs.addPropertyValue("age", "${myAge}");
+ pvs.addPropertyValue("touchy", "${myotherpath/myTouchy}");
+ ac.registerSingleton("tb", TestBean.class, pvs);
+ pvs = new MutablePropertyValues();
+ Properties props = new Properties();
+ props.put("myAge", "99");
+ pvs.addPropertyValue("properties", props);
+ pvs.addPropertyValue("systemTreePath", "mySystemPath");
+ pvs.addPropertyValue("userTreePath", "myUserPath");
+ ac.registerSingleton("configurer", PreferencesPlaceholderConfigurer.class, pvs);
+ Preferences.systemRoot().node("mySystemPath").node("mypath").put("myName", "myNameValue");
+ Preferences.systemRoot().node("mySystemPath/myotherpath").put("myTouchy", "myTouchyValue");
+ Preferences.userRoot().node("myUserPath/myotherpath").put("myTouchy", "myOtherTouchyValue");
+ ac.refresh();
+ TestBean tb = (TestBean) ac.getBean("tb");
+ assertEquals("myNameValue", tb.getName());
+ assertEquals(99, tb.getAge());
+ assertEquals("myOtherTouchyValue", tb.getTouchy());
+ Preferences.userRoot().node("myUserPath/myotherpath").remove("myTouchy");
+ Preferences.systemRoot().node("mySystemPath/myotherpath").remove("myTouchy");
+ Preferences.systemRoot().node("mySystemPath/mypath").remove("myName");
+ }
+
+
+ private static class ConvertingOverrideConfigurer extends PropertyOverrideConfigurer {
+
+ protected String convertPropertyValue(String originalValue) {
+ return "X" + originalValue;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/ServiceLocatorFactoryBeanTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/ServiceLocatorFactoryBeanTests.java
new file mode 100644
index 00000000000..f093bffe9fe
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/ServiceLocatorFactoryBeanTests.java
@@ -0,0 +1,346 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.beans.factory.config;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.beans.FatalBeanException;
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.PropertyValue;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.context.support.StaticApplicationContext;
+import org.springframework.core.NestedCheckedException;
+import org.springframework.core.NestedRuntimeException;
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Colin Sampaleanu
+ * @author Rick Evans
+ */
+public class ServiceLocatorFactoryBeanTests extends TestCase {
+
+ public void testNoArgGetter() {
+ StaticApplicationContext ctx = new StaticApplicationContext();
+ ctx.registerSingleton("testService", TestService.class, new MutablePropertyValues());
+ MutablePropertyValues mpv = new MutablePropertyValues();
+ mpv.addPropertyValue(new PropertyValue("serviceLocatorInterface", TestServiceLocator.class));
+ ctx.registerSingleton("factory", ServiceLocatorFactoryBean.class, mpv);
+ ctx.refresh();
+
+ TestServiceLocator factory = (TestServiceLocator) ctx.getBean("factory");
+ TestService testService = factory.getTestService();
+ assertNotNull(testService);
+ }
+
+ public void testErrorOnTooManyOrTooFew() throws Exception {
+ StaticApplicationContext ctx = new StaticApplicationContext();
+ ctx.registerSingleton("testService", TestService.class, new MutablePropertyValues());
+ ctx.registerSingleton("testServiceInstance2", TestService.class, new MutablePropertyValues());
+ MutablePropertyValues mpv = new MutablePropertyValues();
+ mpv.addPropertyValue(new PropertyValue("serviceLocatorInterface", TestServiceLocator.class));
+ ctx.registerSingleton("factory", ServiceLocatorFactoryBean.class, mpv);
+ mpv = new MutablePropertyValues();
+ mpv.addPropertyValue(new PropertyValue("serviceLocatorInterface", TestServiceLocator2.class));
+ ctx.registerSingleton("factory2", ServiceLocatorFactoryBean.class, mpv);
+ mpv = new MutablePropertyValues();
+ mpv.addPropertyValue(new PropertyValue("serviceLocatorInterface", TestService2Locator.class));
+ ctx.registerSingleton("factory3", ServiceLocatorFactoryBean.class, mpv);
+ ctx.refresh();
+
+ final TestServiceLocator factory = (TestServiceLocator) ctx.getBean("factory");
+ new AssertThrows(NoSuchBeanDefinitionException.class, "Must fail on more than one matching type") {
+ public void test() throws Exception {
+ factory.getTestService();
+ }
+ }.runTest();
+
+ final TestServiceLocator2 factory2 = (TestServiceLocator2) ctx.getBean("factory2");
+ new AssertThrows(NoSuchBeanDefinitionException.class, "Must fail on more than one matching type") {
+ public void test() throws Exception {
+ factory2.getTestService(null);
+ }
+ }.runTest();
+ final TestService2Locator factory3 = (TestService2Locator) ctx.getBean("factory3");
+ new AssertThrows(NoSuchBeanDefinitionException.class, "Must fail on no matching types") {
+ public void test() throws Exception {
+ factory3.getTestService();
+ }
+ }.runTest();
+ }
+
+ public void testErrorOnTooManyOrTooFewWithCustomServiceLocatorException() {
+ StaticApplicationContext ctx = new StaticApplicationContext();
+ ctx.registerSingleton("testService", TestService.class, new MutablePropertyValues());
+ ctx.registerSingleton("testServiceInstance2", TestService.class, new MutablePropertyValues());
+ MutablePropertyValues mpv = new MutablePropertyValues();
+ mpv.addPropertyValue(new PropertyValue("serviceLocatorInterface", TestServiceLocator.class));
+ mpv.addPropertyValue(new PropertyValue("serviceLocatorExceptionClass", CustomServiceLocatorException1.class));
+ ctx.registerSingleton("factory", ServiceLocatorFactoryBean.class, mpv);
+ mpv = new MutablePropertyValues();
+ mpv.addPropertyValue(new PropertyValue("serviceLocatorInterface", TestServiceLocator2.class));
+ mpv.addPropertyValue(new PropertyValue("serviceLocatorExceptionClass", CustomServiceLocatorException2.class));
+ ctx.registerSingleton("factory2", ServiceLocatorFactoryBean.class, mpv);
+ mpv = new MutablePropertyValues();
+ mpv.addPropertyValue(new PropertyValue("serviceLocatorInterface", TestService2Locator.class));
+ mpv.addPropertyValue(new PropertyValue("serviceLocatorExceptionClass", CustomServiceLocatorException3.class));
+ ctx.registerSingleton("factory3", ServiceLocatorFactoryBean.class, mpv);
+ ctx.refresh();
+
+ TestServiceLocator factory = (TestServiceLocator) ctx.getBean("factory");
+ try {
+ factory.getTestService();
+ fail("Must fail on more than one matching type");
+ }
+ catch (CustomServiceLocatorException1 expected) {
+ assertTrue(expected.getCause() instanceof NoSuchBeanDefinitionException);
+ }
+ TestServiceLocator2 factory2 = (TestServiceLocator2) ctx.getBean("factory2");
+ try {
+ factory2.getTestService(null);
+ fail("Must fail on more than one matching type");
+ }
+ catch (CustomServiceLocatorException2 expected) {
+ assertTrue(expected.getCause() instanceof NoSuchBeanDefinitionException);
+ }
+ final TestService2Locator factory3 = (TestService2Locator) ctx.getBean("factory3");
+ new AssertThrows(CustomServiceLocatorException3.class, "Must fail on no matching types") {
+ public void test() throws Exception {
+ factory3.getTestService();
+ }
+ }.runTest();
+ }
+
+ public void testStringArgGetter() throws Exception {
+ StaticApplicationContext ctx = new StaticApplicationContext();
+ ctx.registerSingleton("testService", TestService.class, new MutablePropertyValues());
+ MutablePropertyValues mpv = new MutablePropertyValues();
+ mpv.addPropertyValue(new PropertyValue("serviceLocatorInterface", TestServiceLocator2.class));
+ ctx.registerSingleton("factory", ServiceLocatorFactoryBean.class, mpv);
+ ctx.refresh();
+
+ // test string-arg getter with null id
+ final TestServiceLocator2 factory = (TestServiceLocator2) ctx.getBean("factory");
+ TestService testBean = factory.getTestService(null);
+ // now test with explicit id
+ testBean = factory.getTestService("testService");
+ // now verify failure on bad id
+ new AssertThrows(NoSuchBeanDefinitionException.class, "Illegal operation allowed") {
+ public void test() throws Exception {
+ factory.getTestService("bogusTestService");
+ }
+ }.runTest();
+ }
+
+ public void testCombinedLocatorInterface() {
+ StaticApplicationContext ctx = new StaticApplicationContext();
+ ctx.registerPrototype("testService", TestService.class, new MutablePropertyValues());
+ ctx.registerAlias("testService", "1");
+ MutablePropertyValues mpv = new MutablePropertyValues();
+ mpv.addPropertyValue("serviceLocatorInterface", TestServiceLocator3.class);
+ ctx.registerSingleton("factory", ServiceLocatorFactoryBean.class, mpv);
+ ctx.refresh();
+
+ TestServiceLocator3 factory = (TestServiceLocator3) ctx.getBean("factory");
+ TestService testBean1 = factory.getTestService();
+ TestService testBean2 = factory.getTestService("testService");
+ TestService testBean3 = factory.getTestService(1);
+ TestService testBean4 = factory.someFactoryMethod();
+ assertNotSame(testBean1, testBean2);
+ assertNotSame(testBean1, testBean3);
+ assertNotSame(testBean1, testBean4);
+ assertNotSame(testBean2, testBean3);
+ assertNotSame(testBean2, testBean4);
+ assertNotSame(testBean3, testBean4);
+
+ assertTrue(factory.toString().indexOf("TestServiceLocator3") != -1);
+ }
+
+ public void testServiceMappings() {
+ StaticApplicationContext ctx = new StaticApplicationContext();
+ ctx.registerPrototype("testService1", TestService.class, new MutablePropertyValues());
+ ctx.registerPrototype("testService2", ExtendedTestService.class, new MutablePropertyValues());
+ MutablePropertyValues mpv = new MutablePropertyValues();
+ mpv.addPropertyValue("serviceLocatorInterface", TestServiceLocator3.class);
+ mpv.addPropertyValue("serviceMappings", "=testService1\n1=testService1\n2=testService2");
+ ctx.registerSingleton("factory", ServiceLocatorFactoryBean.class, mpv);
+ ctx.refresh();
+
+ TestServiceLocator3 factory = (TestServiceLocator3) ctx.getBean("factory");
+ TestService testBean1 = factory.getTestService();
+ TestService testBean2 = factory.getTestService("testService1");
+ TestService testBean3 = factory.getTestService(1);
+ TestService testBean4 = factory.getTestService(2);
+ assertNotSame(testBean1, testBean2);
+ assertNotSame(testBean1, testBean3);
+ assertNotSame(testBean1, testBean4);
+ assertNotSame(testBean2, testBean3);
+ assertNotSame(testBean2, testBean4);
+ assertNotSame(testBean3, testBean4);
+ assertFalse(testBean1 instanceof ExtendedTestService);
+ assertFalse(testBean2 instanceof ExtendedTestService);
+ assertFalse(testBean3 instanceof ExtendedTestService);
+ assertTrue(testBean4 instanceof ExtendedTestService);
+ }
+
+ public void testNoServiceLocatorInterfaceSupplied() throws Exception {
+ new AssertThrows(IllegalArgumentException.class, "No serviceLocator interface supplied") {
+ public void test() throws Exception {
+ new ServiceLocatorFactoryBean().afterPropertiesSet();
+ }
+ }.runTest();
+ }
+
+ public void testWhenServiceLocatorInterfaceIsNotAnInterfaceType() throws Exception {
+ new AssertThrows(IllegalArgumentException.class, "Bad (non-interface-type) serviceLocator interface supplied") {
+ public void test() throws Exception {
+ ServiceLocatorFactoryBean factory = new ServiceLocatorFactoryBean();
+ factory.setServiceLocatorInterface(getClass());
+ factory.afterPropertiesSet();
+ }
+ }.runTest();
+ }
+
+ public void testWhenServiceLocatorExceptionClassToExceptionTypeWithOnlyNoArgCtor() throws Exception {
+ new AssertThrows(IllegalArgumentException.class, "Bad (invalid-Exception-type) serviceLocatorException class supplied") {
+ public void test() throws Exception {
+ ServiceLocatorFactoryBean factory = new ServiceLocatorFactoryBean();
+ factory.setServiceLocatorExceptionClass(ExceptionClassWithOnlyZeroArgCtor.class);
+ }
+ }.runTest();
+ }
+
+ public void testWhenServiceLocatorExceptionClassIsNotAnExceptionSubclass() throws Exception {
+ new AssertThrows(IllegalArgumentException.class, "Bad (non-Exception-type) serviceLocatorException class supplied") {
+ public void test() throws Exception {
+ ServiceLocatorFactoryBean factory = new ServiceLocatorFactoryBean();
+ factory.setServiceLocatorExceptionClass(getClass());
+ }
+ }.runTest();
+ }
+
+ public void testWhenServiceLocatorMethodCalledWithTooManyParameters() throws Exception {
+ ServiceLocatorFactoryBean factory = new ServiceLocatorFactoryBean();
+ factory.setServiceLocatorInterface(ServiceLocatorInterfaceWithExtraNonCompliantMethod.class);
+ factory.afterPropertiesSet();
+ final ServiceLocatorInterfaceWithExtraNonCompliantMethod locator = (ServiceLocatorInterfaceWithExtraNonCompliantMethod) factory.getObject();
+ new AssertThrows(UnsupportedOperationException.class, "Bad method (too many args, doesn't obey class contract)") {
+ public void test() throws Exception {
+ locator.getTestService("not", "allowed");
+ }
+ }.runTest();
+ }
+
+ public void testRequiresListableBeanFactoryAndChokesOnAnythingElse() throws Exception {
+ MockControl mockBeanFactory = MockControl.createControl(BeanFactory.class);
+ final BeanFactory beanFactory = (BeanFactory) mockBeanFactory.getMock();
+ mockBeanFactory.replay();
+
+ new AssertThrows(FatalBeanException.class) {
+ public void test() throws Exception {
+ ServiceLocatorFactoryBean factory = new ServiceLocatorFactoryBean();
+ factory.setBeanFactory(beanFactory);
+ }
+ }.runTest();
+
+ mockBeanFactory.verify();
+ }
+
+
+ public static class TestService {
+
+ }
+
+
+ public static class ExtendedTestService extends TestService {
+
+ }
+
+
+ public static class TestService2 {
+
+ }
+
+
+ public static interface TestServiceLocator {
+
+ TestService getTestService();
+ }
+
+
+ public static interface TestServiceLocator2 {
+
+ TestService getTestService(String id) throws CustomServiceLocatorException2;
+ }
+
+
+ public static interface TestServiceLocator3 {
+
+ TestService getTestService();
+
+ TestService getTestService(String id);
+
+ TestService getTestService(int id);
+
+ TestService someFactoryMethod();
+ }
+
+
+ public static interface TestService2Locator {
+
+ TestService2 getTestService() throws CustomServiceLocatorException3;
+ }
+
+
+ public static interface ServiceLocatorInterfaceWithExtraNonCompliantMethod {
+
+ TestService2 getTestService();
+
+ TestService2 getTestService(String serviceName, String defaultNotAllowedParameter);
+ }
+
+
+ public static class CustomServiceLocatorException1 extends NestedRuntimeException {
+
+ public CustomServiceLocatorException1(String message, Throwable cause) {
+ super(message, cause);
+ }
+ }
+
+
+ public static class CustomServiceLocatorException2 extends NestedCheckedException {
+
+ public CustomServiceLocatorException2(Throwable cause) {
+ super("", cause);
+ }
+ }
+
+
+ public static class CustomServiceLocatorException3 extends NestedCheckedException {
+
+ public CustomServiceLocatorException3(String message) {
+ super(message);
+ }
+ }
+
+
+ public static class ExceptionClassWithOnlyZeroArgCtor extends Exception {
+
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/SimpleMapScope.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/SimpleMapScope.java
new file mode 100644
index 00000000000..3aedfb8de71
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/SimpleMapScope.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.config;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.beans.factory.ObjectFactory;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class SimpleMapScope implements Scope, Serializable {
+
+ private final Map map = new HashMap();
+
+ private final List callbacks = new LinkedList();
+
+
+ public SimpleMapScope() {
+ }
+
+ public final Map getMap() {
+ return this.map;
+ }
+
+
+ public Object get(String name, ObjectFactory objectFactory) {
+ synchronized (this.map) {
+ Object scopedObject = this.map.get(name);
+ if (scopedObject == null) {
+ scopedObject = objectFactory.getObject();
+ this.map.put(name, scopedObject);
+ }
+ return scopedObject;
+ }
+ }
+
+ public Object remove(String name) {
+ synchronized (this.map) {
+ return this.map.remove(name);
+ }
+ }
+
+ public void registerDestructionCallback(String name, Runnable callback) {
+ this.callbacks.add(callback);
+ }
+
+ public void close() {
+ for (Iterator it = this.callbacks.iterator(); it.hasNext();) {
+ Runnable runnable = (Runnable) it.next();
+ runnable.run();
+ }
+ }
+
+ public String getConversationId() {
+ return null;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/SimpleScopeTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/SimpleScopeTests.java
new file mode 100644
index 00000000000..26c41b74688
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/SimpleScopeTests.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.config;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.ObjectFactory;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.context.support.GenericApplicationContext;
+
+/**
+ * Simple test to illustrate and verify scope usage.
+ *
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public class SimpleScopeTests extends TestCase {
+
+ private GenericApplicationContext applicationContext;
+
+ protected void setUp() {
+ applicationContext = new GenericApplicationContext();
+ Scope scope = new NoOpScope() {
+ private int index;
+ private List objects = new LinkedList(); {
+ objects.add(new TestBean());
+ objects.add(new TestBean());
+ }
+ public Object get(String name, ObjectFactory objectFactory) {
+ if (index >= objects.size()) {
+ index = 0;
+ }
+ return objects.get(index++);
+ }
+ };
+
+ applicationContext.getBeanFactory().registerScope("myScope", scope);
+
+ String[] scopeNames = applicationContext.getBeanFactory().getRegisteredScopeNames();
+ assertEquals(1, scopeNames.length);
+ assertEquals("myScope", scopeNames[0]);
+ assertSame(scope, applicationContext.getBeanFactory().getRegisteredScope("myScope"));
+
+ XmlBeanDefinitionReader xbdr = new XmlBeanDefinitionReader(applicationContext);
+ xbdr.loadBeanDefinitions("org/springframework/beans/factory/config/simpleScope.xml");
+
+ applicationContext.refresh();
+ }
+
+ public void testCanGetScopedObject() {
+ TestBean tb1 = (TestBean) applicationContext.getBean("usesScope");
+ TestBean tb2 = (TestBean) applicationContext.getBean("usesScope");
+ assertNotSame(tb1, tb2);
+ TestBean tb3 = (TestBean) applicationContext.getBean("usesScope");
+ assertSame(tb3, tb1);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/fieldRetrieving.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/fieldRetrieving.xml
new file mode 100644
index 00000000000..564920e6d3a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/fieldRetrieving.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/propertyPath.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/propertyPath.xml
new file mode 100644
index 00000000000..ceacc6bc44b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/propertyPath.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+ 10
+
+
+ 11
+
+
+
+
+
+ 98
+
+
+ 99
+
+
+
+
+
+
+
+ 12
+
+
+ age
+
+
+
+ tb
+ spouse.age
+
+
+
+
+
+
+
+
+
+
+
+ tb
+ spouse
+ org.springframework.beans.TestBean
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/simpleScope.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/simpleScope.xml
new file mode 100644
index 00000000000..2bd9706f77e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/simpleScope.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/test-properties.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/test-properties.xml
new file mode 100644
index 00000000000..e39b872c9fc
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/test-properties.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+ 99
+ test
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/test.properties b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/test.properties
new file mode 100644
index 00000000000..9affcba0135
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/test.properties
@@ -0,0 +1,2 @@
+tb.array[0].age=99
+tb.list[1].name=test
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/util.properties b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/util.properties
new file mode 100644
index 00000000000..c9f0304f65e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/config/util.properties
@@ -0,0 +1 @@
+foo=bar
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/dependentBeans.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/dependentBeans.xml
new file mode 100644
index 00000000000..0dae03ee940
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/dependentBeans.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/factoryBeanReturnsNull.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/factoryBeanReturnsNull.xml
new file mode 100644
index 00000000000..d9b583910ea
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/factoryBeanReturnsNull.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/factoryBeansWithAutowiring.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/factoryBeansWithAutowiring.xml
new file mode 100644
index 00000000000..e650f8082a0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/factoryBeansWithAutowiring.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ yourName
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/leaf.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/leaf.xml
new file mode 100644
index 00000000000..4183c20b691
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/leaf.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ custom
+ 25
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/middle.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/middle.xml
new file mode 100644
index 00000000000..ced3b8f2ea1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/middle.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+ custom
+ 666
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/CollectingReaderEventListener.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/CollectingReaderEventListener.java
new file mode 100644
index 00000000000..74d6b48540e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/CollectingReaderEventListener.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.parsing;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.core.CollectionFactory;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class CollectingReaderEventListener implements ReaderEventListener {
+
+ private final List defaults = new LinkedList();
+
+ private final Map componentDefinitions = CollectionFactory.createLinkedMapIfPossible(8);
+
+ private final Map aliasMap = CollectionFactory.createLinkedMapIfPossible(8);
+
+ private final List imports = new LinkedList();
+
+
+ public void defaultsRegistered(DefaultsDefinition defaultsDefinition) {
+ this.defaults.add(defaultsDefinition);
+ }
+
+ public List getDefaults() {
+ return Collections.unmodifiableList(this.defaults);
+ }
+
+ public void componentRegistered(ComponentDefinition componentDefinition) {
+ this.componentDefinitions.put(componentDefinition.getName(), componentDefinition);
+ }
+
+ public ComponentDefinition getComponentDefinition(String name) {
+ return (ComponentDefinition) this.componentDefinitions.get(name);
+ }
+
+ public ComponentDefinition[] getComponentDefinitions() {
+ Collection collection = this.componentDefinitions.values();
+ return (ComponentDefinition[]) collection.toArray(new ComponentDefinition[collection.size()]);
+ }
+
+ public void aliasRegistered(AliasDefinition aliasDefinition) {
+ List aliases = (List) this.aliasMap.get(aliasDefinition.getBeanName());
+ if(aliases == null) {
+ aliases = new ArrayList();
+ this.aliasMap.put(aliasDefinition.getBeanName(), aliases);
+ }
+ aliases.add(aliasDefinition);
+ }
+
+ public List getAliases(String beanName) {
+ List aliases = (List) this.aliasMap.get(beanName);
+ return aliases == null ? null : Collections.unmodifiableList(aliases);
+ }
+
+ public void importProcessed(ImportDefinition importDefinition) {
+ this.imports.add(importDefinition);
+ }
+
+ public List getImports() {
+ return Collections.unmodifiableList(this.imports);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/ConstructorArgumentEntryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/ConstructorArgumentEntryTests.java
new file mode 100644
index 00000000000..e102aa9f178
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/ConstructorArgumentEntryTests.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory.parsing;
+
+import junit.framework.TestCase;
+import org.springframework.test.AssertThrows;
+
+/**
+ * Unit tests for the {@link ConstructorArgumentEntry} class.
+ *
+ * @author Rick Evans
+ */
+public final class ConstructorArgumentEntryTests extends TestCase {
+
+ public void testCtorBailsOnNegativeCtorIndexArgument() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new ConstructorArgumentEntry(-1);
+ }
+ }.runTest();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/CustomProblemReporterTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/CustomProblemReporterTests.java
new file mode 100644
index 00000000000..5581384221e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/CustomProblemReporterTests.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.parsing;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Rob Harrop
+ * @since 2.0
+ */
+public class CustomProblemReporterTests extends TestCase {
+
+ private CollatingProblemReporter problemReporter;
+
+ private DefaultListableBeanFactory beanFactory;
+
+ private XmlBeanDefinitionReader reader;
+
+
+ protected void setUp() throws Exception {
+ this.problemReporter = new CollatingProblemReporter();
+ this.beanFactory = new DefaultListableBeanFactory();
+ this.reader = new XmlBeanDefinitionReader(this.beanFactory);
+ this.reader.setProblemReporter(this.problemReporter);
+ }
+
+ public void testErrorsAreCollated() throws Exception {
+ this.reader.loadBeanDefinitions(new ClassPathResource("withErrors.xml", getClass()));
+ assertEquals("Incorrect number of errors collated", 4, this.problemReporter.getErrors().length);
+
+ TestBean bean = (TestBean) this.beanFactory.getBean("validBean");
+ assertNotNull(bean);
+ }
+
+
+ private static class CollatingProblemReporter implements ProblemReporter {
+
+ private List errors = new ArrayList();
+
+ private List warnings = new ArrayList();
+
+
+ public void fatal(Problem problem) {
+ throw new BeanDefinitionParsingException(problem);
+ }
+
+ public void error(Problem problem) {
+ System.out.println(problem);
+ this.errors.add(problem);
+ }
+
+ public Problem[] getErrors() {
+ return (Problem[]) this.errors.toArray(new Problem[this.errors.size()]);
+ }
+
+ public void warning(Problem problem) {
+ System.out.println(problem);
+ this.warnings.add(problem);
+ }
+
+ public Problem[] getWarnings() {
+ return (Problem[]) this.warnings.toArray(new Problem[this.warnings.size()]);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/FailFastProblemReporterTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/FailFastProblemReporterTests.java
new file mode 100644
index 00000000000..f41d11304bb
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/FailFastProblemReporterTests.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory.parsing;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+import org.apache.commons.logging.Log;
+import org.easymock.AbstractMatcher;
+import org.easymock.MockControl;
+
+import org.springframework.core.io.DescriptiveResource;
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public final class FailFastProblemReporterTests extends TestCase {
+
+ public void testError() throws Exception {
+ new AssertThrows(BeanDefinitionParsingException.class) {
+ public void test() throws Exception {
+ FailFastProblemReporter reporter = new FailFastProblemReporter();
+ reporter.error(new Problem("VGER", new Location(new DescriptiveResource("here")),
+ null, new IllegalArgumentException()));
+ }
+ }.runTest();
+ }
+
+ public void testWarn() throws Exception {
+ IllegalArgumentException rootCause = new IllegalArgumentException();
+ Problem problem = new Problem("VGER", new Location(new DescriptiveResource("here")),
+ null, new IllegalArgumentException());
+
+ MockControl mockLog = MockControl.createControl(Log.class);
+ Log log = (Log) mockLog.getMock();
+ log.warn(null, rootCause);
+ mockLog.setMatcher(new AbstractMatcher() {
+ public boolean matches(Object[] expected, Object[] actual) {
+ Assert.assertEquals(2, actual.length);
+ Assert.assertTrue(actual[1] instanceof IllegalArgumentException);
+ return true;
+ }
+ });
+ mockLog.replay();
+
+ FailFastProblemReporter reporter = new FailFastProblemReporter();
+ reporter.setLogger(log);
+ reporter.warning(problem);
+
+ mockLog.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/NullSourceExtractorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/NullSourceExtractorTests.java
new file mode 100644
index 00000000000..708331ed73c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/NullSourceExtractorTests.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory.parsing;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rick Evans
+ */
+public final class NullSourceExtractorTests extends TestCase {
+
+ public void testPassThroughContract() throws Exception {
+ Object source = new Object();
+ Object extractedSource = new NullSourceExtractor().extractSource(source, null);
+ assertNull("The contract of NullSourceExtractor states that the extraction *always* return null", extractedSource);
+ }
+
+ public void testPassThroughContractEvenWithNull() throws Exception {
+ Object extractedSource = new NullSourceExtractor().extractSource(null, null);
+ assertNull("The contract of NullSourceExtractor states that the extraction *always* return null", extractedSource);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/ParseStateTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/ParseStateTests.java
new file mode 100644
index 00000000000..8a2b58788c6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/ParseStateTests.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory.parsing;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.factory.parsing.ParseState;
+
+/**
+ * @author Rob Harrop
+ * @since 2.0
+ */
+public class ParseStateTests extends TestCase {
+
+ public void testSimple() throws Exception {
+ MockEntry entry = new MockEntry();
+
+ ParseState parseState = new ParseState();
+ parseState.push(entry);
+ assertEquals("Incorrect peek value.", entry, parseState.peek());
+ parseState.pop();
+ assertNull("Should get null on peek()", parseState.peek());
+ }
+
+ public void testNesting() throws Exception {
+ MockEntry one = new MockEntry();
+ MockEntry two = new MockEntry();
+ MockEntry three = new MockEntry();
+
+ ParseState parseState = new ParseState();
+ parseState.push(one);
+ assertEquals(one, parseState.peek());
+ parseState.push(two);
+ assertEquals(two, parseState.peek());
+ parseState.push(three);
+ assertEquals(three, parseState.peek());
+
+ parseState.pop();
+ assertEquals(two, parseState.peek());
+ parseState.pop();
+ assertEquals(one, parseState.peek());
+ }
+
+ public void testSnapshot() throws Exception {
+ MockEntry entry = new MockEntry();
+
+ ParseState original = new ParseState();
+ original.push(entry);
+
+ ParseState snapshot = original.snapshot();
+ original.push(new MockEntry());
+ assertEquals("Snapshot should not have been modified.", entry, snapshot.peek());
+ }
+
+
+ private static class MockEntry implements ParseState.Entry {
+
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/PassThroughSourceExtractorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/PassThroughSourceExtractorTests.java
new file mode 100644
index 00000000000..b65e047b473
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/PassThroughSourceExtractorTests.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory.parsing;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rick Evans
+ */
+public final class PassThroughSourceExtractorTests extends TestCase {
+
+ public void testPassThroughContract() throws Exception {
+ Object source = new Object();
+ Object extractedSource = new PassThroughSourceExtractor().extractSource(source, null);
+ assertSame("The contract of PassThroughSourceExtractor states that the supplied source object *must* be returned as-is", source, extractedSource);
+ }
+
+ public void testPassThroughContractEvenWithNull() throws Exception {
+ Object extractedSource = new PassThroughSourceExtractor().extractSource(null, null);
+ assertNull("The contract of PassThroughSourceExtractor states that the supplied source object *must* be returned as-is (even if null)", extractedSource);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/PropertyEntryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/PropertyEntryTests.java
new file mode 100644
index 00000000000..d94a8cebf7f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/PropertyEntryTests.java
@@ -0,0 +1,37 @@
+package org.springframework.beans.factory.parsing;
+
+import junit.framework.TestCase;
+import org.springframework.test.AssertThrows;
+
+/**
+ * Unit tests for the {@link PropertyEntry} class.
+ *
+ * @author Rick Evans
+ */
+public final class PropertyEntryTests extends TestCase {
+
+ public void testCtorBailsOnNullPropertyNameArgument() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new PropertyEntry(null);
+ }
+ }.runTest();
+ }
+
+ public void testCtorBailsOnEmptyPropertyNameArgument() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new PropertyEntry("");
+ }
+ }.runTest();
+ }
+
+ public void testCtorBailsOnWhitespacedPropertyNameArgument() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new PropertyEntry("\t ");
+ }
+ }.runTest();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/withErrors.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/withErrors.xml
new file mode 100644
index 00000000000..218056302c7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/parsing/withErrors.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/root.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/root.xml
new file mode 100644
index 00000000000..913a57378e2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/root.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ custom
+ 25
+
+
+
+
+
+ false
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/BeanDefinitionBuilderTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/BeanDefinitionBuilderTests.java
new file mode 100644
index 00000000000..0aedf79d322
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/BeanDefinitionBuilderTests.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.support;
+
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.framework.PrototypeTargetTests.TestBean;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public class BeanDefinitionBuilderTests extends TestCase {
+
+ public void testBeanClassWithSimpleProperty() {
+ String[] dependsOn = new String[] { "A", "B", "C" };
+ BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(TestBean.class);
+ bdb.setSingleton(false).addPropertyReference("age", "15");
+ for (int i = 0; i < dependsOn.length; i++) {
+ bdb.addDependsOn(dependsOn[i]);
+ }
+
+ RootBeanDefinition rbd = (RootBeanDefinition) bdb.getBeanDefinition();
+ assertFalse(rbd.isSingleton());
+ assertEquals(TestBean.class, rbd.getBeanClass());
+ assertTrue("Depends on was added", Arrays.equals(dependsOn, rbd.getDependsOn()));
+ assertTrue(rbd.getPropertyValues().contains("age"));
+ }
+
+ public void testBeanClassWithFactoryMethod() {
+ BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(TestBean.class, "create");
+ RootBeanDefinition rbd = (RootBeanDefinition) bdb.getBeanDefinition();
+ assertTrue(rbd.hasBeanClass());
+ assertEquals(TestBean.class, rbd.getBeanClass());
+ assertEquals("create", rbd.getFactoryMethodName());
+ }
+
+ public void testBeanClassName() {
+ BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(TestBean.class.getName());
+ RootBeanDefinition rbd = (RootBeanDefinition) bdb.getBeanDefinition();
+ assertFalse(rbd.hasBeanClass());
+ assertEquals(TestBean.class.getName(), rbd.getBeanClassName());
+ }
+
+ public void testBeanClassNameWithFactoryMethod() {
+ BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(TestBean.class.getName(), "create");
+ RootBeanDefinition rbd = (RootBeanDefinition) bdb.getBeanDefinition();
+ assertFalse(rbd.hasBeanClass());
+ assertEquals(TestBean.class.getName(), rbd.getBeanClassName());
+ assertEquals("create", rbd.getFactoryMethodName());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/BeanDefinitionTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/BeanDefinitionTests.java
new file mode 100644
index 00000000000..786e41f08df
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/BeanDefinitionTests.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory.support;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.config.BeanDefinitionHolder;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class BeanDefinitionTests extends TestCase {
+
+ public void testBeanDefinitionEquality() {
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
+ bd.setAbstract(true);
+ bd.setLazyInit(true);
+ bd.setScope("request");
+ RootBeanDefinition otherBd = new RootBeanDefinition(TestBean.class);
+ assertTrue(!bd.equals(otherBd));
+ assertTrue(!otherBd.equals(bd));
+ otherBd.setAbstract(true);
+ otherBd.setLazyInit(true);
+ otherBd.setScope("request");
+ assertTrue(bd.equals(otherBd));
+ assertTrue(otherBd.equals(bd));
+ assertTrue(bd.hashCode() == otherBd.hashCode());
+ }
+
+ public void testBeanDefinitionEqualityWithPropertyValues() {
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
+ bd.getPropertyValues().addPropertyValue("name", "myName");
+ bd.getPropertyValues().addPropertyValue("age", "99");
+ RootBeanDefinition otherBd = new RootBeanDefinition(TestBean.class);
+ otherBd.getPropertyValues().addPropertyValue("name", "myName");
+ assertTrue(!bd.equals(otherBd));
+ assertTrue(!otherBd.equals(bd));
+ otherBd.getPropertyValues().addPropertyValue("age", "11");
+ assertTrue(!bd.equals(otherBd));
+ assertTrue(!otherBd.equals(bd));
+ otherBd.getPropertyValues().addPropertyValue("age", "99");
+ assertTrue(bd.equals(otherBd));
+ assertTrue(otherBd.equals(bd));
+ assertTrue(bd.hashCode() == otherBd.hashCode());
+ }
+
+ public void testBeanDefinitionEqualityWithConstructorArguments() {
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
+ bd.getConstructorArgumentValues().addGenericArgumentValue("test");
+ bd.getConstructorArgumentValues().addIndexedArgumentValue(1, new Integer(5));
+ RootBeanDefinition otherBd = new RootBeanDefinition(TestBean.class);
+ otherBd.getConstructorArgumentValues().addGenericArgumentValue("test");
+ assertTrue(!bd.equals(otherBd));
+ assertTrue(!otherBd.equals(bd));
+ otherBd.getConstructorArgumentValues().addIndexedArgumentValue(1, new Integer(9));
+ assertTrue(!bd.equals(otherBd));
+ assertTrue(!otherBd.equals(bd));
+ otherBd.getConstructorArgumentValues().addIndexedArgumentValue(1, new Integer(5));
+ assertTrue(bd.equals(otherBd));
+ assertTrue(otherBd.equals(bd));
+ assertTrue(bd.hashCode() == otherBd.hashCode());
+ }
+
+ public void testBeanDefinitionEqualityWithTypedConstructorArguments() {
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
+ bd.getConstructorArgumentValues().addGenericArgumentValue("test", "int");
+ bd.getConstructorArgumentValues().addIndexedArgumentValue(1, new Integer(5), "long");
+ RootBeanDefinition otherBd = new RootBeanDefinition(TestBean.class);
+ otherBd.getConstructorArgumentValues().addGenericArgumentValue("test", "int");
+ otherBd.getConstructorArgumentValues().addIndexedArgumentValue(1, new Integer(5));
+ assertTrue(!bd.equals(otherBd));
+ assertTrue(!otherBd.equals(bd));
+ otherBd.getConstructorArgumentValues().addIndexedArgumentValue(1, new Integer(5), "int");
+ assertTrue(!bd.equals(otherBd));
+ assertTrue(!otherBd.equals(bd));
+ otherBd.getConstructorArgumentValues().addIndexedArgumentValue(1, new Integer(5), "long");
+ assertTrue(bd.equals(otherBd));
+ assertTrue(otherBd.equals(bd));
+ assertTrue(bd.hashCode() == otherBd.hashCode());
+ }
+
+ public void testBeanDefinitionHolderEquality() {
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
+ bd.setAbstract(true);
+ bd.setLazyInit(true);
+ bd.setScope("request");
+ BeanDefinitionHolder holder = new BeanDefinitionHolder(bd, "bd");
+ RootBeanDefinition otherBd = new RootBeanDefinition(TestBean.class);
+ assertTrue(!bd.equals(otherBd));
+ assertTrue(!otherBd.equals(bd));
+ otherBd.setAbstract(true);
+ otherBd.setLazyInit(true);
+ otherBd.setScope("request");
+ BeanDefinitionHolder otherHolder = new BeanDefinitionHolder(bd, "bd");
+ assertTrue(holder.equals(otherHolder));
+ assertTrue(otherHolder.equals(holder));
+ assertTrue(holder.hashCode() == otherHolder.hashCode());
+ }
+
+ public void testBeanDefinitionMerging() {
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
+ bd.getConstructorArgumentValues().addGenericArgumentValue("test");
+ bd.getConstructorArgumentValues().addIndexedArgumentValue(1, new Integer(5));
+ bd.getPropertyValues().addPropertyValue("name", "myName");
+ bd.getPropertyValues().addPropertyValue("age", "99");
+
+ ChildBeanDefinition childBd = new ChildBeanDefinition("bd");
+
+ RootBeanDefinition mergedBd = new RootBeanDefinition(bd);
+ mergedBd.overrideFrom(childBd);
+ assertEquals(2, mergedBd.getConstructorArgumentValues().getArgumentCount());
+ assertEquals(2, mergedBd.getPropertyValues().size());
+ assertEquals(bd, mergedBd);
+
+ mergedBd.getConstructorArgumentValues().getArgumentValue(1, null).setValue(new Integer(9));
+ assertEquals(new Integer(5), bd.getConstructorArgumentValues().getArgumentValue(1, null).getValue());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/DefinitionMetadataEqualsHashCodeTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/DefinitionMetadataEqualsHashCodeTests.java
new file mode 100644
index 00000000000..48985a82e32
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/DefinitionMetadataEqualsHashCodeTests.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.beans.factory.support;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
+
+/**
+ * @author Rob Harrop
+ */
+public class DefinitionMetadataEqualsHashCodeTests extends TestCase {
+
+ public void testRootBeanDefinitionEqualsAndHashCode() throws Exception {
+ RootBeanDefinition master = new RootBeanDefinition(TestBean.class);
+ RootBeanDefinition equal = new RootBeanDefinition(TestBean.class);
+ RootBeanDefinition notEqual = new RootBeanDefinition(String.class);
+ RootBeanDefinition subclass = new RootBeanDefinition(TestBean.class) {};
+ setBaseProperties(master);
+ setBaseProperties(equal);
+ setBaseProperties(notEqual);
+ setBaseProperties(subclass);
+
+ assertEqualsContract(master, equal, notEqual, subclass);
+ assertEquals("Hash code for equal instances should match", master.hashCode(), equal.hashCode());
+ }
+
+ public void testChildBeanDefinitionEqualsAndHashCode() throws Exception {
+ ChildBeanDefinition master = new ChildBeanDefinition("foo");
+ ChildBeanDefinition equal = new ChildBeanDefinition("foo");
+ ChildBeanDefinition notEqual = new ChildBeanDefinition("bar");
+ ChildBeanDefinition subclass = new ChildBeanDefinition("foo"){};
+ setBaseProperties(master);
+ setBaseProperties(equal);
+ setBaseProperties(notEqual);
+ setBaseProperties(subclass);
+
+ assertEqualsContract(master, equal, notEqual, subclass);
+ assertEquals("Hash code for equal instances should match", master.hashCode(), equal.hashCode());
+ }
+
+ public void testRuntimeBeanReference() throws Exception {
+ RuntimeBeanReference master = new RuntimeBeanReference("name");
+ RuntimeBeanReference equal = new RuntimeBeanReference("name");
+ RuntimeBeanReference notEqual = new RuntimeBeanReference("someOtherName");
+ RuntimeBeanReference subclass = new RuntimeBeanReference("name"){};
+ assertEqualsContract(master, equal, notEqual, subclass);
+ }
+ private void setBaseProperties(AbstractBeanDefinition definition) {
+ definition.setAbstract(true);
+ definition.setAttribute("foo", "bar");
+ definition.setAutowireCandidate(false);
+ definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
+ //definition.getConstructorArgumentValues().addGenericArgumentValue("foo");
+ definition.setDependencyCheck(AbstractBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
+ definition.setDependsOn(new String[]{"foo", "bar"});
+ definition.setDestroyMethodName("destroy");
+ definition.setEnforceDestroyMethod(false);
+ definition.setEnforceInitMethod(true);
+ definition.setFactoryBeanName("factoryBean");
+ definition.setFactoryMethodName("factoryMethod");
+ definition.setInitMethodName("init");
+ definition.setLazyInit(true);
+ definition.getMethodOverrides().addOverride(new LookupOverride("foo", "bar"));
+ definition.getMethodOverrides().addOverride(new ReplaceOverride("foo", "bar"));
+ definition.getPropertyValues().addPropertyValue("foo", "bar");
+ definition.setResourceDescription("desc");
+ definition.setRole(BeanDefinition.ROLE_APPLICATION);
+ definition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
+ definition.setSource("foo");
+ }
+
+ private void assertEqualsContract(Object master, Object equal, Object notEqual, Object subclass) {
+ assertEquals("Should be equal", master, equal);
+ assertFalse("Should not be equal", master.equals(notEqual));
+ assertEquals("Subclass should be equal", master, subclass);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/ManagedListTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/ManagedListTests.java
new file mode 100644
index 00000000000..9dc27c7f373
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/ManagedListTests.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.support;
+
+import java.util.List;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class ManagedListTests extends TestCase {
+
+ public void testMergeSunnyDay() {
+ ManagedList parent = new ManagedList();
+ parent.add("one");
+ parent.add("two");
+ ManagedList child = new ManagedList();
+ child.add("three");
+ child.setMergeEnabled(true);
+ List mergedList = (List) child.merge(parent);
+ assertEquals("merge() obviously did not work.", 3, mergedList.size());
+ }
+
+ public void testMergeWithNullParent() {
+ ManagedList child = new ManagedList();
+ child.add("one");
+ child.setMergeEnabled(true);
+ assertSame(child, child.merge(null));
+ }
+
+ public void testMergeNotAllowedWhenMergeNotEnabled() {
+ ManagedList child = new ManagedList();
+ try {
+ child.merge(null);
+ fail("Must have failed by this point (cannot merge() when the mergeEnabled property is false.");
+ }
+ catch (IllegalStateException expected) {
+ }
+ }
+
+ public void testMergeWithNonCompatibleParentType() {
+ ManagedList child = new ManagedList();
+ child.add("one");
+ child.setMergeEnabled(true);
+ try {
+ child.merge("hello");
+ fail("Must have failed by this point.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testMergeEmptyChild() {
+ ManagedList parent = new ManagedList();
+ parent.add("one");
+ parent.add("two");
+ ManagedList child = new ManagedList();
+ child.setMergeEnabled(true);
+ List mergedList = (List) child.merge(parent);
+ assertEquals("merge() obviously did not work.", 2, mergedList.size());
+ }
+
+ public void testMergeChildValuesOverrideTheParents() {
+ // doesn't make a whole lotta sense in the context of a list...
+ ManagedList parent = new ManagedList();
+ parent.add("one");
+ parent.add("two");
+ ManagedList child = new ManagedList();
+ child.add("one");
+ child.setMergeEnabled(true);
+ List mergedList = (List) child.merge(parent);
+ assertEquals("merge() obviously did not work.", 3, mergedList.size());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/ManagedMapTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/ManagedMapTests.java
new file mode 100644
index 00000000000..c86752d8e9a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/ManagedMapTests.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.support;
+
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class ManagedMapTests extends TestCase {
+
+ public void testMergeSunnyDay() {
+ ManagedMap parent = new ManagedMap();
+ parent.put("one", "one");
+ parent.put("two", "two");
+ ManagedMap child = new ManagedMap();
+ child.put("three", "three");
+ child.setMergeEnabled(true);
+ Map mergedMap = (Map) child.merge(parent);
+ assertEquals("merge() obviously did not work.", 3, mergedMap.size());
+ }
+
+ public void testMergeWithNullParent() {
+ ManagedMap child = new ManagedMap();
+ child.setMergeEnabled(true);
+ assertSame(child, child.merge(null));
+ }
+
+ public void testMergeWithNonCompatibleParentType() {
+ ManagedMap map = new ManagedMap();
+ map.setMergeEnabled(true);
+ try {
+ map.merge("hello");
+ fail("Must have failed by this point.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testMergeNotAllowedWhenMergeNotEnabled() {
+ ManagedMap map = new ManagedMap();
+ try {
+ map.merge(null);
+ fail("Must have failed by this point (cannot merge() when the mergeEnabled property is false.");
+ }
+ catch (IllegalStateException expected) {
+ }
+ }
+
+ public void testMergeEmptyChild() {
+ ManagedMap parent = new ManagedMap();
+ parent.put("one", "one");
+ parent.put("two", "two");
+ ManagedMap child = new ManagedMap();
+ child.setMergeEnabled(true);
+ Map mergedMap = (Map) child.merge(parent);
+ assertEquals("merge() obviously did not work.", 2, mergedMap.size());
+ }
+
+ public void testMergeChildValuesOverrideTheParents() {
+ ManagedMap parent = new ManagedMap();
+ parent.put("one", "one");
+ parent.put("two", "two");
+ ManagedMap child = new ManagedMap();
+ child.put("one", "fork");
+ child.setMergeEnabled(true);
+ Map mergedMap = (Map) child.merge(parent);
+ // child value for 'one' must override parent value...
+ assertEquals("merge() obviously did not work.", 2, mergedMap.size());
+ assertEquals("Parent value not being overridden during merge().", "fork", mergedMap.get("one"));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/ManagedPropertiesTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/ManagedPropertiesTests.java
new file mode 100644
index 00000000000..7594ab6cddd
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/ManagedPropertiesTests.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.support;
+
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class ManagedPropertiesTests extends TestCase {
+
+ public void testMergeSunnyDay() {
+ ManagedProperties parent = new ManagedProperties();
+ parent.setProperty("one", "one");
+ parent.setProperty("two", "two");
+ ManagedProperties child = new ManagedProperties();
+ child.setProperty("three", "three");
+ child.setMergeEnabled(true);
+ Map mergedMap = (Map) child.merge(parent);
+ assertEquals("merge() obviously did not work.", 3, mergedMap.size());
+ }
+
+ public void testMergeWithNullParent() {
+ ManagedProperties child = new ManagedProperties();
+ child.setMergeEnabled(true);
+ assertSame(child, child.merge(null));
+ }
+
+ public void testMergeWithNonCompatibleParentType() {
+ ManagedProperties map = new ManagedProperties();
+ map.setMergeEnabled(true);
+ try {
+ map.merge("hello");
+ fail("Must have failed by this point.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testMergeNotAllowedWhenMergeNotEnabled() {
+ ManagedProperties map = new ManagedProperties();
+ try {
+ map.merge(null);
+ fail("Must have failed by this point (cannot merge() when the mergeEnabled property is false.");
+ }
+ catch (IllegalStateException expected) {
+ }
+ }
+
+ public void testMergeEmptyChild() {
+ ManagedProperties parent = new ManagedProperties();
+ parent.setProperty("one", "one");
+ parent.setProperty("two", "two");
+ ManagedProperties child = new ManagedProperties();
+ child.setMergeEnabled(true);
+ Map mergedMap = (Map) child.merge(parent);
+ assertEquals("merge() obviously did not work.", 2, mergedMap.size());
+ }
+
+ public void testMergeChildValuesOverrideTheParents() {
+ ManagedProperties parent = new ManagedProperties();
+ parent.setProperty("one", "one");
+ parent.setProperty("two", "two");
+ ManagedProperties child = new ManagedProperties();
+ child.setProperty("one", "fork");
+ child.setMergeEnabled(true);
+ Map mergedMap = (Map) child.merge(parent);
+ // child value for 'one' must override parent value...
+ assertEquals("merge() obviously did not work.", 2, mergedMap.size());
+ assertEquals("Parent value not being overridden during merge().", "fork", mergedMap.get("one"));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/ManagedSetTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/ManagedSetTests.java
new file mode 100644
index 00000000000..0eea409ab89
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/ManagedSetTests.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.support;
+
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class ManagedSetTests extends TestCase {
+
+ public void testMergeSunnyDay() {
+ ManagedSet parent = new ManagedSet();
+ parent.add("one");
+ parent.add("two");
+ ManagedSet child = new ManagedSet();
+ child.add("three");
+ child.setMergeEnabled(true);
+ Set mergedSet = (Set) child.merge(parent);
+ assertEquals("merge() obviously did not work.", 3, mergedSet.size());
+ }
+
+ public void testMergeWithNullParent() {
+ ManagedSet child = new ManagedSet();
+ child.add("one");
+ child.setMergeEnabled(true);
+ assertSame(child, child.merge(null));
+ }
+
+ public void testMergeNotAllowedWhenMergeNotEnabled() {
+ ManagedSet child = new ManagedSet();
+ try {
+ child.merge(null);
+ fail("Must have failed by this point (cannot merge() when the mergeEnabled property is false.");
+ }
+ catch (IllegalStateException expected) {
+ }
+ }
+
+ public void testMergeWithNonCompatibleParentType() {
+ ManagedSet child = new ManagedSet();
+ child.add("one");
+ child.setMergeEnabled(true);
+ try {
+ child.merge("hello");
+ fail("Must have failed by this point.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testMergeEmptyChild() {
+ ManagedSet parent = new ManagedSet();
+ parent.add("one");
+ parent.add("two");
+ ManagedSet child = new ManagedSet();
+ child.setMergeEnabled(true);
+ Set mergedSet = (Set) child.merge(parent);
+ assertEquals("merge() obviously did not work.", 2, mergedSet.size());
+ }
+
+ public void testMergeChildValuesOverrideTheParents() {
+ // asserts that the set contract is not violated during a merge() operation...
+ ManagedSet parent = new ManagedSet();
+ parent.add("one");
+ parent.add("two");
+ ManagedSet child = new ManagedSet();
+ child.add("one");
+ child.setMergeEnabled(true);
+ Set mergedSet = (Set) child.merge(parent);
+ assertEquals("merge() obviously did not work.", 2, mergedSet.size());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/PropertiesBeanDefinitionReaderTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/PropertiesBeanDefinitionReaderTests.java
new file mode 100644
index 00000000000..7f7618914d6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/PropertiesBeanDefinitionReaderTests.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory.support;
+
+import junit.framework.TestCase;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.beans.TestBean;
+
+/**
+ * @author Rob Harrop
+ */
+public class PropertiesBeanDefinitionReaderTests extends TestCase {
+
+ private DefaultListableBeanFactory beanFactory;
+
+ private PropertiesBeanDefinitionReader reader;
+
+ protected void setUp() throws Exception {
+ this.beanFactory = new DefaultListableBeanFactory();
+ this.reader = new PropertiesBeanDefinitionReader(beanFactory);
+ }
+
+ public void testWithSimpleConstructorArg() {
+ this.reader.loadBeanDefinitions(new ClassPathResource("simpleConstructorArg.properties", getClass()));
+ TestBean bean = (TestBean)this.beanFactory.getBean("testBean");
+ assertEquals("Rob Harrop", bean.getName());
+ }
+
+ public void testWithConstructorArgRef() throws Exception {
+ this.reader.loadBeanDefinitions(new ClassPathResource("refConstructorArg.properties", getClass()));
+ TestBean rob = (TestBean)this.beanFactory.getBean("rob");
+ TestBean sally = (TestBean)this.beanFactory.getBean("sally");
+ assertEquals(sally, rob.getSpouse());
+ }
+
+ public void testWithMultipleConstructorsArgs() throws Exception {
+ this.reader.loadBeanDefinitions(new ClassPathResource("multiConstructorArgs.properties", getClass()));
+ TestBean bean = (TestBean)this.beanFactory.getBean("testBean");
+ assertEquals("Rob Harrop", bean.getName());
+ assertEquals(23, bean.getAge());
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/multiConstructorArgs.properties b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/multiConstructorArgs.properties
new file mode 100644
index 00000000000..fa36ea20e7b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/multiConstructorArgs.properties
@@ -0,0 +1,3 @@
+testBean.(class)=org.springframework.beans.TestBean
+testBean.$0=Rob Harrop
+testBean.$1=23
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/refConstructorArg.properties b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/refConstructorArg.properties
new file mode 100644
index 00000000000..05b6f9a00e7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/refConstructorArg.properties
@@ -0,0 +1,5 @@
+sally.(class)=org.springframework.beans.TestBean
+sally.name=Sally
+
+rob.(class)=org.springframework.beans.TestBean
+rob.$0(ref)=sally
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/simpleConstructorArg.properties b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/simpleConstructorArg.properties
new file mode 100644
index 00000000000..92a216ca41d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/support/simpleConstructorArg.properties
@@ -0,0 +1,2 @@
+testBean.(class)=org.springframework.beans.TestBean
+testBean.$0=Rob Harrop
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/wiring/BeanConfigurerSupportTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/wiring/BeanConfigurerSupportTests.java
new file mode 100644
index 00000000000..a381e50ed76
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/wiring/BeanConfigurerSupportTests.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.beans.factory.wiring;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class BeanConfigurerSupportTests extends TestCase {
+
+ public void testSupplyIncompatibleBeanFactoryImplementation() throws Exception {
+ MockControl mock = MockControl.createControl(BeanFactory.class);
+ mock.replay();
+ try {
+ new StubBeanConfigurerSupport().setBeanFactory((BeanFactory) mock.getMock());
+ fail("Must have thrown an IllegalArgumentException by this point (incompatible BeanFactory implementation supplied)");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ mock.verify();
+ }
+
+ public void testConfigureBeanDoesNothingIfBeanWiringInfoResolverResolvesToNull() throws Exception {
+ TestBean beanInstance = new TestBean();
+
+ MockControl mock = MockControl.createControl(BeanWiringInfoResolver.class);
+ BeanWiringInfoResolver resolver = (BeanWiringInfoResolver) mock.getMock();
+ resolver.resolveWiringInfo(beanInstance);
+ mock.setReturnValue(null);
+ mock.replay();
+
+ BeanConfigurerSupport configurer = new StubBeanConfigurerSupport();
+ configurer.setBeanWiringInfoResolver(resolver);
+ configurer.setBeanFactory(new DefaultListableBeanFactory());
+ configurer.configureBean(beanInstance);
+ mock.verify();
+ assertNull(beanInstance.getName());
+ }
+
+ public void testConfigureBeanDoesNothingIfNoBeanFactoryHasBeenSet() throws Exception {
+ TestBean beanInstance = new TestBean();
+ BeanConfigurerSupport configurer = new StubBeanConfigurerSupport();
+ configurer.configureBean(beanInstance);
+ assertNull(beanInstance.getName());
+ }
+
+ public void testConfigureBeanReallyDoesDefaultToUsingTheFullyQualifiedClassNameOfTheSuppliedBeanInstance() throws Exception {
+ TestBean beanInstance = new TestBean();
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(TestBean.class);
+ builder.addPropertyValue("name", "Harriet Wheeler");
+
+ DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
+ factory.registerBeanDefinition(beanInstance.getClass().getName(), builder.getBeanDefinition());
+
+ BeanConfigurerSupport configurer = new StubBeanConfigurerSupport();
+ configurer.setBeanFactory(factory);
+ configurer.afterPropertiesSet();
+ configurer.configureBean(beanInstance);
+ assertEquals("Bean is evidently not being configured (for some reason)", "Harriet Wheeler", beanInstance.getName());
+ }
+
+ public void testConfigureBeanPerformsAutowiringByNameIfAppropriateBeanWiringInfoResolverIsPluggedIn() throws Exception {
+ TestBean beanInstance = new TestBean();
+ // spouse for autowiring by name...
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(TestBean.class);
+ builder.addConstructorArgValue("David Gavurin");
+
+ DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
+ factory.registerBeanDefinition("spouse", builder.getBeanDefinition());
+
+ MockControl mock = MockControl.createControl(BeanWiringInfoResolver.class);
+ BeanWiringInfoResolver resolver = (BeanWiringInfoResolver) mock.getMock();
+ resolver.resolveWiringInfo(beanInstance);
+ mock.setReturnValue(new BeanWiringInfo(BeanWiringInfo.AUTOWIRE_BY_NAME, false));
+ mock.replay();
+
+ BeanConfigurerSupport configurer = new StubBeanConfigurerSupport();
+ configurer.setBeanFactory(factory);
+ configurer.setBeanWiringInfoResolver(resolver);
+ configurer.configureBean(beanInstance);
+ assertEquals("Bean is evidently not being configured (for some reason)", "David Gavurin", beanInstance.getSpouse().getName());
+
+ mock.verify();
+ }
+
+ public void testConfigureBeanPerformsAutowiringByTypeIfAppropriateBeanWiringInfoResolverIsPluggedIn() throws Exception {
+ TestBean beanInstance = new TestBean();
+ // spouse for autowiring by type...
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(TestBean.class);
+ builder.addConstructorArgValue("David Gavurin");
+
+ DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
+ factory.registerBeanDefinition("Mmm, I fancy a salad!", builder.getBeanDefinition());
+
+ MockControl mock = MockControl.createControl(BeanWiringInfoResolver.class);
+ BeanWiringInfoResolver resolver = (BeanWiringInfoResolver) mock.getMock();
+ resolver.resolveWiringInfo(beanInstance);
+ mock.setReturnValue(new BeanWiringInfo(BeanWiringInfo.AUTOWIRE_BY_TYPE, false));
+ mock.replay();
+
+ BeanConfigurerSupport configurer = new StubBeanConfigurerSupport();
+ configurer.setBeanFactory(factory);
+ configurer.setBeanWiringInfoResolver(resolver);
+ configurer.configureBean(beanInstance);
+ assertEquals("Bean is evidently not being configured (for some reason)", "David Gavurin", beanInstance.getSpouse().getName());
+
+ mock.verify();
+ }
+
+
+ private static class StubBeanConfigurerSupport extends BeanConfigurerSupport {
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/wiring/BeanWiringInfoTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/wiring/BeanWiringInfoTests.java
new file mode 100644
index 00000000000..18ab24bedfb
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/wiring/BeanWiringInfoTests.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory.wiring;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for the BeanWiringInfo class.
+ *
+ * @author Rick Evans
+ */
+public final class BeanWiringInfoTests extends TestCase {
+
+ public void testCtorWithNullBeanName() throws Exception {
+ try {
+ new BeanWiringInfo(null);
+ fail("Must have thrown an IllegalArgumentException by this point (null argument).");
+ }
+ catch (IllegalArgumentException ex) {
+ }
+ }
+
+ public void testCtorWithWhitespacedBeanName() throws Exception {
+ try {
+ new BeanWiringInfo(" \t");
+ fail("Must have thrown an IllegalArgumentException by this point (bean name has only whitespace).");
+ }
+ catch (IllegalArgumentException ex) {
+ }
+ }
+
+ public void testCtorWithEmptyBeanName() throws Exception {
+ try {
+ new BeanWiringInfo("");
+ fail("Must have thrown an IllegalArgumentException by this point (bean name is empty).");
+ }
+ catch (IllegalArgumentException ex) {
+ }
+ }
+
+ public void testCtorWithNegativeIllegalAutowiringValue() throws Exception {
+ try {
+ new BeanWiringInfo(-1, true);
+ fail("Must have thrown an IllegalArgumentException by this point (out-of-range argument).");
+ }
+ catch (IllegalArgumentException ex) {
+ }
+ }
+
+ public void testCtorWithPositiveOutOfRangeAutowiringValue() throws Exception {
+ try {
+ new BeanWiringInfo(123871, true);
+ fail("Must have thrown an IllegalArgumentException by this point (out-of-range argument).");
+ }
+ catch (IllegalArgumentException ex) {
+ }
+ }
+
+ public void testUsingAutowireCtorIndicatesAutowiring() throws Exception {
+ BeanWiringInfo info = new BeanWiringInfo(BeanWiringInfo.AUTOWIRE_BY_NAME, true);
+ assertTrue(info.indicatesAutowiring());
+ }
+
+ public void testUsingBeanNameCtorDoesNotIndicateAutowiring() throws Exception {
+ BeanWiringInfo info = new BeanWiringInfo("fooService");
+ assertFalse(info.indicatesAutowiring());
+ }
+
+ public void testNoDependencyCheckValueIsPreserved() throws Exception {
+ BeanWiringInfo info = new BeanWiringInfo(BeanWiringInfo.AUTOWIRE_BY_NAME, true);
+ assertTrue(info.getDependencyCheck());
+ }
+
+ public void testDependencyCheckValueIsPreserved() throws Exception {
+ BeanWiringInfo info = new BeanWiringInfo(BeanWiringInfo.AUTOWIRE_BY_TYPE, false);
+ assertFalse(info.getDependencyCheck());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/wiring/ClassNameBeanWiringInfoResolverTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/wiring/ClassNameBeanWiringInfoResolverTests.java
new file mode 100644
index 00000000000..6bacb2ce70d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/wiring/ClassNameBeanWiringInfoResolverTests.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory.wiring;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for the ClassNameBeanWiringInfoResolver class.
+ *
+ * @author Rick Evans
+ */
+public final class ClassNameBeanWiringInfoResolverTests extends TestCase {
+
+ public void testResolveWiringInfoWithNullBeanInstance() throws Exception {
+ try {
+ new ClassNameBeanWiringInfoResolver().resolveWiringInfo(null);
+ fail("Must have thrown an IllegalArgumentException by this point (null argument).");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testResolveWiringInfo() {
+ ClassNameBeanWiringInfoResolver resolver = new ClassNameBeanWiringInfoResolver();
+ Long beanInstance = new Long(1);
+ BeanWiringInfo info = resolver.resolveWiringInfo(beanInstance);
+ assertNotNull(info);
+ assertEquals("Not resolving bean name to the class name of the supplied bean instance as per class contract.",
+ beanInstance.getClass().getName(), info.getBeanName());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/AutowireWithExclusionTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/AutowireWithExclusionTests.java
new file mode 100644
index 00000000000..a376eac4908
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/AutowireWithExclusionTests.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.CountingFactory;
+import org.springframework.beans.factory.config.PropertiesFactoryBean;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class AutowireWithExclusionTests extends TestCase {
+
+ public void testByTypeAutowireWithAutoSelfExclusion() throws Exception {
+ CountingFactory.reset();
+ XmlBeanFactory beanFactory = getBeanFactory("autowire-with-exclusion.xml");
+ beanFactory.preInstantiateSingletons();
+ TestBean rob = (TestBean) beanFactory.getBean("rob");
+ TestBean sally = (TestBean) beanFactory.getBean("sally");
+ assertEquals(sally, rob.getSpouse());
+ assertEquals(1, CountingFactory.getFactoryBeanInstanceCount());
+ }
+
+ public void testByTypeAutowireWithExclusion() throws Exception {
+ CountingFactory.reset();
+ XmlBeanFactory beanFactory = getBeanFactory("autowire-with-exclusion.xml");
+ beanFactory.preInstantiateSingletons();
+ TestBean rob = (TestBean) beanFactory.getBean("rob");
+ assertEquals("props1", rob.getSomeProperties().getProperty("name"));
+ assertEquals(1, CountingFactory.getFactoryBeanInstanceCount());
+ }
+
+ public void testByTypeAutowireWithExclusionInParentFactory() throws Exception {
+ CountingFactory.reset();
+ XmlBeanFactory parent = getBeanFactory("autowire-with-exclusion.xml");
+ parent.preInstantiateSingletons();
+ DefaultListableBeanFactory child = new DefaultListableBeanFactory(parent);
+ RootBeanDefinition robDef = new RootBeanDefinition(TestBean.class, RootBeanDefinition.AUTOWIRE_BY_TYPE);
+ robDef.getPropertyValues().addPropertyValue("spouse", new RuntimeBeanReference("sally"));
+ child.registerBeanDefinition("rob2", robDef);
+ TestBean rob = (TestBean) child.getBean("rob2");
+ assertEquals("props1", rob.getSomeProperties().getProperty("name"));
+ assertEquals(1, CountingFactory.getFactoryBeanInstanceCount());
+ }
+
+ public void testByTypeAutowireWithPrimaryInParentFactory() throws Exception {
+ CountingFactory.reset();
+ XmlBeanFactory parent = getBeanFactory("autowire-with-exclusion.xml");
+ ((AbstractBeanDefinition) parent.getBeanDefinition("props1")).setPrimary(true);
+ parent.preInstantiateSingletons();
+ DefaultListableBeanFactory child = new DefaultListableBeanFactory(parent);
+ RootBeanDefinition robDef = new RootBeanDefinition(TestBean.class, RootBeanDefinition.AUTOWIRE_BY_TYPE);
+ robDef.getPropertyValues().addPropertyValue("spouse", new RuntimeBeanReference("sally"));
+ child.registerBeanDefinition("rob2", robDef);
+ RootBeanDefinition propsDef = new RootBeanDefinition(PropertiesFactoryBean.class);
+ propsDef.getPropertyValues().addPropertyValue("properties", "name=props3");
+ child.registerBeanDefinition("props3", propsDef);
+ TestBean rob = (TestBean) child.getBean("rob2");
+ assertEquals("props1", rob.getSomeProperties().getProperty("name"));
+ assertEquals(1, CountingFactory.getFactoryBeanInstanceCount());
+ }
+
+ public void testByTypeAutowireWithPrimaryOverridingParentFactory() throws Exception {
+ CountingFactory.reset();
+ XmlBeanFactory parent = getBeanFactory("autowire-with-exclusion.xml");
+ parent.preInstantiateSingletons();
+ DefaultListableBeanFactory child = new DefaultListableBeanFactory(parent);
+ RootBeanDefinition robDef = new RootBeanDefinition(TestBean.class, RootBeanDefinition.AUTOWIRE_BY_TYPE);
+ robDef.getPropertyValues().addPropertyValue("spouse", new RuntimeBeanReference("sally"));
+ child.registerBeanDefinition("rob2", robDef);
+ RootBeanDefinition propsDef = new RootBeanDefinition(PropertiesFactoryBean.class);
+ propsDef.getPropertyValues().addPropertyValue("properties", "name=props3");
+ propsDef.setPrimary(true);
+ child.registerBeanDefinition("props3", propsDef);
+ TestBean rob = (TestBean) child.getBean("rob2");
+ assertEquals("props3", rob.getSomeProperties().getProperty("name"));
+ assertEquals(1, CountingFactory.getFactoryBeanInstanceCount());
+ }
+
+ public void testByTypeAutowireWithInclusion() throws Exception {
+ CountingFactory.reset();
+ XmlBeanFactory beanFactory = getBeanFactory("autowire-with-inclusion.xml");
+ beanFactory.preInstantiateSingletons();
+ TestBean rob = (TestBean) beanFactory.getBean("rob");
+ assertEquals("props1", rob.getSomeProperties().getProperty("name"));
+ assertEquals(1, CountingFactory.getFactoryBeanInstanceCount());
+ }
+
+ public void testByTypeAutowireWithSelectiveInclusion() throws Exception {
+ CountingFactory.reset();
+ XmlBeanFactory beanFactory = getBeanFactory("autowire-with-selective-inclusion.xml");
+ beanFactory.preInstantiateSingletons();
+ TestBean rob = (TestBean) beanFactory.getBean("rob");
+ assertEquals("props1", rob.getSomeProperties().getProperty("name"));
+ assertEquals(1, CountingFactory.getFactoryBeanInstanceCount());
+ }
+
+ public void testConstructorAutowireWithAutoSelfExclusion() throws Exception {
+ XmlBeanFactory beanFactory = getBeanFactory("autowire-constructor-with-exclusion.xml");
+ TestBean rob = (TestBean) beanFactory.getBean("rob");
+ TestBean sally = (TestBean) beanFactory.getBean("sally");
+ assertEquals(sally, rob.getSpouse());
+ TestBean rob2 = (TestBean) beanFactory.getBean("rob");
+ assertEquals(rob, rob2);
+ assertNotSame(rob, rob2);
+ assertEquals(rob.getSpouse(), rob2.getSpouse());
+ assertNotSame(rob.getSpouse(), rob2.getSpouse());
+ }
+
+ public void testConstructorAutowireWithExclusion() throws Exception {
+ XmlBeanFactory beanFactory = getBeanFactory("autowire-constructor-with-exclusion.xml");
+ TestBean rob = (TestBean) beanFactory.getBean("rob");
+ assertEquals("props1", rob.getSomeProperties().getProperty("name"));
+ }
+
+ private XmlBeanFactory getBeanFactory(String configPath) {
+ return new XmlBeanFactory(new ClassPathResource(configPath, getClass()));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/BeanNameGenerationTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/BeanNameGenerationTests.java
new file mode 100644
index 00000000000..ba05c516756
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/BeanNameGenerationTests.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class BeanNameGenerationTests extends TestCase {
+
+ private DefaultListableBeanFactory beanFactory;
+
+ public void setUp() {
+ this.beanFactory = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this.beanFactory);
+ reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE);
+ reader.loadBeanDefinitions(new ClassPathResource("beanNameGeneration.xml", getClass()));
+ }
+
+ public void testNaming() {
+ String className = GeneratedNameBean.class.getName();
+
+ String targetName = className + BeanDefinitionReaderUtils.GENERATED_BEAN_NAME_SEPARATOR + "0";
+ GeneratedNameBean topLevel1 = (GeneratedNameBean) beanFactory.getBean(targetName);
+ assertNotNull(topLevel1);
+
+ targetName = className + BeanDefinitionReaderUtils.GENERATED_BEAN_NAME_SEPARATOR + "1";
+ GeneratedNameBean topLevel2 = (GeneratedNameBean) beanFactory.getBean(targetName);
+ assertNotNull(topLevel2);
+
+ GeneratedNameBean child1 = topLevel1.getChild();
+ assertNotNull(child1.getBeanName());
+ assertTrue(child1.getBeanName().startsWith(className));
+
+ GeneratedNameBean child2 = topLevel2.getChild();
+ assertNotNull(child2.getBeanName());
+ assertTrue(child2.getBeanName().startsWith(className));
+
+ assertFalse(child1.getBeanName().equals(child2.getBeanName()));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/CollectionMergingTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/CollectionMergingTests.java
new file mode 100644
index 00000000000..42fae8868da
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/CollectionMergingTests.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.support.BeanDefinitionReader;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * Unit and integration tests for the collection merging support.
+ *
+ * @author Rob Harrop
+ * @author Rick Evans
+ */
+public class CollectionMergingTests extends TestCase {
+
+ private DefaultListableBeanFactory beanFactory;
+
+ protected void setUp() throws Exception {
+ this.beanFactory = new DefaultListableBeanFactory();
+ BeanDefinitionReader reader = new XmlBeanDefinitionReader(this.beanFactory);
+ reader.loadBeanDefinitions(new ClassPathResource("collectionMerging.xml", getClass()));
+ }
+
+ public void testMergeList() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("childWithList");
+ List list = bean.getSomeList();
+ assertEquals("Incorrect size", 3, list.size());
+ assertEquals(list.get(0), "Rob Harrop");
+ assertEquals(list.get(1), "Rod Johnson");
+ assertEquals(list.get(2), "Juergen Hoeller");
+ }
+
+ public void testMergeListWithInnerBeanAsListElement() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("childWithListOfRefs");
+ List list = bean.getSomeList();
+ assertNotNull(list);
+ assertEquals(3, list.size());
+ assertNotNull(list.get(2));
+ assertTrue(list.get(2) instanceof TestBean);
+ }
+
+ public void testMergeSet() {
+ TestBean bean = (TestBean) this.beanFactory.getBean("childWithSet");
+ Set set = bean.getSomeSet();
+ assertEquals("Incorrect size", 2, set.size());
+ assertTrue(set.contains("Rob Harrop"));
+ assertTrue(set.contains("Sally Greenwood"));
+ }
+
+ public void testMergeSetWithInnerBeanAsSetElement() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("childWithSetOfRefs");
+ Set set = bean.getSomeSet();
+ assertNotNull(set);
+ assertEquals(2, set.size());
+ Iterator it = set.iterator();
+ it.next();
+ Object o = it.next();
+ assertNotNull(o);
+ assertTrue(o instanceof TestBean);
+ assertEquals("Sally", ((TestBean) o).getName());
+ }
+
+ public void testMergeMap() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("childWithMap");
+ Map map = bean.getSomeMap();
+ assertEquals("Incorrect size", 3, map.size());
+ assertEquals(map.get("Rob"), "Sally");
+ assertEquals(map.get("Rod"), "Kerry");
+ assertEquals(map.get("Juergen"), "Eva");
+ }
+
+ public void testMergeMapWithInnerBeanAsMapEntryValue() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("childWithMapOfRefs");
+ Map map = bean.getSomeMap();
+ assertNotNull(map);
+ assertEquals(2, map.size());
+ assertNotNull(map.get("Rob"));
+ assertTrue(map.get("Rob") instanceof TestBean);
+ assertEquals("Sally", ((TestBean) map.get("Rob")).getName());
+ }
+
+ public void testMergeProperties() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("childWithProps");
+ Properties props = bean.getSomeProperties();
+ assertEquals("Incorrect size", 3, props.size());
+ assertEquals(props.getProperty("Rob"), "Sally");
+ assertEquals(props.getProperty("Rod"), "Kerry");
+ assertEquals(props.getProperty("Juergen"), "Eva");
+ }
+
+
+ public void testMergeListInConstructor() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("childWithListInConstructor");
+ List list = bean.getSomeList();
+ assertEquals("Incorrect size", 3, list.size());
+ assertEquals(list.get(0), "Rob Harrop");
+ assertEquals(list.get(1), "Rod Johnson");
+ assertEquals(list.get(2), "Juergen Hoeller");
+ }
+
+ public void testMergeListWithInnerBeanAsListElementInConstructor() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("childWithListOfRefsInConstructor");
+ List list = bean.getSomeList();
+ assertNotNull(list);
+ assertEquals(3, list.size());
+ assertNotNull(list.get(2));
+ assertTrue(list.get(2) instanceof TestBean);
+ }
+
+ public void testMergeSetInConstructor() {
+ TestBean bean = (TestBean) this.beanFactory.getBean("childWithSetInConstructor");
+ Set set = bean.getSomeSet();
+ assertEquals("Incorrect size", 2, set.size());
+ assertTrue(set.contains("Rob Harrop"));
+ assertTrue(set.contains("Sally Greenwood"));
+ }
+
+ public void testMergeSetWithInnerBeanAsSetElementInConstructor() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("childWithSetOfRefsInConstructor");
+ Set set = bean.getSomeSet();
+ assertNotNull(set);
+ assertEquals(2, set.size());
+ Iterator it = set.iterator();
+ it.next();
+ Object o = it.next();
+ assertNotNull(o);
+ assertTrue(o instanceof TestBean);
+ assertEquals("Sally", ((TestBean) o).getName());
+ }
+
+ public void testMergeMapInConstructor() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("childWithMapInConstructor");
+ Map map = bean.getSomeMap();
+ assertEquals("Incorrect size", 3, map.size());
+ assertEquals(map.get("Rob"), "Sally");
+ assertEquals(map.get("Rod"), "Kerry");
+ assertEquals(map.get("Juergen"), "Eva");
+ }
+
+ public void testMergeMapWithInnerBeanAsMapEntryValueInConstructor() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("childWithMapOfRefsInConstructor");
+ Map map = bean.getSomeMap();
+ assertNotNull(map);
+ assertEquals(2, map.size());
+ assertNotNull(map.get("Rob"));
+ assertTrue(map.get("Rob") instanceof TestBean);
+ assertEquals("Sally", ((TestBean) map.get("Rob")).getName());
+ }
+
+ public void testMergePropertiesInConstructor() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("childWithPropsInConstructor");
+ Properties props = bean.getSomeProperties();
+ assertEquals("Incorrect size", 3, props.size());
+ assertEquals(props.getProperty("Rob"), "Sally");
+ assertEquals(props.getProperty("Rod"), "Kerry");
+ assertEquals(props.getProperty("Juergen"), "Eva");
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/CollectionsWithDefaultTypesTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/CollectionsWithDefaultTypesTests.java
new file mode 100644
index 00000000000..ae298609c1f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/CollectionsWithDefaultTypesTests.java
@@ -0,0 +1,59 @@
+package org.springframework.beans.factory.xml;
+
+import junit.framework.TestCase;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.beans.TestBean;
+
+import java.util.List;
+import java.util.Set;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * @author Rob Harrop
+ */
+public class CollectionsWithDefaultTypesTests extends TestCase {
+
+ private XmlBeanFactory beanFactory;
+
+ protected void setUp() throws Exception {
+ this.beanFactory = new XmlBeanFactory(new ClassPathResource("collectionsWithDefaultTypes.xml", getClass()));
+ }
+
+ public void testListHasDefaultType() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("testBean");
+ List list = bean.getSomeList();
+ for (int i = 0; i < list.size(); i++) {
+ Object o = list.get(i);
+ assertEquals("Value type is incorrect", Integer.class, o.getClass());
+ }
+ }
+
+ public void testSetHasDefaultType() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("testBean");
+ Set set = bean.getSomeSet();
+ Iterator iterator = set.iterator();
+ while (iterator.hasNext()) {
+ Object o = iterator.next();
+ assertEquals("Value type is incorrect", Integer.class, o.getClass());
+ }
+ }
+
+ public void testMapHasDefaultKeyAndValueType() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("testBean");
+ assertMap(bean.getSomeMap());
+ }
+
+ public void testMapWithNestedElementsHasDefaultKeyAndValueType() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("testBean2");
+ assertMap(bean.getSomeMap());
+ }
+
+ private void assertMap(Map map) {
+ for (Iterator iterator = map.entrySet().iterator(); iterator.hasNext();) {
+ Map.Entry entry = (Map.Entry) iterator.next();
+ assertEquals("Key type is incorrect", Integer.class, entry.getKey().getClass());
+ assertEquals("Value type is incorrect", Boolean.class, entry.getValue().getClass());
+ }
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/ConstructorDependenciesBean.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/ConstructorDependenciesBean.java
new file mode 100644
index 00000000000..2d9f4a2b46b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/ConstructorDependenciesBean.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import java.io.Serializable;
+
+import org.springframework.beans.IndexedTestBean;
+import org.springframework.beans.TestBean;
+
+/**
+ * Simple bean used to check constructor dependency checking.
+ *
+ * @author Juergen Hoeller
+ * @since 09.11.2003
+ */
+public class ConstructorDependenciesBean implements Serializable {
+
+ private int age;
+
+ private String name;
+
+ private TestBean spouse1;
+
+ private TestBean spouse2;
+
+ private IndexedTestBean other;
+
+ public ConstructorDependenciesBean(int age) {
+ this.age = age;
+ }
+
+ public ConstructorDependenciesBean(String name) {
+ this.name = name;
+ }
+
+ public ConstructorDependenciesBean(TestBean spouse1) {
+ this.spouse1 = spouse1;
+ }
+
+ public ConstructorDependenciesBean(TestBean spouse1, TestBean spouse2) {
+ this.spouse1 = spouse1;
+ this.spouse2 = spouse2;
+ }
+
+ public ConstructorDependenciesBean(TestBean spouse1, TestBean spouse2, int age) {
+ this.spouse1 = spouse1;
+ this.spouse2 = spouse2;
+ this.age = age;
+ }
+
+ public ConstructorDependenciesBean(TestBean spouse1, TestBean spouse2, IndexedTestBean other) {
+ this.spouse1 = spouse1;
+ this.spouse2 = spouse2;
+ this.other = other;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public TestBean getSpouse1() {
+ return spouse1;
+ }
+
+ public TestBean getSpouse2() {
+ return spouse2;
+ }
+
+ public IndexedTestBean getOther() {
+ return other;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/ConstructorInjectedOverrides.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/ConstructorInjectedOverrides.java
new file mode 100644
index 00000000000..3bed86420ab
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/ConstructorInjectedOverrides.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import org.springframework.beans.ITestBean;
+
+/**
+ * Bean testing the ability to use both lookup method overrides
+ * and constructor injection.
+ * There is also a property ("setterString") to be set via
+ * Setter Injection.
+ *
+ * @author Rod Johnson
+ */
+public abstract class ConstructorInjectedOverrides {
+
+ private ITestBean tb;
+
+ private String setterString;
+
+ public ConstructorInjectedOverrides(ITestBean tb) {
+ this.tb = tb;
+ }
+
+ public ITestBean getTestBean() {
+ return this.tb;
+ }
+
+
+ protected abstract FactoryMethods createFactoryMethods();
+
+ /**
+ * @return Returns the setterString.
+ */
+ public String getSetterString() {
+ return setterString;
+ }
+ /**
+ * @param setterString The setterString to set.
+ */
+ public void setSetterString(String setterString) {
+ this.setterString = setterString;
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DefaultLifecycleMethodsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DefaultLifecycleMethodsTests.java
new file mode 100644
index 00000000000..8662e52c782
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DefaultLifecycleMethodsTests.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import junit.framework.TestCase;
+
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Rob Harrop
+ */
+public class DefaultLifecycleMethodsTests extends TestCase {
+
+ private XmlBeanFactory beanFactory;
+
+ protected void setUp() throws Exception {
+ this.beanFactory = new XmlBeanFactory(new ClassPathResource("defaultLifecycleMethods.xml", getClass()));
+ }
+
+ public void testLifecycleMethodsInvoked() {
+ LifecycleAwareBean bean = (LifecycleAwareBean) this.beanFactory.getBean("lifecycleAware");
+ assertTrue("Bean not initialized", bean.isInitCalled());
+ assertFalse("Bean destroyed too early", bean.isDestroyCalled());
+ this.beanFactory.destroySingletons();
+ assertTrue("Bean not destroyed", bean.isDestroyCalled());
+ }
+
+ public void testLifecycleMethodsDisabled() throws Exception {
+ LifecycleAwareBean bean = (LifecycleAwareBean) this.beanFactory.getBean("lifecycleMethodsDisabled");
+ assertFalse("Bean init method called incorrectly", bean.isInitCalled());
+ this.beanFactory.destroySingletons();
+ assertFalse("Bean destroy method called incorrectly", bean.isDestroyCalled());
+ }
+
+ public void testIgnoreDefaultLifecycleMethods() throws Exception {
+ try {
+ XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("ignoreDefaultLifecycleMethods.xml", getClass()));
+ bf.preInstantiateSingletons();
+ bf.destroySingletons();
+ }
+ catch (Exception ex) {
+ ex.printStackTrace();
+ fail("Should ignore non-existent default lifecycle methods");
+ }
+ }
+
+ public void testOverrideDefaultLifecycleMethods() throws Exception {
+ LifecycleAwareBean bean = (LifecycleAwareBean) this.beanFactory.getBean("overrideLifecycleMethods");
+ assertFalse("Default init method called incorrectly.", bean.isInitCalled());
+ assertTrue("Custom init method not called.", bean.isCustomInitCalled());
+ this.beanFactory.destroySingletons();
+ assertFalse("Default destory method called incorrectly.", bean.isDestroyCalled());
+ assertTrue("Custom destory method not called.", bean.isCustomDestroyCalled());
+ }
+
+
+ public static class LifecycleAwareBean {
+
+ private boolean initCalled;
+
+ private boolean destroyCalled;
+
+ private boolean customInitCalled;
+
+ private boolean customDestroyCalled;
+
+ public void init() {
+ this.initCalled = true;
+ }
+
+ public void destroy() {
+ this.destroyCalled = true;
+ }
+
+ public void customInit() {
+ this.customInitCalled = true;
+ }
+
+ public void customDestroy() {
+ this.customDestroyCalled = true;
+ }
+
+ public boolean isInitCalled() {
+ return initCalled;
+ }
+
+ public boolean isDestroyCalled() {
+ return destroyCalled;
+ }
+
+ public boolean isCustomInitCalled() {
+ return customInitCalled;
+ }
+
+ public boolean isCustomDestroyCalled() {
+ return customDestroyCalled;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DelegatingEntityResolverTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DelegatingEntityResolverTests.java
new file mode 100644
index 00000000000..25c95972987
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DelegatingEntityResolverTests.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import junit.framework.TestCase;
+import org.springframework.test.AssertThrows;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+
+/**
+ * Unit tests for the {@link DelegatingEntityResolver} class.
+ *
+ * @author Rick Evans
+ */
+public final class DelegatingEntityResolverTests extends TestCase {
+
+ public void testCtorWhereDtdEntityResolverIsNull() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new DelegatingEntityResolver(null, new NoOpEntityResolver());
+ }
+ }.runTest();
+ }
+
+ public void testCtorWhereSchemaEntityResolverIsNull() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new DelegatingEntityResolver(new NoOpEntityResolver(), null);
+ }
+ }.runTest();
+ }
+
+ public void testCtorWhereEntityResolversAreBothNull() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new DelegatingEntityResolver(null, null);
+ }
+ }.runTest();
+ }
+
+
+ private static final class NoOpEntityResolver implements EntityResolver {
+
+ public InputSource resolveEntity(String publicId, String systemId) {
+ return null;
+ }
+
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DependenciesBean.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DependenciesBean.java
new file mode 100644
index 00000000000..0ca614e051f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DependenciesBean.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanFactoryAware;
+
+/**
+ * Simple bean used to test dependency checking.
+ *
+ * @author Rod Johnson
+ * @since 04.09.2003
+ */
+public class DependenciesBean implements BeanFactoryAware {
+
+ private int age;
+
+ private String name;
+
+ private TestBean spouse;
+
+ private BeanFactory beanFactory;
+
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setSpouse(TestBean spouse) {
+ this.spouse = spouse;
+ }
+
+ public TestBean getSpouse() {
+ return spouse;
+ }
+
+ public void setBeanFactory(BeanFactory beanFactory) {
+ this.beanFactory = beanFactory;
+ }
+
+ public BeanFactory getBeanFactory() {
+ return beanFactory;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DerivedConstructorDependenciesBean.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DerivedConstructorDependenciesBean.java
new file mode 100644
index 00000000000..50bd0e368ff
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DerivedConstructorDependenciesBean.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import org.springframework.beans.IndexedTestBean;
+import org.springframework.beans.TestBean;
+
+/**
+ * Simple bean used to check constructor dependency checking.
+ *
+ * @author Juergen Hoeller
+ * @since 09.11.2003
+ */
+class DerivedConstructorDependenciesBean extends ConstructorDependenciesBean {
+
+ boolean initialized;
+ boolean destroyed;
+
+ DerivedConstructorDependenciesBean(TestBean spouse1, TestBean spouse2, IndexedTestBean other) {
+ super(spouse1, spouse2, other);
+ }
+
+ private DerivedConstructorDependenciesBean(TestBean spouse1, Object spouse2, IndexedTestBean other) {
+ super(spouse1, null, other);
+ }
+
+ protected DerivedConstructorDependenciesBean(TestBean spouse1, TestBean spouse2, IndexedTestBean other, int age, int otherAge) {
+ super(spouse1, spouse2, other);
+ }
+
+ public DerivedConstructorDependenciesBean(TestBean spouse1, TestBean spouse2, IndexedTestBean other, int age, String name) {
+ super(spouse1, spouse2, other);
+ setAge(age);
+ setName(name);
+ }
+
+ private void init() {
+ this.initialized = true;
+ }
+
+ private void destroy() {
+ this.destroyed = true;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DummyBo.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DummyBo.java
new file mode 100644
index 00000000000..6bb51516e4d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DummyBo.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+/**
+ *
+ * @author Rod Johnson
+ */
+public interface DummyBo {
+
+ void something();
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DummyBoImpl.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DummyBoImpl.java
new file mode 100644
index 00000000000..a03cb3b9e6c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DummyBoImpl.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+/**
+ *
+ * @author Rod Johnson
+ */
+public class DummyBoImpl implements DummyBo {
+
+ DummyDao dao;
+
+ public DummyBoImpl(DummyDao dao) {
+ this.dao = dao;
+ }
+
+ public void something() {
+
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DummyDao.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DummyDao.java
new file mode 100644
index 00000000000..d0b3176345f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DummyDao.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import javax.sql.DataSource;
+
+/**
+ *
+ * @author Rod Johnson
+ */
+public class DummyDao {
+
+ DataSource ds;
+
+ public DummyDao(DataSource ds) {
+ this.ds = ds;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DummyReferencer.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DummyReferencer.java
new file mode 100644
index 00000000000..94ff6de94ae
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/DummyReferencer.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.DummyFactory;
+
+/**
+ * @author Juergen Hoeller
+ * @since 21.07.2003
+ */
+public class DummyReferencer {
+
+ private TestBean testBean1;
+
+ private TestBean testBean2;
+
+ private DummyFactory dummyFactory;
+
+
+ public DummyReferencer() {
+ }
+
+ public DummyReferencer(DummyFactory dummyFactory) {
+ this.dummyFactory = dummyFactory;
+ }
+
+ public void setDummyFactory(DummyFactory dummyFactory) {
+ this.dummyFactory = dummyFactory;
+ }
+
+ public DummyFactory getDummyFactory() {
+ return dummyFactory;
+ }
+
+ public void setTestBean1(TestBean testBean1) {
+ this.testBean1 = testBean1;
+ }
+
+ public TestBean getTestBean1() {
+ return testBean1;
+ }
+
+ public void setTestBean2(TestBean testBean2) {
+ this.testBean2 = testBean2;
+ }
+
+ public TestBean getTestBean2() {
+ return testBean2;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/EventPublicationTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/EventPublicationTests.java
new file mode 100644
index 00000000000..b2c34a77578
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/EventPublicationTests.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import java.util.List;
+
+import junit.framework.TestCase;
+import org.w3c.dom.Element;
+
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.TypedStringValue;
+import org.springframework.beans.factory.parsing.AliasDefinition;
+import org.springframework.beans.factory.parsing.BeanComponentDefinition;
+import org.springframework.beans.factory.parsing.CollectingReaderEventListener;
+import org.springframework.beans.factory.parsing.ComponentDefinition;
+import org.springframework.beans.factory.parsing.ImportDefinition;
+import org.springframework.beans.factory.parsing.PassThroughSourceExtractor;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class EventPublicationTests extends TestCase {
+
+ private final DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
+
+ private final CollectingReaderEventListener eventListener = new CollectingReaderEventListener();
+
+
+ protected void setUp() throws Exception {
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this.beanFactory);
+ reader.setEventListener(this.eventListener);
+ reader.setSourceExtractor(new PassThroughSourceExtractor());
+ reader.loadBeanDefinitions(new ClassPathResource("beanEvents.xml", getClass()));
+ }
+
+ public void testDefaultsEventReceived() throws Exception {
+ List defaultsList = this.eventListener.getDefaults();
+ assertTrue(!defaultsList.isEmpty());
+ assertTrue(defaultsList.get(0) instanceof DocumentDefaultsDefinition);
+ DocumentDefaultsDefinition defaults = (DocumentDefaultsDefinition) defaultsList.get(0);
+ assertEquals("true", defaults.getLazyInit());
+ assertEquals("constructor", defaults.getAutowire());
+ assertEquals("objects", defaults.getDependencyCheck());
+ assertEquals("myInit", defaults.getInitMethod());
+ assertEquals("myDestroy", defaults.getDestroyMethod());
+ assertEquals("true", defaults.getMerge());
+ assertTrue(defaults.getSource() instanceof Element);
+ }
+
+ public void testBeanEventReceived() throws Exception {
+ ComponentDefinition componentDefinition1 = this.eventListener.getComponentDefinition("testBean");
+ assertTrue(componentDefinition1 instanceof BeanComponentDefinition);
+ assertEquals(1, componentDefinition1.getBeanDefinitions().length);
+ BeanDefinition beanDefinition1 = componentDefinition1.getBeanDefinitions()[0];
+ assertEquals(new TypedStringValue("Rob Harrop"),
+ beanDefinition1.getConstructorArgumentValues().getGenericArgumentValue(String.class).getValue());
+ assertEquals(1, componentDefinition1.getBeanReferences().length);
+ assertEquals("testBean2", componentDefinition1.getBeanReferences()[0].getBeanName());
+ assertEquals(1, componentDefinition1.getInnerBeanDefinitions().length);
+ BeanDefinition innerBd1 = componentDefinition1.getInnerBeanDefinitions()[0];
+ assertEquals(new TypedStringValue("ACME"),
+ innerBd1.getConstructorArgumentValues().getGenericArgumentValue(String.class).getValue());
+ assertTrue(componentDefinition1.getSource() instanceof Element);
+
+ ComponentDefinition componentDefinition2 = this.eventListener.getComponentDefinition("testBean2");
+ assertTrue(componentDefinition2 instanceof BeanComponentDefinition);
+ assertEquals(1, componentDefinition1.getBeanDefinitions().length);
+ BeanDefinition beanDefinition2 = componentDefinition2.getBeanDefinitions()[0];
+ assertEquals(new TypedStringValue("Juergen Hoeller"),
+ beanDefinition2.getPropertyValues().getPropertyValue("name").getValue());
+ assertEquals(0, componentDefinition2.getBeanReferences().length);
+ assertEquals(1, componentDefinition2.getInnerBeanDefinitions().length);
+ BeanDefinition innerBd2 = componentDefinition2.getInnerBeanDefinitions()[0];
+ assertEquals(new TypedStringValue("Eva Schallmeiner"),
+ innerBd2.getPropertyValues().getPropertyValue("name").getValue());
+ assertTrue(componentDefinition2.getSource() instanceof Element);
+ }
+
+ public void testAliasEventReceived() throws Exception {
+ List aliases = this.eventListener.getAliases("testBean");
+ assertEquals(2, aliases.size());
+ AliasDefinition aliasDefinition1 = (AliasDefinition) aliases.get(0);
+ assertEquals("testBeanAlias1", aliasDefinition1.getAlias());
+ assertTrue(aliasDefinition1.getSource() instanceof Element);
+ AliasDefinition aliasDefinition2 = (AliasDefinition) aliases.get(1);
+ assertEquals("testBeanAlias2", aliasDefinition2.getAlias());
+ assertTrue(aliasDefinition2.getSource() instanceof Element);
+ }
+
+ public void testImportEventReceived() throws Exception {
+ List imports = this.eventListener.getImports();
+ assertEquals(1, imports.size());
+ ImportDefinition importDefinition = (ImportDefinition) imports.get(0);
+ assertEquals("beanEventsImported.xml", importDefinition.getImportedResource());
+ assertTrue(importDefinition.getSource() instanceof Element);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/FactoryMethodTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/FactoryMethodTests.java
new file mode 100644
index 00000000000..b9715163f89
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/FactoryMethodTests.java
@@ -0,0 +1,325 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import javax.mail.Session;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.BeanDefinitionStoreException;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class FactoryMethodTests extends TestCase {
+
+ public void testFactoryMethodsSingletonOnTargetClass() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass()));
+
+ TestBean tb = (TestBean) xbf.getBean("defaultTestBean");
+ assertEquals("defaultInstance", tb.getName());
+ assertEquals(1, tb.getAge());
+
+ FactoryMethods fm = (FactoryMethods) xbf.getBean("default");
+ assertEquals(0, fm.getNum());
+ assertEquals("default", fm.getName());
+ assertEquals("defaultInstance", fm.getTestBean().getName());
+ assertEquals("setterString", fm.getStringValue());
+
+ fm = (FactoryMethods) xbf.getBean("testBeanOnly");
+ assertEquals(0, fm.getNum());
+ assertEquals("default", fm.getName());
+ // This comes from the test bean
+ assertEquals("Juergen", fm.getTestBean().getName());
+
+ fm = (FactoryMethods) xbf.getBean("full");
+ assertEquals(27, fm.getNum());
+ assertEquals("gotcha", fm.getName());
+ assertEquals("Juergen", fm.getTestBean().getName());
+
+ FactoryMethods fm2 = (FactoryMethods) xbf.getBean("full");
+ assertSame(fm, fm2);
+
+ xbf.destroySingletons();
+ assertTrue(tb.wasDestroyed());
+ }
+
+ public void testFactoryMethodsWithNullInstance() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass()));
+
+ FactoryMethods fm = (FactoryMethods) xbf.getBean("null");
+ assertNull(fm);
+
+ try {
+ xbf.getBean("nullWithProperty");
+ fail("Should have thrown BeanCreationException");
+ }
+ catch (BeanCreationException ex) {
+ // expected
+ }
+ }
+
+ public void testFactoryMethodsWithNullValue() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass()));
+
+ FactoryMethods fm = (FactoryMethods) xbf.getBean("fullWithNull");
+ assertEquals(27, fm.getNum());
+ assertEquals(null, fm.getName());
+ assertEquals("Juergen", fm.getTestBean().getName());
+
+ fm = (FactoryMethods) xbf.getBean("fullWithGenericNull");
+ assertEquals(27, fm.getNum());
+ assertEquals(null, fm.getName());
+ assertEquals("Juergen", fm.getTestBean().getName());
+ }
+
+ public void testFactoryMethodsWithAutowire() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass()));
+
+ FactoryMethods fm = (FactoryMethods) xbf.getBean("fullWithAutowire");
+ assertEquals(27, fm.getNum());
+ assertEquals("gotchaAutowired", fm.getName());
+ assertEquals("Juergen", fm.getTestBean().getName());
+ }
+
+ public void testProtectedFactoryMethod() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass()));
+
+ TestBean tb = (TestBean) xbf.getBean("defaultTestBean.protected");
+ assertEquals(1, tb.getAge());
+ }
+
+ public void testPrivateFactoryMethod() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass()));
+
+ TestBean tb = (TestBean) xbf.getBean("defaultTestBean.private");
+ assertEquals(1, tb.getAge());
+ }
+
+ public void testFactoryMethodsPrototypeOnTargetClass() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass()));
+ FactoryMethods fm = (FactoryMethods) xbf.getBean("defaultPrototype");
+ FactoryMethods fm2 = (FactoryMethods) xbf.getBean("defaultPrototype");
+ assertEquals(0, fm.getNum());
+ assertEquals("default", fm.getName());
+ assertEquals("defaultInstance", fm.getTestBean().getName());
+ assertEquals("setterString", fm.getStringValue());
+ assertEquals(fm.getNum(), fm2.getNum());
+ assertEquals(fm.getStringValue(), fm2.getStringValue());
+ // The TestBean is created separately for each bean
+ assertNotSame(fm.getTestBean(), fm2.getTestBean());
+ assertNotSame(fm, fm2);
+
+ fm = (FactoryMethods) xbf.getBean("testBeanOnlyPrototype");
+ fm2 = (FactoryMethods) xbf.getBean("testBeanOnlyPrototype");
+ assertEquals(0, fm.getNum());
+ assertEquals("default", fm.getName());
+ // This comes from the test bean
+ assertEquals("Juergen", fm.getTestBean().getName());
+ assertEquals(fm.getNum(), fm2.getNum());
+ assertEquals(fm.getStringValue(), fm2.getStringValue());
+ // The TestBean reference is resolved to a prototype in the factory
+ assertSame(fm.getTestBean(), fm2.getTestBean());
+ assertNotSame(fm, fm2);
+
+ fm = (FactoryMethods) xbf.getBean("fullPrototype");
+ fm2 = (FactoryMethods) xbf.getBean("fullPrototype");
+ assertEquals(27, fm.getNum());
+ assertEquals("gotcha", fm.getName());
+ assertEquals("Juergen", fm.getTestBean().getName());
+ assertEquals(fm.getNum(), fm2.getNum());
+ assertEquals(fm.getStringValue(), fm2.getStringValue());
+ // The TestBean reference is resolved to a prototype in the factory
+ assertSame(fm.getTestBean(), fm2.getTestBean());
+ assertNotSame(fm, fm2);
+ }
+
+ /**
+ * Tests where the static factory method is on a different class.
+ */
+ public void testFactoryMethodsOnExternalClass() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass()));
+
+ assertEquals(TestBean.class, xbf.getType("externalFactoryMethodWithoutArgs"));
+ assertEquals(TestBean.class, xbf.getType("externalFactoryMethodWithArgs"));
+ String[] names = xbf.getBeanNamesForType(TestBean.class);
+ assertTrue(Arrays.asList(names).contains("externalFactoryMethodWithoutArgs"));
+ assertTrue(Arrays.asList(names).contains("externalFactoryMethodWithArgs"));
+
+ TestBean tb = (TestBean) xbf.getBean("externalFactoryMethodWithoutArgs");
+ assertEquals(2, tb.getAge());
+ assertEquals("Tristan", tb.getName());
+ tb = (TestBean) xbf.getBean("externalFactoryMethodWithArgs");
+ assertEquals(33, tb.getAge());
+ assertEquals("Rod", tb.getName());
+
+ assertEquals(TestBean.class, xbf.getType("externalFactoryMethodWithoutArgs"));
+ assertEquals(TestBean.class, xbf.getType("externalFactoryMethodWithArgs"));
+ names = xbf.getBeanNamesForType(TestBean.class);
+ assertTrue(Arrays.asList(names).contains("externalFactoryMethodWithoutArgs"));
+ assertTrue(Arrays.asList(names).contains("externalFactoryMethodWithArgs"));
+ }
+
+ public void testInstanceFactoryMethodWithoutArgs() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass()));
+
+ InstanceFactory.count = 0;
+ xbf.preInstantiateSingletons();
+ assertEquals(1, InstanceFactory.count);
+ FactoryMethods fm = (FactoryMethods) xbf.getBean("instanceFactoryMethodWithoutArgs");
+ assertEquals("instanceFactory", fm.getTestBean().getName());
+ assertEquals(1, InstanceFactory.count);
+ FactoryMethods fm2 = (FactoryMethods) xbf.getBean("instanceFactoryMethodWithoutArgs");
+ assertEquals("instanceFactory", fm2.getTestBean().getName());
+ assertSame(fm2, fm);
+ assertEquals(1, InstanceFactory.count);
+ }
+
+ public void testFactoryMethodNoMatchingStaticMethod() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass()));
+ try {
+ xbf.getBean("noMatchPrototype");
+ fail("No static method matched");
+ }
+ catch (BeanCreationException ex) {
+ // Ok
+ }
+ }
+
+ public void testCanSpecifyFactoryMethodArgumentsOnFactoryMethodPrototype() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass()));
+ TestBean tbArg = new TestBean();
+ tbArg.setName("arg1");
+ TestBean tbArg2 = new TestBean();
+ tbArg2.setName("arg2");
+
+ FactoryMethods fm1 = (FactoryMethods) xbf.getBean("testBeanOnlyPrototype", new Object[] {tbArg});
+ assertEquals(0, fm1.getNum());
+ assertEquals("default", fm1.getName());
+ // This comes from the test bean
+ assertEquals("arg1", fm1.getTestBean().getName());
+
+ FactoryMethods fm2 = (FactoryMethods) xbf.getBean("testBeanOnlyPrototype", new Object[] {tbArg2});
+ assertEquals("arg2", fm2.getTestBean().getName());
+ assertEquals(fm1.getNum(), fm2.getNum());
+ assertEquals(fm2.getStringValue(), "testBeanOnlyPrototypeDISetterString");
+ assertEquals(fm2.getStringValue(), fm2.getStringValue());
+ // The TestBean reference is resolved to a prototype in the factory
+ assertSame(fm2.getTestBean(), fm2.getTestBean());
+ assertNotSame(fm1, fm2);
+
+ FactoryMethods fm3 = (FactoryMethods) xbf.getBean("testBeanOnlyPrototype", new Object[] {tbArg2, new Integer(1), "myName"});
+ assertEquals(1, fm3.getNum());
+ assertEquals("myName", fm3.getName());
+ assertEquals("arg2", fm3.getTestBean().getName());
+
+ FactoryMethods fm4 = (FactoryMethods) xbf.getBean("testBeanOnlyPrototype", new Object[] {tbArg});
+ assertEquals(0, fm4.getNum());
+ assertEquals("default", fm4.getName());
+ assertEquals("arg1", fm4.getTestBean().getName());
+ }
+
+ public void testCannotSpecifyFactoryMethodArgumentsOnSingleton() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass()));
+ try {
+ xbf.getBean("testBeanOnly", new Object[] {new TestBean()});
+ fail("Shouldn't allow args to be passed to a singleton");
+ }
+ catch (BeanDefinitionStoreException ex) {
+ // OK
+ }
+ }
+
+ public void testCannotSpecifyFactoryMethodArgumentsOnSingletonAfterCreation() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass()));
+ xbf.getBean("testBeanOnly");
+ try {
+ xbf.getBean("testBeanOnly", new Object[] {new TestBean()});
+ fail("Shouldn't allow args to be passed to a singleton");
+ }
+ catch (BeanDefinitionStoreException ex) {
+ // OK
+ }
+ }
+
+ public void testFactoryMethodWithDifferentReturnType() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass()));
+
+ // Check that listInstance is not considered a bean of type FactoryMethods.
+ assertTrue(List.class.isAssignableFrom(xbf.getType("listInstance")));
+ String[] names = xbf.getBeanNamesForType(FactoryMethods.class);
+ assertTrue(!Arrays.asList(names).contains("listInstance"));
+ names = xbf.getBeanNamesForType(List.class);
+ assertTrue(Arrays.asList(names).contains("listInstance"));
+
+ xbf.preInstantiateSingletons();
+ assertTrue(List.class.isAssignableFrom(xbf.getType("listInstance")));
+ names = xbf.getBeanNamesForType(FactoryMethods.class);
+ assertTrue(!Arrays.asList(names).contains("listInstance"));
+ names = xbf.getBeanNamesForType(List.class);
+ assertTrue(Arrays.asList(names).contains("listInstance"));
+ List list = (List) xbf.getBean("listInstance");
+ assertEquals(Collections.EMPTY_LIST, list);
+ }
+
+ public void testFactoryMethodForJavaMailSession() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass()));
+
+ Session session = (Session) xbf.getBean("javaMailSession");
+ assertEquals("someuser", session.getProperty("mail.smtp.user"));
+ assertEquals("somepw", session.getProperty("mail.smtp.password"));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/FactoryMethods.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/FactoryMethods.java
new file mode 100644
index 00000000000..c164d8fae73
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/FactoryMethods.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.springframework.beans.TestBean;
+
+/**
+ * Test class for Spring's ability to create objects using static
+ * factory methods, rather than constructors.
+ *
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public class FactoryMethods {
+
+ public static FactoryMethods nullInstance() {
+ return null;
+ }
+
+ public static FactoryMethods defaultInstance() {
+ TestBean tb = new TestBean();
+ tb.setName("defaultInstance");
+ return new FactoryMethods(tb, "default", 0);
+ }
+
+ /**
+ * Note that overloaded methods are supported.
+ */
+ public static FactoryMethods newInstance(TestBean tb) {
+ return new FactoryMethods(tb, "default", 0);
+ }
+
+ protected static FactoryMethods newInstance(TestBean tb, int num, String name) {
+ if (name == null) {
+ throw new IllegalStateException("Should never be called with null value");
+ }
+ return new FactoryMethods(tb, name, num);
+ }
+
+ static FactoryMethods newInstance(TestBean tb, int num, Integer something) {
+ if (something != null) {
+ throw new IllegalStateException("Should never be called with non-null value");
+ }
+ return new FactoryMethods(tb, null, num);
+ }
+
+ private static List listInstance() {
+ return Collections.EMPTY_LIST;
+ }
+
+
+ private int num = 0;
+ private String name = "default";
+ private TestBean tb;
+ private String stringValue;
+
+
+ /**
+ * Constructor is private: not for use outside this class,
+ * even by IoC container.
+ */
+ private FactoryMethods(TestBean tb, String name, int num) {
+ this.tb = tb;
+ this.name = name;
+ this.num = num;
+ }
+
+ public void setStringValue(String stringValue) {
+ this.stringValue = stringValue;
+ }
+
+ public String getStringValue() {
+ return this.stringValue;
+ }
+
+ public TestBean getTestBean() {
+ return this.tb;
+ }
+
+ protected TestBean protectedGetTestBean() {
+ return this.tb;
+ }
+
+ private TestBean privateGetTestBean() {
+ return this.tb;
+ }
+
+ public int getNum() {
+ return num;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Set via Setter Injection once instance is created.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/FixedMethodReplacer.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/FixedMethodReplacer.java
new file mode 100644
index 00000000000..2ac34def136
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/FixedMethodReplacer.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import java.lang.reflect.Method;
+
+import org.springframework.beans.factory.support.MethodReplacer;
+
+/**
+ * Fixed method replacer for String return types
+ * @author Rod Johnson
+ */
+public class FixedMethodReplacer implements MethodReplacer {
+
+ public static final String VALUE = "fixedMethodReplacer";
+
+ public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
+ return VALUE;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/GeneratedNameBean.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/GeneratedNameBean.java
new file mode 100644
index 00000000000..52eb2b2938c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/GeneratedNameBean.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import org.springframework.beans.factory.BeanNameAware;
+
+/**
+ * @author Rob Harrop
+ */
+public class GeneratedNameBean implements BeanNameAware {
+
+ private String beanName;
+
+ private GeneratedNameBean child;
+
+ public void setBeanName(String beanName) {
+ this.beanName = beanName;
+ }
+
+ public String getBeanName() {
+ return beanName;
+ }
+
+ public void setChild(GeneratedNameBean child) {
+ this.child = child;
+ }
+
+ public GeneratedNameBean getChild() {
+ return child;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/InstanceFactory.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/InstanceFactory.java
new file mode 100644
index 00000000000..8a43857fb76
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/InstanceFactory.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import org.springframework.beans.TestBean;
+
+/**
+ * Test class for Spring's ability to create objects using
+ * static factory methods, rather than constructors.
+ *
+ * @author Rod Johnson
+ */
+public class InstanceFactory {
+
+ protected static int count = 0;
+
+ private String factoryBeanProperty;
+
+ public InstanceFactory() {
+ count++;
+ }
+
+ public void setFactoryBeanProperty(String s) {
+ this.factoryBeanProperty = s;
+ }
+
+ public String getFactoryBeanProperty() {
+ return this.factoryBeanProperty;
+ }
+
+ public FactoryMethods defaultInstance() {
+ TestBean tb = new TestBean();
+ tb.setName(this.factoryBeanProperty);
+ return FactoryMethods.newInstance(tb);
+ }
+
+ /**
+ * Note that overloaded methods are supported.
+ */
+ public FactoryMethods newInstance(TestBean tb) {
+ return FactoryMethods.newInstance(tb);
+ }
+
+ public FactoryMethods newInstance(TestBean tb, int num, String name) {
+ return FactoryMethods.newInstance(tb, num, name);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/LookupMethodWrappedByCglibProxyTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/LookupMethodWrappedByCglibProxyTests.java
new file mode 100644
index 00000000000..0a3c782d92e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/LookupMethodWrappedByCglibProxyTests.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.interceptor.DebugInterceptor;
+import org.springframework.beans.ITestBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * Tests lookup methods wrapped by a CGLIB proxy (see SPR-391).
+ *
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public class LookupMethodWrappedByCglibProxyTests extends TestCase {
+
+ private ApplicationContext applicationContext;
+
+ protected void setUp() {
+ this.applicationContext = new ClassPathXmlApplicationContext("overloadOverrides.xml", getClass());
+ resetInterceptor();
+ }
+
+ public void testAutoProxiedLookup() {
+ OverloadLookup olup = (OverloadLookup) applicationContext.getBean("autoProxiedOverload");
+ ITestBean jenny = olup.newTestBean();
+ assertEquals("Jenny", jenny.getName());
+ assertEquals("foo", olup.testMethod());
+ assertInterceptorCount(2);
+ }
+
+ public void testRegularlyProxiedLookup() {
+ OverloadLookup olup = (OverloadLookup) applicationContext.getBean("regularlyProxiedOverload");
+ ITestBean jenny = olup.newTestBean();
+ assertEquals("Jenny", jenny.getName());
+ assertEquals("foo", olup.testMethod());
+ assertInterceptorCount(2);
+ }
+
+ private void assertInterceptorCount(int count) {
+ DebugInterceptor interceptor = getInterceptor();
+ assertEquals("Interceptor count is incorrect", count, interceptor.getCount());
+ }
+
+ private void resetInterceptor() {
+ DebugInterceptor interceptor = getInterceptor();
+ interceptor.resetCount();
+ }
+
+ private DebugInterceptor getInterceptor() {
+ return (DebugInterceptor) applicationContext.getBean("interceptor");
+ }
+
+
+ public static abstract class OverloadLookup {
+
+ public abstract ITestBean newTestBean();
+
+ public String testMethod() {
+ return "foo";
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/MetadataAttachmentTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/MetadataAttachmentTests.java
new file mode 100644
index 00000000000..b943361f1a2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/MetadataAttachmentTests.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.PropertyValue;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Rob Harrop
+ */
+public class MetadataAttachmentTests extends TestCase {
+
+ private XmlBeanFactory beanFactory;
+
+ protected void setUp() throws Exception {
+ this.beanFactory = new XmlBeanFactory(new ClassPathResource("withMeta.xml", getClass()));
+ }
+
+ public void testMetadataAttachment() throws Exception {
+ BeanDefinition beanDefinition1 = this.beanFactory.getMergedBeanDefinition("testBean1");
+ assertEquals("bar", beanDefinition1.getAttribute("foo"));
+ }
+
+ public void testMetadataIsInherited() throws Exception {
+ BeanDefinition beanDefinition = this.beanFactory.getMergedBeanDefinition("testBean2");
+ assertEquals("Metadata not inherited", "bar", beanDefinition.getAttribute("foo"));
+ assertEquals("Child metdata not attached", "123", beanDefinition.getAttribute("abc"));
+ }
+
+ public void testPropertyMetadata() throws Exception {
+ BeanDefinition beanDefinition = this.beanFactory.getMergedBeanDefinition("testBean3");
+ PropertyValue pv = beanDefinition.getPropertyValues().getPropertyValue("name");
+ assertEquals("Harrop", pv.getAttribute("surname"));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/MethodReplaceCandidate.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/MethodReplaceCandidate.java
new file mode 100644
index 00000000000..bf104819349
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/MethodReplaceCandidate.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+/**
+ *
+ * @author Rod Johnson
+ */
+public class MethodReplaceCandidate {
+
+ public String replaceMe(String echo) {
+ return echo;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/MixedCollectionBean.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/MixedCollectionBean.java
new file mode 100644
index 00000000000..8ed5f2517ec
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/MixedCollectionBean.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import java.util.Collection;
+
+/**
+ * Bean that exposes a simple property that can be set
+ * to a mix of references and individual values.
+ *
+ * @author Rod Johnson
+ * @since 27.05.2003
+ */
+public class MixedCollectionBean {
+
+ private Collection jumble;
+
+
+ public void setJumble(Collection jumble) {
+ this.jumble = jumble;
+ }
+
+ public Collection getJumble() {
+ return jumble;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/OverrideInterface.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/OverrideInterface.java
new file mode 100644
index 00000000000..4ad5bedd82a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/OverrideInterface.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import org.springframework.beans.TestBean;
+
+/**
+ * @author Juergen Hoeller
+ */
+public interface OverrideInterface {
+
+ TestBean getPrototypeDependency();
+
+ TestBean getPrototypeDependency(Object someParam);
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/OverrideOneMethod.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/OverrideOneMethod.java
new file mode 100644
index 00000000000..6053f68e333
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/OverrideOneMethod.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import org.springframework.beans.TestBean;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public abstract class OverrideOneMethod extends MethodReplaceCandidate implements OverrideInterface {
+
+ protected abstract TestBean protectedOverrideSingleton();
+
+ public TestBean getPrototypeDependency(Object someParam) {
+ return new TestBean();
+ }
+
+ public TestBean invokesOverridenMethodOnSelf() {
+ return getPrototypeDependency();
+ }
+
+ public String echo(String echo) {
+ return echo;
+ }
+
+ /**
+ * Overloaded form of replaceMe.
+ */
+ public String replaceMe() {
+ return "replaceMe";
+ }
+
+ /**
+ * Another overloaded form of replaceMe, not getting replaced.
+ * Must not cause errors when the other replaceMe methods get replaced.
+ */
+ public String replaceMe(int someParam) {
+ return "replaceMe:" + someParam;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/OverrideOneMethodSubclass.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/OverrideOneMethodSubclass.java
new file mode 100644
index 00000000000..95da446ed48
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/OverrideOneMethodSubclass.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+/**
+ * Subclass of OverrideOneMethod, to check that overriding is
+ * supported for inherited methods.
+ *
+ * @author Rod Johnson
+ */
+public abstract class OverrideOneMethodSubclass extends OverrideOneMethod {
+
+ protected void doSomething(String arg) {
+ // This implementation does nothing!
+ // It's not overloaded
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/ProtectedLifecycleBean.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/ProtectedLifecycleBean.java
new file mode 100644
index 00000000000..7fef9c31533
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/ProtectedLifecycleBean.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanFactoryAware;
+import org.springframework.beans.factory.BeanNameAware;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+
+/**
+ * Simple test of BeanFactory initialization and lifecycle callbacks.
+ *
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+class ProtectedLifecycleBean implements BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean {
+
+ protected boolean initMethodDeclared = false;
+
+ protected String beanName;
+
+ protected BeanFactory owningFactory;
+
+ protected boolean postProcessedBeforeInit;
+
+ protected boolean inited;
+
+ protected boolean initedViaDeclaredInitMethod;
+
+ protected boolean postProcessedAfterInit;
+
+ protected boolean destroyed;
+
+
+ public void setInitMethodDeclared(boolean initMethodDeclared) {
+ this.initMethodDeclared = initMethodDeclared;
+ }
+
+ public boolean isInitMethodDeclared() {
+ return initMethodDeclared;
+ }
+
+ public void setBeanName(String name) {
+ this.beanName = name;
+ }
+
+ public String getBeanName() {
+ return beanName;
+ }
+
+ public void setBeanFactory(BeanFactory beanFactory) {
+ this.owningFactory = beanFactory;
+ }
+
+ public void postProcessBeforeInit() {
+ if (this.inited || this.initedViaDeclaredInitMethod) {
+ throw new RuntimeException("Factory called postProcessBeforeInit after afterPropertiesSet");
+ }
+ if (this.postProcessedBeforeInit) {
+ throw new RuntimeException("Factory called postProcessBeforeInit twice");
+ }
+ this.postProcessedBeforeInit = true;
+ }
+
+ public void afterPropertiesSet() {
+ if (this.owningFactory == null) {
+ throw new RuntimeException("Factory didn't call setBeanFactory before afterPropertiesSet on lifecycle bean");
+ }
+ if (!this.postProcessedBeforeInit) {
+ throw new RuntimeException("Factory didn't call postProcessBeforeInit before afterPropertiesSet on lifecycle bean");
+ }
+ if (this.initedViaDeclaredInitMethod) {
+ throw new RuntimeException("Factory initialized via declared init method before initializing via afterPropertiesSet");
+ }
+ if (this.inited) {
+ throw new RuntimeException("Factory called afterPropertiesSet twice");
+ }
+ this.inited = true;
+ }
+
+ public void declaredInitMethod() {
+ if (!this.inited) {
+ throw new RuntimeException("Factory didn't call afterPropertiesSet before declared init method");
+ }
+
+ if (this.initedViaDeclaredInitMethod) {
+ throw new RuntimeException("Factory called declared init method twice");
+ }
+ this.initedViaDeclaredInitMethod = true;
+ }
+
+ public void postProcessAfterInit() {
+ if (!this.inited) {
+ throw new RuntimeException("Factory called postProcessAfterInit before afterPropertiesSet");
+ }
+ if (this.initMethodDeclared && !this.initedViaDeclaredInitMethod) {
+ throw new RuntimeException("Factory called postProcessAfterInit before calling declared init method");
+ }
+ if (this.postProcessedAfterInit) {
+ throw new RuntimeException("Factory called postProcessAfterInit twice");
+ }
+ this.postProcessedAfterInit = true;
+ }
+
+ /**
+ * Dummy business method that will fail unless the factory
+ * managed the bean's lifecycle correctly
+ */
+ public void businessMethod() {
+ if (!this.inited || (this.initMethodDeclared && !this.initedViaDeclaredInitMethod) ||
+ !this.postProcessedAfterInit) {
+ throw new RuntimeException("Factory didn't initialize lifecycle object correctly");
+ }
+ }
+
+ public void destroy() {
+ if (this.destroyed) {
+ throw new IllegalStateException("Already destroyed");
+ }
+ this.destroyed = true;
+ }
+
+ public boolean isDestroyed() {
+ return destroyed;
+ }
+
+
+ public static class PostProcessor implements BeanPostProcessor {
+
+ public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
+ if (bean instanceof ProtectedLifecycleBean) {
+ ((ProtectedLifecycleBean) bean).postProcessBeforeInit();
+ }
+ return bean;
+ }
+
+ public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
+ if (bean instanceof ProtectedLifecycleBean) {
+ ((ProtectedLifecycleBean) bean).postProcessAfterInit();
+ }
+ return bean;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/ReverseMethodReplacer.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/ReverseMethodReplacer.java
new file mode 100644
index 00000000000..73e364fa267
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/ReverseMethodReplacer.java
@@ -0,0 +1,23 @@
+/*
+ * The Spring Framework is published under the terms
+ * of the Apache Software License.
+ */
+
+package org.springframework.beans.factory.xml;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+
+import org.springframework.beans.factory.support.MethodReplacer;
+
+/**
+ * @author Rod Johnson
+ */
+public class ReverseMethodReplacer implements MethodReplacer, Serializable {
+
+ public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
+ String s = (String) args[0];
+ return new StringBuffer(s).reverse().toString();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/SchemaValidationTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/SchemaValidationTests.java
new file mode 100644
index 00000000000..3679c5a0e3e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/SchemaValidationTests.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import junit.framework.TestCase;
+import org.xml.sax.SAXParseException;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Rob Harrop
+ */
+public class SchemaValidationTests extends TestCase {
+
+ public void testWithAutodetection() throws Exception {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
+ try {
+ reader.loadBeanDefinitions(new ClassPathResource("invalidPerSchema.xml", getClass()));
+ fail("Should not be able to parse a file with errors");
+ }
+ catch (BeansException ex) {
+ assertTrue(ex.getCause() instanceof SAXParseException);
+ }
+ }
+
+ public void testWithExplicitValidationMode() throws Exception {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
+ reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_XSD);
+ try {
+ reader.loadBeanDefinitions(new ClassPathResource("invalidPerSchema.xml", getClass()));
+ fail("Should not be able to parse a file with errors");
+ }
+ catch (BeansException ex) {
+ assertTrue(ex.getCause() instanceof SAXParseException);
+ }
+ }
+
+ public void testLoadDefinitions() throws Exception {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
+ reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_XSD);
+ reader.loadBeanDefinitions(new ClassPathResource("schemaValidated.xml", getClass()));
+
+ TestBean foo = (TestBean) bf.getBean("fooBean");
+ assertNotNull("Spouse is null", foo.getSpouse());
+ assertEquals("Incorrect number of friends", 2, foo.getFriends().size());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/SerializableMethodReplacerCandidate.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/SerializableMethodReplacerCandidate.java
new file mode 100644
index 00000000000..33150572012
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/SerializableMethodReplacerCandidate.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import java.io.Serializable;
+
+/**
+ * @author Rod Johnson
+ */
+public abstract class SerializableMethodReplacerCandidate extends MethodReplaceCandidate implements Serializable {
+
+ //public abstract Point getPoint();
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/ShortcutTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/ShortcutTests.java
new file mode 100644
index 00000000000..389e468b0ca
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/ShortcutTests.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.BeanDefinitionStoreException;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class ShortcutTests extends TestCase {
+
+ public void testSimpleBeanConfigured() throws Exception {
+ XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("shortcutTests.xml", getClass()));
+ ITestBean rob = (TestBean) beanFactory.getBean("rob");
+ ITestBean sally = (TestBean) beanFactory.getBean("sally");
+ assertEquals("Rob Harrop", rob.getName());
+ assertEquals(24, rob.getAge());
+ assertEquals(rob.getSpouse(), sally);
+ }
+
+ public void testInnerBeanConfigured() throws Exception {
+ XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("shortcutTests.xml", getClass()));
+ TestBean sally = (TestBean) beanFactory.getBean("sally2");
+ ITestBean rob = (TestBean) sally.getSpouse();
+ assertEquals("Rob Harrop", rob.getName());
+ assertEquals(24, rob.getAge());
+ assertEquals(rob.getSpouse(), sally);
+ }
+
+ public void testWithPropertyDefinedTwice() throws Exception {
+ try {
+ new XmlBeanFactory(new ClassPathResource("shortcutTestsWithErrors.xml", getClass()));
+ fail("Should not be able to load a file with property specified twice.");
+ }
+ catch (BeanDefinitionStoreException e) {
+ // success
+ }
+ }
+
+ public void testPropertyWithNameEndingInRef() throws Exception {
+ XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("shortcutTests.xml", getClass()));
+ ITestBean sally = (TestBean) beanFactory.getBean("derivedSally");
+ assertEquals("r", sally.getSpouse().getName());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/SingleSimpleTypeConstructorBean.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/SingleSimpleTypeConstructorBean.java
new file mode 100644
index 00000000000..50ca3486480
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/SingleSimpleTypeConstructorBean.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+/**
+ * @author Juergen Hoeller
+ * @since 23.10.2004
+ */
+public class SingleSimpleTypeConstructorBean {
+
+ private boolean singleBoolean;
+
+ private boolean secondBoolean;
+
+ private String testString;
+
+ public SingleSimpleTypeConstructorBean(boolean singleBoolean) {
+ this.singleBoolean = singleBoolean;
+ }
+
+ public SingleSimpleTypeConstructorBean(String testString, boolean secondBoolean) {
+ this.testString = testString;
+ this.secondBoolean = secondBoolean;
+ }
+
+ public boolean isSingleBoolean() {
+ return singleBoolean;
+ }
+
+ public boolean isSecondBoolean() {
+ return secondBoolean;
+ }
+
+ public String getTestString() {
+ return testString;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/TestBeanCreator.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/TestBeanCreator.java
new file mode 100644
index 00000000000..8658bc5a12a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/TestBeanCreator.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import org.springframework.beans.TestBean;
+
+/**
+ * Test class for Spring's ability to create
+ * objects using static factory methods, rather
+ * than constructors.
+ * @author Rod Johnson
+ */
+public class TestBeanCreator {
+
+ public static TestBean createTestBean(String name, int age) {
+ TestBean tb = new TestBean();
+ tb.setName(name);
+ tb.setAge(age);
+ return tb;
+ }
+
+ public static TestBean createTestBean() {
+ TestBean tb = new TestBean();
+ tb.setName("Tristan");
+ tb.setAge(2);
+ return tb;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/UtilNamespaceHandlerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/UtilNamespaceHandlerTests.java
new file mode 100644
index 00000000000..31398eb9d96
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/UtilNamespaceHandlerTests.java
@@ -0,0 +1,310 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import java.lang.reflect.Proxy;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeMap;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.parsing.CollectingReaderEventListener;
+import org.springframework.beans.factory.parsing.ComponentDefinition;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.beans.factory.config.PropertiesFactoryBean;
+import org.springframework.beans.factory.config.FieldRetrievingFactoryBean;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ * @author Mark Fisher
+ */
+public class UtilNamespaceHandlerTests extends TestCase {
+
+ private DefaultListableBeanFactory beanFactory;
+
+ private CollectingReaderEventListener listener = new CollectingReaderEventListener();
+
+ public void setUp() {
+ this.beanFactory = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this.beanFactory);
+ reader.setEventListener(this.listener);
+ reader.loadBeanDefinitions(new ClassPathResource("testUtilNamespace.xml", getClass()));
+ }
+
+ public void testConstant() throws Exception {
+ Integer min = (Integer) this.beanFactory.getBean("min");
+ assertEquals(Integer.MIN_VALUE, min.intValue());
+ }
+
+ public void testConstantWithDefaultName() throws Exception {
+ Integer max = (Integer) this.beanFactory.getBean("java.lang.Integer.MAX_VALUE");
+ assertEquals(Integer.MAX_VALUE, max.intValue());
+ }
+
+ public void testEvents() throws Exception {
+ ComponentDefinition propertiesComponent = this.listener.getComponentDefinition("myProperties");
+ assertNotNull("Event for 'myProperties' not sent", propertiesComponent);
+ AbstractBeanDefinition propertiesBean = (AbstractBeanDefinition) propertiesComponent.getBeanDefinitions()[0];
+ assertEquals("Incorrect BeanDefinition", PropertiesFactoryBean.class, propertiesBean.getBeanClass());
+
+ ComponentDefinition constantComponent = this.listener.getComponentDefinition("min");
+ assertNotNull("Event for 'min' not sent", propertiesComponent);
+ AbstractBeanDefinition constantBean = (AbstractBeanDefinition) constantComponent.getBeanDefinitions()[0];
+ assertEquals("Incorrect BeanDefinition", FieldRetrievingFactoryBean.class, constantBean.getBeanClass());
+ }
+
+ public void testNestedProperties() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("testBean");
+ Properties props = bean.getSomeProperties();
+ assertEquals("Incorrect property value", "bar", props.get("foo"));
+ }
+
+ public void testPropertyPath() throws Exception {
+ String name = (String) this.beanFactory.getBean("name");
+ assertEquals("Rob Harrop", name);
+ }
+
+ public void testNestedPropertyPath() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("testBean");
+ assertEquals("Rob Harrop", bean.getName());
+ }
+
+ public void testSimpleMap() throws Exception {
+ Map map = (Map) this.beanFactory.getBean("simpleMap");
+ assertEquals("bar", map.get("foo"));
+ Map map2 = (Map) this.beanFactory.getBean("simpleMap");
+ assertTrue(map == map2);
+ }
+
+ public void testScopedMap() throws Exception {
+ Map map = (Map) this.beanFactory.getBean("scopedMap");
+ assertEquals("bar", map.get("foo"));
+ Map map2 = (Map) this.beanFactory.getBean("scopedMap");
+ assertEquals("bar", map2.get("foo"));
+ assertTrue(map != map2);
+ }
+
+ public void testSimpleList() throws Exception {
+ List list = (List) this.beanFactory.getBean("simpleList");
+ assertEquals("Rob Harrop", list.get(0));
+ List list2 = (List) this.beanFactory.getBean("simpleList");
+ assertTrue(list == list2);
+ }
+
+ public void testScopedList() throws Exception {
+ List list = (List) this.beanFactory.getBean("scopedList");
+ assertEquals("Rob Harrop", list.get(0));
+ List list2 = (List) this.beanFactory.getBean("scopedList");
+ assertEquals("Rob Harrop", list2.get(0));
+ assertTrue(list != list2);
+ }
+
+ public void testSimpleSet() throws Exception {
+ Set set = (Set) this.beanFactory.getBean("simpleSet");
+ assertTrue(set.contains("Rob Harrop"));
+ Set set2 = (Set) this.beanFactory.getBean("simpleSet");
+ assertTrue(set == set2);
+ }
+
+ public void testScopedSet() throws Exception {
+ Set set = (Set) this.beanFactory.getBean("scopedSet");
+ assertTrue(set.contains("Rob Harrop"));
+ Set set2 = (Set) this.beanFactory.getBean("scopedSet");
+ assertTrue(set2.contains("Rob Harrop"));
+ assertTrue(set != set2);
+ }
+
+ public void testMapWithRef() throws Exception {
+ Map map = (Map) this.beanFactory.getBean("mapWithRef");
+ assertTrue(map instanceof TreeMap);
+ assertEquals(this.beanFactory.getBean("testBean"), map.get("bean"));
+ }
+
+ public void testNestedCollections() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("nestedCollectionsBean");
+
+ List list = bean.getSomeList();
+ assertEquals(1, list.size());
+ assertEquals("foo", list.get(0));
+
+ Set set = bean.getSomeSet();
+ assertEquals(1, set.size());
+ assertTrue(set.contains("bar"));
+
+ Map map = bean.getSomeMap();
+ assertEquals(1, map.size());
+ assertTrue(map.get("foo") instanceof Set);
+ Set innerSet = (Set) map.get("foo");
+ assertEquals(1, innerSet.size());
+ assertTrue(innerSet.contains("bar"));
+ }
+
+ public void testNestedInCollections() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("nestedCustomTagBean");
+ Integer min = new Integer(Integer.MIN_VALUE);
+
+ List list = bean.getSomeList();
+ assertEquals(1, list.size());
+ assertEquals(min, list.get(0));
+
+ Set set = bean.getSomeSet();
+ assertEquals(1, set.size());
+ assertTrue(set.contains(min));
+
+ Map map = bean.getSomeMap();
+ assertEquals(1, map.size());
+ assertEquals(min, map.get("min"));
+ }
+
+ public void testCircularCollections() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("circularCollectionsBean");
+
+ List list = bean.getSomeList();
+ assertEquals(1, list.size());
+ assertEquals(bean, list.get(0));
+
+ Set set = bean.getSomeSet();
+ assertEquals(1, set.size());
+ assertTrue(set.contains(bean));
+
+ Map map = bean.getSomeMap();
+ assertEquals(1, map.size());
+ assertEquals(bean, map.get("foo"));
+ }
+
+ public void testCircularCollectionBeansStartingWithList() throws Exception {
+ this.beanFactory.getBean("circularList");
+ TestBean bean = (TestBean) this.beanFactory.getBean("circularCollectionBeansBean");
+
+ List list = bean.getSomeList();
+ assertTrue(Proxy.isProxyClass(list.getClass()));
+ assertEquals(1, list.size());
+ assertEquals(bean, list.get(0));
+
+ Set set = bean.getSomeSet();
+ assertFalse(Proxy.isProxyClass(set.getClass()));
+ assertEquals(1, set.size());
+ assertTrue(set.contains(bean));
+
+ Map map = bean.getSomeMap();
+ assertFalse(Proxy.isProxyClass(map.getClass()));
+ assertEquals(1, map.size());
+ assertEquals(bean, map.get("foo"));
+ }
+
+ public void testCircularCollectionBeansStartingWithSet() throws Exception {
+ this.beanFactory.getBean("circularSet");
+ TestBean bean = (TestBean) this.beanFactory.getBean("circularCollectionBeansBean");
+
+ List list = bean.getSomeList();
+ assertFalse(Proxy.isProxyClass(list.getClass()));
+ assertEquals(1, list.size());
+ assertEquals(bean, list.get(0));
+
+ Set set = bean.getSomeSet();
+ assertTrue(Proxy.isProxyClass(set.getClass()));
+ assertEquals(1, set.size());
+ assertTrue(set.contains(bean));
+
+ Map map = bean.getSomeMap();
+ assertFalse(Proxy.isProxyClass(map.getClass()));
+ assertEquals(1, map.size());
+ assertEquals(bean, map.get("foo"));
+ }
+
+ public void testCircularCollectionBeansStartingWithMap() throws Exception {
+ this.beanFactory.getBean("circularMap");
+ TestBean bean = (TestBean) this.beanFactory.getBean("circularCollectionBeansBean");
+
+ List list = bean.getSomeList();
+ assertFalse(Proxy.isProxyClass(list.getClass()));
+ assertEquals(1, list.size());
+ assertEquals(bean, list.get(0));
+
+ Set set = bean.getSomeSet();
+ assertFalse(Proxy.isProxyClass(set.getClass()));
+ assertEquals(1, set.size());
+ assertTrue(set.contains(bean));
+
+ Map map = bean.getSomeMap();
+ assertTrue(Proxy.isProxyClass(map.getClass()));
+ assertEquals(1, map.size());
+ assertEquals(bean, map.get("foo"));
+ }
+
+ public void testNestedInConstructor() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("constructedTestBean");
+ assertEquals("Rob Harrop", bean.getName());
+ }
+
+ public void testLoadProperties() throws Exception {
+ Properties props = (Properties) this.beanFactory.getBean("myProperties");
+ assertEquals("Incorrect property value", "bar", props.get("foo"));
+ assertEquals("Incorrect property value", null, props.get("foo2"));
+ Properties props2 = (Properties) this.beanFactory.getBean("myProperties");
+ assertTrue(props == props2);
+ }
+
+ public void testScopedProperties() throws Exception {
+ Properties props = (Properties) this.beanFactory.getBean("myScopedProperties");
+ assertEquals("Incorrect property value", "bar", props.get("foo"));
+ assertEquals("Incorrect property value", null, props.get("foo2"));
+ Properties props2 = (Properties) this.beanFactory.getBean("myScopedProperties");
+ assertEquals("Incorrect property value", "bar", props.get("foo"));
+ assertEquals("Incorrect property value", null, props.get("foo2"));
+ assertTrue(props != props2);
+ }
+
+ public void testLocalProperties() throws Exception {
+ Properties props = (Properties) this.beanFactory.getBean("myLocalProperties");
+ assertEquals("Incorrect property value", null, props.get("foo"));
+ assertEquals("Incorrect property value", "bar2", props.get("foo2"));
+ }
+
+ public void testMergedProperties() throws Exception {
+ Properties props = (Properties) this.beanFactory.getBean("myMergedProperties");
+ assertEquals("Incorrect property value", "bar", props.get("foo"));
+ assertEquals("Incorrect property value", "bar2", props.get("foo2"));
+ }
+
+ public void testLocalOverrideDefault() {
+ Properties props = (Properties) this.beanFactory.getBean("defaultLocalOverrideProperties");
+ assertEquals("Incorrect property value", "bar", props.get("foo"));
+ assertEquals("Incorrect property value", "local2", props.get("foo2"));
+ }
+
+ public void testLocalOverrideFalse() {
+ Properties props = (Properties) this.beanFactory.getBean("falseLocalOverrideProperties");
+ assertEquals("Incorrect property value", "bar", props.get("foo"));
+ assertEquals("Incorrect property value", "local2", props.get("foo2"));
+ }
+
+ public void testLocalOverrideTrue() {
+ Properties props = (Properties) this.beanFactory.getBean("trueLocalOverrideProperties");
+ assertEquals("Incorrect property value", "local", props.get("foo"));
+ assertEquals("Incorrect property value", "local2", props.get("foo2"));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/XmlBeanCollectionTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/XmlBeanCollectionTests.java
new file mode 100644
index 00000000000..358b07eb9e3
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/XmlBeanCollectionTests.java
@@ -0,0 +1,413 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import junit.framework.TestCase;
+import org.hibernate.FlushMode;
+
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.BeanDefinitionStoreException;
+import org.springframework.beans.factory.HasMap;
+import org.springframework.beans.factory.config.ListFactoryBean;
+import org.springframework.beans.factory.config.MapFactoryBean;
+import org.springframework.beans.factory.config.SetFactoryBean;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * Tests for collections in XML bean definitions.
+ *
+ * @author Juergen Hoeller
+ * @since 19.12.2004
+ */
+public class XmlBeanCollectionTests extends TestCase {
+
+ public void testCollectionFactoryDefaults() throws Exception {
+ ListFactoryBean listFactory = new ListFactoryBean();
+ listFactory.setSourceList(new LinkedList());
+ listFactory.afterPropertiesSet();
+ assertTrue(listFactory.getObject() instanceof ArrayList);
+
+ SetFactoryBean setFactory = new SetFactoryBean();
+ setFactory.setSourceSet(new TreeSet());
+ setFactory.afterPropertiesSet();
+ assertTrue(setFactory.getObject() instanceof LinkedHashSet);
+
+ MapFactoryBean mapFactory = new MapFactoryBean();
+ mapFactory.setSourceMap(new TreeMap());
+ mapFactory.afterPropertiesSet();
+ assertTrue(mapFactory.getObject() instanceof LinkedHashMap);
+ }
+
+ public void testRefSubelement() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ //assertTrue("5 beans in reftypes, not " + xbf.getBeanDefinitionCount(), xbf.getBeanDefinitionCount() == 5);
+ TestBean jen = (TestBean) xbf.getBean("jenny");
+ TestBean dave = (TestBean) xbf.getBean("david");
+ assertTrue(jen.getSpouse() == dave);
+ }
+
+ public void testPropertyWithLiteralValueSubelement() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ TestBean verbose = (TestBean) xbf.getBean("verbose");
+ assertTrue(verbose.getName().equals("verbose"));
+ }
+
+ public void testPropertyWithIdRefLocalAttrSubelement() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ TestBean verbose = (TestBean) xbf.getBean("verbose2");
+ assertTrue(verbose.getName().equals("verbose"));
+ }
+
+ public void testPropertyWithIdRefBeanAttrSubelement() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ TestBean verbose = (TestBean) xbf.getBean("verbose3");
+ assertTrue(verbose.getName().equals("verbose"));
+ }
+
+ public void testRefSubelementsBuildCollection() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ TestBean jen = (TestBean) xbf.getBean("jenny");
+ TestBean dave = (TestBean) xbf.getBean("david");
+ TestBean rod = (TestBean) xbf.getBean("rod");
+
+ // Must be a list to support ordering
+ // Our bean doesn't modify the collection:
+ // of course it could be a different copy in a real object.
+ Object[] friends = rod.getFriends().toArray();
+ assertTrue(friends.length == 2);
+
+ assertTrue("First friend must be jen, not " + friends[0], friends[0] == jen);
+ assertTrue(friends[1] == dave);
+ // Should be ordered
+ }
+
+ public void testRefSubelementsBuildCollectionWithPrototypes() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+
+ TestBean jen = (TestBean) xbf.getBean("pJenny");
+ TestBean dave = (TestBean) xbf.getBean("pDavid");
+ TestBean rod = (TestBean) xbf.getBean("pRod");
+ Object[] friends = rod.getFriends().toArray();
+ assertTrue(friends.length == 2);
+ assertTrue("First friend must be jen, not " + friends[0],
+ friends[0].toString().equals(jen.toString()));
+ assertTrue("Jen not same instance", friends[0] != jen);
+ assertTrue(friends[1].toString().equals(dave.toString()));
+ assertTrue("Dave not same instance", friends[1] != dave);
+
+ TestBean rod2 = (TestBean) xbf.getBean("pRod");
+ Object[] friends2 = rod2.getFriends().toArray();
+ assertTrue(friends2.length == 2);
+ assertTrue("First friend must be jen, not " + friends2[0],
+ friends2[0].toString().equals(jen.toString()));
+ assertTrue("Jen not same instance", friends2[0] != friends[0]);
+ assertTrue(friends2[1].toString().equals(dave.toString()));
+ assertTrue("Dave not same instance", friends2[1] != friends[1]);
+ }
+
+ public void testRefSubelementsBuildCollectionFromSingleElement() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ TestBean loner = (TestBean) xbf.getBean("loner");
+ TestBean dave = (TestBean) xbf.getBean("david");
+ assertTrue(loner.getFriends().size() == 1);
+ assertTrue(loner.getFriends().contains(dave));
+ }
+
+ public void testBuildCollectionFromMixtureOfReferencesAndValues() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ MixedCollectionBean jumble = (MixedCollectionBean) xbf.getBean("jumble");
+ assertTrue("Expected 4 elements, not " + jumble.getJumble().size(),
+ jumble.getJumble().size() == 4);
+ List l = (List) jumble.getJumble();
+ assertTrue(l.get(0).equals(xbf.getBean("david")));
+ assertTrue(l.get(1).equals("literal"));
+ assertTrue(l.get(2).equals(xbf.getBean("jenny")));
+ assertTrue(l.get(3).equals("rod"));
+ }
+
+ public void testInvalidBeanNameReference() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ try {
+ xbf.getBean("jumble2");
+ fail("Should have thrown BeanCreationException");
+ }
+ catch (BeanCreationException ex) {
+ assertTrue(ex.getCause() instanceof BeanDefinitionStoreException);
+ assertTrue(ex.getCause().getMessage().indexOf("rod2") != -1);
+ }
+ }
+
+ public void testEmptyMap() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ HasMap hasMap = (HasMap) xbf.getBean("emptyMap");
+ assertTrue(hasMap.getMap().size() == 0);
+ }
+
+ public void testMapWithLiteralsOnly() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ HasMap hasMap = (HasMap) xbf.getBean("literalMap");
+ assertTrue(hasMap.getMap().size() == 3);
+ assertTrue(hasMap.getMap().get("foo").equals("bar"));
+ assertTrue(hasMap.getMap().get("fi").equals("fum"));
+ assertTrue(hasMap.getMap().get("fa") == null);
+ }
+
+ public void testMapWithLiteralsAndReferences() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ HasMap hasMap = (HasMap) xbf.getBean("mixedMap");
+ assertTrue(hasMap.getMap().size() == 3);
+ assertTrue(hasMap.getMap().get("foo").equals(new Integer(10)));
+ TestBean jenny = (TestBean) xbf.getBean("jenny");
+ assertTrue(hasMap.getMap().get("jenny") == jenny);
+ assertTrue(hasMap.getMap().get(new Integer(5)).equals("david"));
+ }
+
+ public void testMapWithLiteralsAndPrototypeReferences() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+
+ TestBean jenny = (TestBean) xbf.getBean("pJenny");
+ HasMap hasMap = (HasMap) xbf.getBean("pMixedMap");
+ assertTrue(hasMap.getMap().size() == 2);
+ assertTrue(hasMap.getMap().get("foo").equals("bar"));
+ assertTrue(hasMap.getMap().get("jenny").toString().equals(jenny.toString()));
+ assertTrue("Not same instance", hasMap.getMap().get("jenny") != jenny);
+
+ HasMap hasMap2 = (HasMap) xbf.getBean("pMixedMap");
+ assertTrue(hasMap2.getMap().size() == 2);
+ assertTrue(hasMap2.getMap().get("foo").equals("bar"));
+ assertTrue(hasMap2.getMap().get("jenny").toString().equals(jenny.toString()));
+ assertTrue("Not same instance", hasMap2.getMap().get("jenny") != hasMap.getMap().get("jenny"));
+ }
+
+ public void testMapWithLiteralsReferencesAndList() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ HasMap hasMap = (HasMap) xbf.getBean("mixedMapWithList");
+ assertTrue(hasMap.getMap().size() == 4);
+ assertTrue(hasMap.getMap().get(null).equals("bar"));
+ TestBean jenny = (TestBean) xbf.getBean("jenny");
+ assertTrue(hasMap.getMap().get("jenny").equals(jenny));
+
+ // Check list
+ List l = (List) hasMap.getMap().get("list");
+ assertNotNull(l);
+ assertTrue(l.size() == 4);
+ assertTrue(l.get(0).equals("zero"));
+ assertTrue(l.get(3) == null);
+
+ // Check nested map in list
+ Map m = (Map) l.get(1);
+ assertNotNull(m);
+ assertTrue(m.size() == 2);
+ assertTrue(m.get("fo").equals("bar"));
+ assertTrue("Map element 'jenny' should be equal to jenny bean, not " + m.get("jen"),
+ m.get("jen").equals(jenny));
+
+ // Check nested list in list
+ l = (List) l.get(2);
+ assertNotNull(l);
+ assertTrue(l.size() == 2);
+ assertTrue(l.get(0).equals(jenny));
+ assertTrue(l.get(1).equals("ba"));
+
+ // Check nested map
+ m = (Map) hasMap.getMap().get("map");
+ assertNotNull(m);
+ assertTrue(m.size() == 2);
+ assertTrue(m.get("foo").equals("bar"));
+ assertTrue("Map element 'jenny' should be equal to jenny bean, not " + m.get("jenny"),
+ m.get("jenny").equals(jenny));
+ }
+
+ public void testEmptySet() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ HasMap hasMap = (HasMap) xbf.getBean("emptySet");
+ assertTrue(hasMap.getSet().size() == 0);
+ }
+
+ public void testPopulatedSet() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ HasMap hasMap = (HasMap) xbf.getBean("set");
+ assertTrue(hasMap.getSet().size() == 3);
+ assertTrue(hasMap.getSet().contains("bar"));
+ TestBean jenny = (TestBean) xbf.getBean("jenny");
+ assertTrue(hasMap.getSet().contains(jenny));
+ assertTrue(hasMap.getSet().contains(null));
+ Iterator it = hasMap.getSet().iterator();
+ assertEquals("bar", it.next());
+ assertEquals(jenny, it.next());
+ assertEquals(null, it.next());
+ }
+
+ public void testEmptyProps() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ HasMap hasMap = (HasMap) xbf.getBean("emptyProps");
+ assertTrue(hasMap.getProps().size() == 0);
+ assertEquals(hasMap.getProps().getClass(), Properties.class);
+ }
+
+ public void testPopulatedProps() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ HasMap hasMap = (HasMap) xbf.getBean("props");
+ assertTrue(hasMap.getProps().size() == 2);
+ assertTrue(hasMap.getProps().get("foo").equals("bar"));
+ assertTrue(hasMap.getProps().get("2").equals("TWO"));
+ }
+
+ public void testObjectArray() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ HasMap hasMap = (HasMap) xbf.getBean("objectArray");
+ assertTrue(hasMap.getObjectArray().length == 2);
+ assertTrue(hasMap.getObjectArray()[0].equals("one"));
+ assertTrue(hasMap.getObjectArray()[1].equals(xbf.getBean("jenny")));
+ }
+
+ public void testClassArray() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ HasMap hasMap = (HasMap) xbf.getBean("classArray");
+ assertTrue(hasMap.getClassArray().length == 2);
+ assertTrue(hasMap.getClassArray()[0].equals(String.class));
+ assertTrue(hasMap.getClassArray()[1].equals(Exception.class));
+ }
+
+ public void testIntegerArray() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ HasMap hasMap = (HasMap) xbf.getBean("integerArray");
+ assertTrue(hasMap.getIntegerArray().length == 3);
+ assertTrue(hasMap.getIntegerArray()[0].intValue() == 0);
+ assertTrue(hasMap.getIntegerArray()[1].intValue() == 1);
+ assertTrue(hasMap.getIntegerArray()[2].intValue() == 2);
+ }
+
+ public void testProps() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+
+ HasMap hasMap = (HasMap) xbf.getBean("props");
+ assertEquals(2, hasMap.getProps().size());
+ assertEquals("bar", hasMap.getProps().getProperty("foo"));
+ assertEquals("TWO", hasMap.getProps().getProperty("2"));
+
+ HasMap hasMap2 = (HasMap) xbf.getBean("propsViaMap");
+ assertEquals(2, hasMap2.getProps().size());
+ assertEquals("bar", hasMap2.getProps().getProperty("foo"));
+ assertEquals("TWO", hasMap2.getProps().getProperty("2"));
+ }
+
+ public void testListFactory() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ List list = (List) xbf.getBean("listFactory");
+ assertTrue(list instanceof LinkedList);
+ assertTrue(list.size() == 2);
+ assertEquals("bar", list.get(0));
+ assertEquals("jenny", list.get(1));
+ }
+
+ public void testPrototypeListFactory() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ List list = (List) xbf.getBean("pListFactory");
+ assertTrue(list instanceof LinkedList);
+ assertTrue(list.size() == 2);
+ assertEquals("bar", list.get(0));
+ assertEquals("jenny", list.get(1));
+ }
+
+ public void testSetFactory() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ Set set = (Set) xbf.getBean("setFactory");
+ assertTrue(set instanceof TreeSet);
+ assertTrue(set.size() == 2);
+ assertTrue(set.contains("bar"));
+ assertTrue(set.contains("jenny"));
+ }
+
+ public void testPrototypeSetFactory() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ Set set = (Set) xbf.getBean("pSetFactory");
+ assertTrue(set instanceof TreeSet);
+ assertTrue(set.size() == 2);
+ assertTrue(set.contains("bar"));
+ assertTrue(set.contains("jenny"));
+ }
+
+ public void testMapFactory() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ Map map = (Map) xbf.getBean("mapFactory");
+ assertTrue(map instanceof TreeMap);
+ assertTrue(map.size() == 2);
+ assertEquals("bar", map.get("foo"));
+ assertEquals("jenny", map.get("jen"));
+ }
+
+ public void testPrototypeMapFactory() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ Map map = (Map) xbf.getBean("pMapFactory");
+ assertTrue(map instanceof TreeMap);
+ assertTrue(map.size() == 2);
+ assertEquals("bar", map.get("foo"));
+ assertEquals("jenny", map.get("jen"));
+ }
+
+ public void testChoiceBetweenSetAndMap() {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ MapAndSet sam = (MapAndSet) xbf.getBean("setAndMap");
+ assertTrue("Didn't choose constructor with Map argument", sam.getObject() instanceof Map);
+ Map map = (Map) sam.getObject();
+ assertEquals(3, map.size());
+ assertEquals("val1", map.get("key1"));
+ assertEquals("val2", map.get("key2"));
+ assertEquals("val3", map.get("key3"));
+ }
+
+ public void testEnumSetFactory() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("collections.xml", getClass()));
+ Set set = (Set) xbf.getBean("enumSetFactory");
+ assertTrue(set.size() == 2);
+ assertTrue(set.contains(FlushMode.NEVER));
+ assertTrue(set.contains(FlushMode.COMMIT));
+ }
+
+
+ public static class MapAndSet {
+
+ private Object obj;
+
+ public MapAndSet(Map map) {
+ this.obj = map;
+ }
+
+ public MapAndSet(Set set) {
+ this.obj = set;
+ }
+
+ public Object getObject() {
+ return obj;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/XmlBeanDefinitionReaderTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/XmlBeanDefinitionReaderTests.java
new file mode 100644
index 00000000000..efeab901716
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/XmlBeanDefinitionReaderTests.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+import org.xml.sax.InputSource;
+
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.BeanDefinitionStoreException;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.InputStreamResource;
+import org.springframework.core.io.Resource;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class XmlBeanDefinitionReaderTests extends TestCase {
+
+ public void testSetParserClassSunnyDay() {
+ SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
+ new XmlBeanDefinitionReader(registry).setDocumentReaderClass(DefaultBeanDefinitionDocumentReader.class);
+ }
+
+ public void testSetParserClassToNull() {
+ try {
+ SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
+ new XmlBeanDefinitionReader(registry).setDocumentReaderClass(null);
+ fail("Should have thrown IllegalArgumentException (null parserClass)");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testSetParserClassToUnsupportedParserType() throws Exception {
+ try {
+ SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
+ new XmlBeanDefinitionReader(registry).setDocumentReaderClass(String.class);
+ fail("Should have thrown IllegalArgumentException (unsupported parserClass)");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testWithOpenInputStream() {
+ try {
+ SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
+ Resource resource = new InputStreamResource(getClass().getResourceAsStream("test.xml"));
+ new XmlBeanDefinitionReader(registry).loadBeanDefinitions(resource);
+ fail("Should have thrown BeanDefinitionStoreException (can't determine validation mode)");
+ }
+ catch (BeanDefinitionStoreException expected) {
+ }
+ }
+
+ public void testWithOpenInputStreamAndExplicitValidationMode() {
+ SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
+ Resource resource = new InputStreamResource(getClass().getResourceAsStream("test.xml"));
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);
+ reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_DTD);
+ reader.loadBeanDefinitions(resource);
+ testBeanDefinitions(registry);
+ }
+
+ public void testWithInputSource() {
+ try {
+ SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
+ InputSource resource = new InputSource(getClass().getResourceAsStream("test.xml"));
+ new XmlBeanDefinitionReader(registry).loadBeanDefinitions(resource);
+ fail("Should have thrown BeanDefinitionStoreException (can't determine validation mode)");
+ }
+ catch (BeanDefinitionStoreException expected) {
+ }
+ }
+
+ public void testWithInputSourceAndExplicitValidationMode() {
+ SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
+ InputSource resource = new InputSource(getClass().getResourceAsStream("test.xml"));
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);
+ reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_DTD);
+ reader.loadBeanDefinitions(resource);
+ testBeanDefinitions(registry);
+ }
+
+ public void testWithFreshInputStream() {
+ SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();;
+ Resource resource = new ClassPathResource("test.xml", getClass());
+ new XmlBeanDefinitionReader(registry).loadBeanDefinitions(resource);
+ testBeanDefinitions(registry);
+ }
+
+ private void testBeanDefinitions(BeanDefinitionRegistry registry) {
+ assertEquals(24, registry.getBeanDefinitionCount());
+ assertEquals(24, registry.getBeanDefinitionNames().length);
+ assertTrue(Arrays.asList(registry.getBeanDefinitionNames()).contains("rod"));
+ assertTrue(Arrays.asList(registry.getBeanDefinitionNames()).contains("aliased"));
+ assertTrue(registry.containsBeanDefinition("rod"));
+ assertTrue(registry.containsBeanDefinition("aliased"));
+ assertEquals(TestBean.class.getName(), registry.getBeanDefinition("rod").getBeanClassName());
+ assertEquals(TestBean.class.getName(), registry.getBeanDefinition("aliased").getBeanClassName());
+ assertTrue(registry.isAlias("youralias"));
+ assertEquals(2, registry.getAliases("aliased").length);
+ assertEquals("myalias", registry.getAliases("aliased")[0]);
+ assertEquals("youralias", registry.getAliases("aliased")[1]);
+ }
+
+ public void testDtdValidationAutodetect() throws Exception {
+ doTestValidation("validateWithDtd.xml");
+ }
+
+ public void testXsdValidationAutodetect() throws Exception {
+ doTestValidation("validateWithXsd.xml");
+ }
+
+ private void doTestValidation(String resourceName) throws Exception {
+ DefaultListableBeanFactory factory = new DefaultListableBeanFactory();;
+ Resource resource = new ClassPathResource(resourceName, getClass());
+ new XmlBeanDefinitionReader(factory).loadBeanDefinitions(resource);
+ TestBean bean = (TestBean) factory.getBean("testBean");
+ assertNotNull(bean);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/XmlBeanFactoryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/XmlBeanFactoryTests.java
new file mode 100644
index 00000000000..359c8526cc3
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/XmlBeanFactoryTests.java
@@ -0,0 +1,1549 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringWriter;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+import org.apache.commons.logging.LogFactory;
+import org.xml.sax.InputSource;
+
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.DerivedTestBean;
+import org.springframework.beans.FatalBeanException;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.IndexedTestBean;
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.ResourceTestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.BeanCurrentlyInCreationException;
+import org.springframework.beans.factory.BeanDefinitionStoreException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanIsAbstractException;
+import org.springframework.beans.factory.CannotLoadBeanClassException;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.DummyFactory;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.UnsatisfiedDependencyException;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.support.MethodReplacer;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.UrlResource;
+import org.springframework.core.io.support.EncodedResource;
+import org.springframework.util.FileCopyUtils;
+import org.springframework.util.SerializationTestUtils;
+import org.springframework.util.StopWatch;
+
+/**
+ * Miscellaneous tests for XML bean definitions.
+ *
+ * @author Juergen Hoeller
+ * @author Rod Johnson
+ * @author Rick Evans
+ */
+public class XmlBeanFactoryTests extends TestCase {
+
+ /*
+ * http://opensource.atlassian.com/projects/spring/browse/SPR-2368
+ */
+ public void testCollectionsReferredToAsRefLocals() throws Exception {
+ XmlBeanFactory factory = new XmlBeanFactory(
+ new ClassPathResource("local-collections-using-XSD.xml", getClass()));
+ factory.preInstantiateSingletons();
+ }
+
+ public void testRefToSeparatePrototypeInstances() throws Exception {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE);
+ reader.loadBeanDefinitions(new ClassPathResource("reftypes.xml", getClass()));
+
+ TestBean emma = (TestBean) xbf.getBean("emma");
+ TestBean georgia = (TestBean) xbf.getBean("georgia");
+ ITestBean emmasJenks = emma.getSpouse();
+ ITestBean georgiasJenks = georgia.getSpouse();
+ assertTrue("Emma and georgia think they have a different boyfriend", emmasJenks != georgiasJenks);
+ assertTrue("Emmas jenks has right name", emmasJenks.getName().equals("Andrew"));
+ assertTrue("Emmas doesn't equal new ref", emmasJenks != xbf.getBean("jenks"));
+ assertTrue("Georgias jenks has right name", emmasJenks.getName().equals("Andrew"));
+ assertTrue("They are object equal", emmasJenks.equals(georgiasJenks));
+ assertTrue("They object equal direct ref", emmasJenks.equals(xbf.getBean("jenks")));
+ }
+
+ public void testRefToSingleton() throws Exception {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE);
+ Resource resource = new ClassPathResource("reftypes.xml", getClass());
+ reader.loadBeanDefinitions(new EncodedResource(resource, "ISO-8859-1"));
+
+ TestBean jen = (TestBean) xbf.getBean("jenny");
+ TestBean dave = (TestBean) xbf.getBean("david");
+ TestBean jenks = (TestBean) xbf.getBean("jenks");
+ ITestBean davesJen = dave.getSpouse();
+ ITestBean jenksJen = jenks.getSpouse();
+ assertTrue("1 jen instance", davesJen == jenksJen);
+ assertTrue("1 jen instance", davesJen == jen);
+ }
+
+ public void testInnerBeans() throws IOException {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+
+ reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE);
+ InputStream inputStream = getClass().getResourceAsStream("reftypes.xml");
+ try {
+ reader.loadBeanDefinitions(new InputSource(inputStream));
+ }
+ finally {
+ inputStream.close();
+ }
+
+ // Let's create the outer bean named "innerBean",
+ // to check whether it doesn't create any conflicts
+ // with the actual inner beans named "innerBean".
+ xbf.getBean("innerBean");
+
+ TestBean hasInnerBeans = (TestBean) xbf.getBean("hasInnerBeans");
+ assertEquals(5, hasInnerBeans.getAge());
+ TestBean inner1 = (TestBean) hasInnerBeans.getSpouse();
+ assertNotNull(inner1);
+ assertEquals("innerBean#1", inner1.getBeanName());
+ assertEquals("inner1", inner1.getName());
+ assertEquals(6, inner1.getAge());
+
+ assertNotNull(hasInnerBeans.getFriends());
+ Object[] friends = hasInnerBeans.getFriends().toArray();
+ assertEquals(3, friends.length);
+ DerivedTestBean inner2 = (DerivedTestBean) friends[0];
+ assertEquals("inner2", inner2.getName());
+ assertTrue(inner2.getBeanName().startsWith(DerivedTestBean.class.getName()));
+ assertFalse(xbf.containsBean("innerBean#1"));
+ assertNotNull(inner2);
+ assertEquals(7, inner2.getAge());
+ TestBean innerFactory = (TestBean) friends[1];
+ assertEquals(DummyFactory.SINGLETON_NAME, innerFactory.getName());
+ TestBean inner5 = (TestBean) friends[2];
+ assertEquals("innerBean#2", inner5.getBeanName());
+
+ assertNotNull(hasInnerBeans.getSomeMap());
+ assertEquals(2, hasInnerBeans.getSomeMap().size());
+ TestBean inner3 = (TestBean) hasInnerBeans.getSomeMap().get("someKey");
+ assertEquals("Jenny", inner3.getName());
+ assertEquals(30, inner3.getAge());
+ TestBean inner4 = (TestBean) hasInnerBeans.getSomeMap().get("someOtherKey");
+ assertEquals("inner4", inner4.getName());
+ assertEquals(9, inner4.getAge());
+
+ TestBean hasInnerBeansForConstructor = (TestBean) xbf.getBean("hasInnerBeansForConstructor");
+ TestBean innerForConstructor = (TestBean) hasInnerBeansForConstructor.getSpouse();
+ assertNotNull(innerForConstructor);
+ assertEquals("innerBean#3", innerForConstructor.getBeanName());
+ assertEquals("inner1", innerForConstructor.getName());
+ assertEquals(6, innerForConstructor.getAge());
+
+ xbf.destroySingletons();
+ assertTrue(inner1.wasDestroyed());
+ assertTrue(inner2.wasDestroyed());
+ assertTrue(innerFactory.getName() == null);
+ assertTrue(inner5.wasDestroyed());
+ }
+
+ public void testInnerBeansWithoutDestroy() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE);
+ reader.loadBeanDefinitions(new ClassPathResource("reftypes.xml", getClass()));
+
+ // Let's create the outer bean named "innerBean",
+ // to check whether it doesn't create any conflicts
+ // with the actual inner beans named "innerBean".
+ xbf.getBean("innerBean");
+
+ TestBean hasInnerBeans = (TestBean) xbf.getBean("hasInnerBeansWithoutDestroy");
+ assertEquals(5, hasInnerBeans.getAge());
+ TestBean inner1 = (TestBean) hasInnerBeans.getSpouse();
+ assertNotNull(inner1);
+ assertEquals("innerBean", inner1.getBeanName());
+ assertEquals("inner1", inner1.getName());
+ assertEquals(6, inner1.getAge());
+
+ assertNotNull(hasInnerBeans.getFriends());
+ Object[] friends = hasInnerBeans.getFriends().toArray();
+ assertEquals(3, friends.length);
+ DerivedTestBean inner2 = (DerivedTestBean) friends[0];
+ assertEquals("inner2", inner2.getName());
+ assertTrue(inner2.getBeanName().startsWith(DerivedTestBean.class.getName()));
+ assertNotNull(inner2);
+ assertEquals(7, inner2.getAge());
+ TestBean innerFactory = (TestBean) friends[1];
+ assertEquals(DummyFactory.SINGLETON_NAME, innerFactory.getName());
+ TestBean inner5 = (TestBean) friends[2];
+ assertEquals("innerBean", inner5.getBeanName());
+ }
+
+ public void testFailsOnInnerBean() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE);
+ reader.loadBeanDefinitions(new ClassPathResource("reftypes.xml", getClass()));
+
+ try {
+ xbf.getBean("failsOnInnerBean");
+ }
+ catch (BeanCreationException ex) {
+ // Check whether message contains outer bean name.
+ ex.printStackTrace();
+ assertTrue(ex.getMessage().indexOf("failsOnInnerBean") != -1);
+ assertTrue(ex.getMessage().indexOf("someMap") != -1);
+ }
+
+ try {
+ xbf.getBean("failsOnInnerBeanForConstructor");
+ }
+ catch (BeanCreationException ex) {
+ // Check whether message contains outer bean name.
+ ex.printStackTrace();
+ assertTrue(ex.getMessage().indexOf("failsOnInnerBeanForConstructor") != -1);
+ assertTrue(ex.getMessage().indexOf("constructor argument") != -1);
+ }
+ }
+
+ public void testSingletonInheritanceFromParentFactorySingleton() throws Exception {
+ XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("parent.xml", getClass()));
+ XmlBeanFactory child = new XmlBeanFactory(new ClassPathResource("child.xml", getClass()), parent);
+ assertEquals(TestBean.class, child.getType("inheritsFromParentFactory"));
+ TestBean inherits = (TestBean) child.getBean("inheritsFromParentFactory");
+ // Name property value is overridden
+ assertTrue(inherits.getName().equals("override"));
+ // Age property is inherited from bean in parent factory
+ assertTrue(inherits.getAge() == 1);
+ TestBean inherits2 = (TestBean) child.getBean("inheritsFromParentFactory");
+ assertTrue(inherits2 == inherits);
+ }
+
+ public void testInheritanceWithDifferentClass() throws Exception {
+ XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("parent.xml", getClass()));
+ XmlBeanFactory child = new XmlBeanFactory(new ClassPathResource("child.xml", getClass()), parent);
+ assertEquals(DerivedTestBean.class, child.getType("inheritsWithClass"));
+ DerivedTestBean inherits = (DerivedTestBean) child.getBean("inheritsWithDifferentClass");
+ // Name property value is overridden
+ assertTrue(inherits.getName().equals("override"));
+ // Age property is inherited from bean in parent factory
+ assertTrue(inherits.getAge() == 1);
+ assertTrue(inherits.wasInitialized());
+ }
+
+ public void testInheritanceWithClass() throws Exception {
+ XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("parent.xml", getClass()));
+ XmlBeanFactory child = new XmlBeanFactory(new ClassPathResource("child.xml", getClass()), parent);
+ assertEquals(DerivedTestBean.class, child.getType("inheritsWithClass"));
+ DerivedTestBean inherits = (DerivedTestBean) child.getBean("inheritsWithClass");
+ // Name property value is overridden
+ assertTrue(inherits.getName().equals("override"));
+ // Age property is inherited from bean in parent factory
+ assertTrue(inherits.getAge() == 1);
+ assertTrue(inherits.wasInitialized());
+ }
+
+ public void testPrototypeInheritanceFromParentFactoryPrototype() throws Exception {
+ XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("parent.xml", getClass()));
+ XmlBeanFactory child = new XmlBeanFactory(new ClassPathResource("child.xml", getClass()), parent);
+ assertEquals(TestBean.class, child.getType("prototypeInheritsFromParentFactoryPrototype"));
+ TestBean inherits = (TestBean) child.getBean("prototypeInheritsFromParentFactoryPrototype");
+ // Name property value is overridden
+ assertTrue(inherits.getName().equals("prototype-override"));
+ // Age property is inherited from bean in parent factory
+ assertTrue(inherits.getAge() == 2);
+ TestBean inherits2 = (TestBean) child.getBean("prototypeInheritsFromParentFactoryPrototype");
+ assertFalse(inherits2 == inherits);
+ inherits2.setAge(13);
+ assertTrue(inherits2.getAge() == 13);
+ // Shouldn't have changed first instance
+ assertTrue(inherits.getAge() == 2);
+ }
+
+ public void testPrototypeInheritanceFromParentFactorySingleton() throws Exception {
+ XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("parent.xml", getClass()));
+ XmlBeanFactory child = new XmlBeanFactory(new ClassPathResource("child.xml", getClass()), parent);
+ TestBean inherits = (TestBean) child.getBean("protoypeInheritsFromParentFactorySingleton");
+ // Name property value is overridden
+ assertTrue(inherits.getName().equals("prototypeOverridesInheritedSingleton"));
+ // Age property is inherited from bean in parent factory
+ assertTrue(inherits.getAge() == 1);
+ TestBean inherits2 = (TestBean) child.getBean("protoypeInheritsFromParentFactorySingleton");
+ assertFalse(inherits2 == inherits);
+ inherits2.setAge(13);
+ assertTrue(inherits2.getAge() == 13);
+ // Shouldn't have changed first instance
+ assertTrue(inherits.getAge() == 1);
+ }
+
+ public void testAutowireModeNotInherited() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.loadBeanDefinitions(new ClassPathResource("overrides.xml", getClass()));
+
+ TestBean david = (TestBean)xbf.getBean("magicDavid");
+ // the parent bean is autowiring
+ assertNotNull(david.getSpouse());
+
+ TestBean derivedDavid = (TestBean)xbf.getBean("magicDavidDerived");
+ // this fails while it inherits from the child bean
+ assertNull("autowiring not propagated along child relationships", derivedDavid.getSpouse());
+ }
+
+ public void testAbstractParentBeans() {
+ XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("parent.xml", getClass()));
+ parent.preInstantiateSingletons();
+ assertTrue(parent.isSingleton("inheritedTestBeanWithoutClass"));
+
+ // abstract beans should not match
+ Map tbs = parent.getBeansOfType(TestBean.class);
+ assertEquals(2, tbs.size());
+ assertTrue(tbs.containsKey("inheritedTestBeanPrototype"));
+ assertTrue(tbs.containsKey("inheritedTestBeanSingleton"));
+
+ // abstract bean should throw exception on creation attempt
+ try {
+ parent.getBean("inheritedTestBeanWithoutClass");
+ fail("Should have thrown BeanIsAbstractException");
+ }
+ catch (BeanIsAbstractException ex) {
+ // expected
+ }
+
+ // non-abstract bean should work, even if it serves as parent
+ assertTrue(parent.getBean("inheritedTestBeanPrototype") instanceof TestBean);
+ }
+
+ public void testDependenciesMaterializeThis() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("dependenciesMaterializeThis.xml", getClass()));
+
+ assertEquals(2, xbf.getBeansOfType(DummyBo.class, true, false).size());
+ assertEquals(3, xbf.getBeansOfType(DummyBo.class, true, true).size());
+ assertEquals(3, xbf.getBeansOfType(DummyBo.class, true, false).size());
+ assertEquals(3, xbf.getBeansOfType(DummyBo.class).size());
+ assertEquals(2, xbf.getBeansOfType(DummyBoImpl.class, true, true).size());
+ assertEquals(1, xbf.getBeansOfType(DummyBoImpl.class, false, true).size());
+ assertEquals(2, xbf.getBeansOfType(DummyBoImpl.class).size());
+
+ DummyBoImpl bos = (DummyBoImpl) xbf.getBean("boSingleton");
+ DummyBoImpl bop = (DummyBoImpl) xbf.getBean("boPrototype");
+ assertNotSame(bos, bop);
+ assertTrue(bos.dao == bop.dao);
+ }
+
+ public void testChildOverridesParentBean() throws Exception {
+ XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("parent.xml", getClass()));
+ XmlBeanFactory child = new XmlBeanFactory(new ClassPathResource("child.xml", getClass()), parent);
+ TestBean inherits = (TestBean) child.getBean("inheritedTestBean");
+ // Name property value is overridden
+ assertTrue(inherits.getName().equals("overrideParentBean"));
+ // Age property is inherited from bean in parent factory
+ assertTrue(inherits.getAge() == 1);
+ TestBean inherits2 = (TestBean) child.getBean("inheritedTestBean");
+ assertTrue(inherits2 == inherits);
+ }
+
+ /**
+ * Check that a prototype can't inherit from a bogus parent.
+ * If a singleton does this the factory will fail to load.
+ */
+ public void testBogusParentageFromParentFactory() throws Exception {
+ XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("parent.xml", getClass()));
+ XmlBeanFactory child = new XmlBeanFactory(new ClassPathResource("child.xml", getClass()), parent);
+ try {
+ child.getBean("bogusParent", TestBean.class);
+ fail();
+ }
+ catch (BeanDefinitionStoreException ex) {
+ // check exception message contains the name
+ assertTrue(ex.getMessage().indexOf("bogusParent") != -1);
+ assertTrue(ex.getCause() instanceof NoSuchBeanDefinitionException);
+ }
+ }
+
+ /**
+ * Note that prototype/singleton distinction is not inherited.
+ * It's possible for a subclass singleton not to return independent
+ * instances even if derived from a prototype
+ */
+ public void testSingletonInheritsFromParentFactoryPrototype() throws Exception {
+ XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("parent.xml", getClass()));
+ XmlBeanFactory child = new XmlBeanFactory(new ClassPathResource("child.xml", getClass()), parent);
+ TestBean inherits = (TestBean) child.getBean("singletonInheritsFromParentFactoryPrototype");
+ // Name property value is overriden
+ assertTrue(inherits.getName().equals("prototype-override"));
+ // Age property is inherited from bean in parent factory
+ assertTrue(inherits.getAge() == 2);
+ TestBean inherits2 = (TestBean) child.getBean("singletonInheritsFromParentFactoryPrototype");
+ assertTrue(inherits2 == inherits);
+ }
+
+ public void testSingletonFromParent() {
+ XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("parent.xml", getClass()));
+ TestBean beanFromParent = (TestBean) parent.getBean("inheritedTestBeanSingleton");
+ XmlBeanFactory child = new XmlBeanFactory(new ClassPathResource("child.xml", getClass()), parent);
+ TestBean beanFromChild = (TestBean) child.getBean("inheritedTestBeanSingleton");
+ assertTrue("singleton from parent and child is the same", beanFromParent == beanFromChild);
+ }
+
+ public void testNestedPropertyValue() {
+ XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("parent.xml", getClass()));
+ XmlBeanFactory child = new XmlBeanFactory(new ClassPathResource("child.xml", getClass()), parent);
+ IndexedTestBean bean = (IndexedTestBean) child.getBean("indexedTestBean");
+ assertEquals("name applied correctly", "myname", bean.getArray()[0].getName());
+ }
+
+ public void testCircularReferences() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE);
+ reader.loadBeanDefinitions(new ClassPathResource("reftypes.xml", getClass()));
+ TestBean jenny = (TestBean) xbf.getBean("jenny");
+ TestBean david = (TestBean) xbf.getBean("david");
+ TestBean ego = (TestBean) xbf.getBean("ego");
+ TestBean complexInnerEgo = (TestBean) xbf.getBean("complexInnerEgo");
+ TestBean complexEgo = (TestBean) xbf.getBean("complexEgo");
+ assertTrue("Correct circular reference", jenny.getSpouse() == david);
+ assertTrue("Correct circular reference", david.getSpouse() == jenny);
+ assertTrue("Correct circular reference", ego.getSpouse() == ego);
+ assertTrue("Correct circular reference", complexInnerEgo.getSpouse().getSpouse() == complexInnerEgo);
+ assertTrue("Correct circular reference", complexEgo.getSpouse().getSpouse() == complexEgo);
+ }
+
+ public void testCircularReferenceWithFactoryBeanFirst() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE);
+ reader.loadBeanDefinitions(new ClassPathResource("reftypes.xml", getClass()));
+ TestBean egoBridge = (TestBean) xbf.getBean("egoBridge");
+ TestBean complexEgo = (TestBean) xbf.getBean("complexEgo");
+ assertTrue("Correct circular reference", complexEgo.getSpouse().getSpouse() == complexEgo);
+ }
+
+ public void testCircularReferenceWithTwoFactoryBeans() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE);
+ reader.loadBeanDefinitions(new ClassPathResource("reftypes.xml", getClass()));
+ TestBean ego1 = (TestBean) xbf.getBean("ego1");
+ assertTrue("Correct circular reference", ego1.getSpouse().getSpouse() == ego1);
+ TestBean ego3 = (TestBean) xbf.getBean("ego3");
+ assertTrue("Correct circular reference", ego3.getSpouse().getSpouse() == ego3);
+ }
+
+ public void testCircularReferencesWithNotAllowed() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ xbf.setAllowCircularReferences(false);
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE);
+ reader.loadBeanDefinitions(new ClassPathResource("reftypes.xml", getClass()));
+ try {
+ xbf.getBean("jenny");
+ fail("Should have thrown BeanCreationException");
+ }
+ catch (BeanCreationException ex) {
+ assertTrue(ex.contains(BeanCurrentlyInCreationException.class));
+ }
+ }
+
+ public void testCircularReferencesWithWrapping() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE);
+ reader.loadBeanDefinitions(new ClassPathResource("reftypes.xml", getClass()));
+ xbf.addBeanPostProcessor(new WrappingPostProcessor());
+ try {
+ xbf.getBean("jenny");
+ fail("Should have thrown BeanCreationException");
+ }
+ catch (BeanCreationException ex) {
+ assertTrue(ex.contains(BeanCurrentlyInCreationException.class));
+ }
+ }
+
+ public void testCircularReferencesWithWrappingAndRawInjectionAllowed() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ xbf.setAllowRawInjectionDespiteWrapping(true);
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE);
+ reader.loadBeanDefinitions(new ClassPathResource("reftypes.xml", getClass()));
+ xbf.addBeanPostProcessor(new WrappingPostProcessor());
+
+ ITestBean jenny = (ITestBean) xbf.getBean("jenny");
+ ITestBean david = (ITestBean) xbf.getBean("david");
+ assertTrue(AopUtils.isAopProxy(jenny));
+ assertTrue(AopUtils.isAopProxy(david));
+ assertSame(david, jenny.getSpouse());
+ assertNotSame(jenny, david.getSpouse());
+ assertEquals("Jenny", david.getSpouse().getName());
+ assertSame(david, david.getSpouse().getSpouse());
+ assertTrue(AopUtils.isAopProxy(jenny.getSpouse()));
+ assertTrue(!AopUtils.isAopProxy(david.getSpouse()));
+ }
+
+ public void testFactoryReferenceCircle() {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("factoryCircle.xml", getClass()));
+ TestBean tb = (TestBean) xbf.getBean("singletonFactory");
+ DummyFactory db = (DummyFactory) xbf.getBean("&singletonFactory");
+ assertTrue(tb == db.getOtherTestBean());
+ }
+
+ public void testFactoryReferenceWithDoublePrefix() {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("factoryCircle.xml", getClass()));
+ DummyFactory db = (DummyFactory) xbf.getBean("&&singletonFactory");
+ }
+
+ public void testComplexFactoryReferenceCircle() {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("complexFactoryCircle.xml", getClass()));
+ xbf.getBean("proxy1");
+ // check that unused instances from autowiring got removed
+ assertEquals(5, xbf.getSingletonCount());
+ // properly create the remaining two instances
+ xbf.getBean("proxy2");
+ assertEquals(7, xbf.getSingletonCount());
+ }
+
+ public void testNoSuchFactoryBeanMethod() {
+ try {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("no-such-factory-method.xml", getClass()));
+ assertNotNull(xbf.getBean("defaultTestBean"));
+ fail("Should not get invalid bean");
+ }
+ catch (BeanCreationException ex) {
+ // Ok
+ }
+ }
+
+ public void testInitMethodIsInvoked() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("initializers.xml", getClass()));
+ DoubleInitializer in = (DoubleInitializer) xbf.getBean("init-method1");
+ // Initializer should have doubled value
+ assertEquals(14, in.getNum());
+ }
+
+ /**
+ * Test that if a custom initializer throws an exception, it's handled correctly
+ */
+ public void testInitMethodThrowsException() {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("initializers.xml", getClass()));
+ try {
+ xbf.getBean("init-method2");
+ fail();
+ }
+ catch (BeanCreationException ex) {
+ assertTrue(ex.getResourceDescription().indexOf("initializers.xml") != -1);
+ assertEquals("init-method2", ex.getBeanName());
+ assertTrue(ex.getCause() instanceof ServletException);
+ }
+ }
+
+ public void testNoSuchInitMethod() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("initializers.xml", getClass()));
+ try {
+ xbf.getBean("init-method3");
+ fail();
+ }
+ catch (FatalBeanException ex) {
+ // check message is helpful
+ assertTrue(ex.getMessage().indexOf("initializers.xml") != -1);
+ assertTrue(ex.getMessage().indexOf("init-method3") != -1);
+ assertTrue(ex.getMessage().indexOf("init") != -1);
+ }
+ }
+
+ /**
+ * Check that InitializingBean method is called first.
+ */
+ public void testInitializingBeanAndInitMethod() throws Exception {
+ InitAndIB.constructed = false;
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("initializers.xml", getClass()));
+ assertFalse(InitAndIB.constructed);
+ xbf.preInstantiateSingletons();
+ assertFalse(InitAndIB.constructed);
+ InitAndIB iib = (InitAndIB) xbf.getBean("init-and-ib");
+ assertTrue(InitAndIB.constructed);
+ assertTrue(iib.afterPropertiesSetInvoked && iib.initMethodInvoked);
+ assertTrue(!iib.destroyed && !iib.customDestroyed);
+ xbf.destroySingletons();
+ assertTrue(iib.destroyed && iib.customDestroyed);
+ xbf.destroySingletons();
+ assertTrue(iib.destroyed && iib.customDestroyed);
+ }
+
+ /**
+ * Check that InitializingBean method is not called twice.
+ */
+ public void testInitializingBeanAndSameInitMethod() throws Exception {
+ InitAndIB.constructed = false;
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("initializers.xml", getClass()));
+ assertFalse(InitAndIB.constructed);
+ xbf.preInstantiateSingletons();
+ assertFalse(InitAndIB.constructed);
+ InitAndIB iib = (InitAndIB) xbf.getBean("ib-same-init");
+ assertTrue(InitAndIB.constructed);
+ assertTrue(iib.afterPropertiesSetInvoked && !iib.initMethodInvoked);
+ assertTrue(!iib.destroyed && !iib.customDestroyed);
+ xbf.destroySingletons();
+ assertTrue(iib.destroyed && !iib.customDestroyed);
+ xbf.destroySingletons();
+ assertTrue(iib.destroyed && !iib.customDestroyed);
+ }
+
+ public void testDefaultLazyInit() throws Exception {
+ InitAndIB.constructed = false;
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("default-lazy-init.xml", getClass()));
+ assertFalse(InitAndIB.constructed);
+ xbf.preInstantiateSingletons();
+ assertTrue(InitAndIB.constructed);
+ try {
+ xbf.getBean("lazy-and-bad");
+ }
+ catch (BeanCreationException ex) {
+ assertTrue(ex.getCause() instanceof ServletException);
+ }
+ }
+
+ public void testNoSuchXmlFile() throws Exception {
+ try {
+ new XmlBeanFactory(new ClassPathResource("missing.xml", getClass()));
+ fail("Must not create factory from missing XML");
+ }
+ catch (BeanDefinitionStoreException expected) {
+ }
+ }
+
+ public void testInvalidXmlFile() throws Exception {
+ try {
+ new XmlBeanFactory(new ClassPathResource("invalid.xml", getClass()));
+ fail("Must not create factory from invalid XML");
+ }
+ catch (BeanDefinitionStoreException expected) {
+ }
+ }
+
+ public void testUnsatisfiedObjectDependencyCheck() throws Exception {
+ try {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("unsatisfiedObjectDependencyCheck.xml", getClass()));
+ xbf.getBean("a", DependenciesBean.class);
+ fail("Must have thrown an UnsatisfiedDependencyException");
+ }
+ catch (UnsatisfiedDependencyException ex) {
+ }
+ }
+
+ public void testUnsatisfiedSimpleDependencyCheck() throws Exception {
+ try {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("unsatisfiedSimpleDependencyCheck.xml", getClass()));
+ xbf.getBean("a", DependenciesBean.class);
+ fail("Must have thrown an UnsatisfiedDependencyException");
+ }
+ catch (UnsatisfiedDependencyException expected) {
+ }
+ }
+
+ public void testSatisfiedObjectDependencyCheck() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("satisfiedObjectDependencyCheck.xml", getClass()));
+ DependenciesBean a = (DependenciesBean) xbf.getBean("a");
+ assertNotNull(a.getSpouse());
+ assertEquals(xbf, a.getBeanFactory());
+ }
+
+ public void testSatisfiedSimpleDependencyCheck() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("satisfiedSimpleDependencyCheck.xml", getClass()));
+ DependenciesBean a = (DependenciesBean) xbf.getBean("a");
+ assertEquals(a.getAge(), 33);
+ }
+
+ public void testUnsatisfiedAllDependencyCheck() throws Exception {
+ try {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("unsatisfiedAllDependencyCheckMissingObjects.xml", getClass()));
+ xbf.getBean("a", DependenciesBean.class);
+ fail("Must have thrown an UnsatisfiedDependencyException");
+ }
+ catch (UnsatisfiedDependencyException expected) {
+ }
+ }
+
+ public void testSatisfiedAllDependencyCheck() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("satisfiedAllDependencyCheck.xml", getClass()));
+ DependenciesBean a = (DependenciesBean) xbf.getBean("a");
+ assertEquals(a.getAge(), 33);
+ assertNotNull(a.getName());
+ assertNotNull(a.getSpouse());
+ }
+
+ public void testAutowire() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("autowire.xml", getClass()));
+ TestBean spouse = new TestBean("kerry", 0);
+ xbf.registerSingleton("spouse", spouse);
+ doTestAutowire(xbf);
+ }
+
+ public void testAutowireWithParent() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("autowire.xml", getClass()));
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "kerry");
+ lbf.registerBeanDefinition("spouse", new RootBeanDefinition(TestBean.class, pvs));
+ xbf.setParentBeanFactory(lbf);
+ doTestAutowire(xbf);
+ }
+
+ private void doTestAutowire(XmlBeanFactory xbf) throws Exception {
+ DependenciesBean rod1 = (DependenciesBean) xbf.getBean("rod1");
+ TestBean kerry = (TestBean) xbf.getBean("spouse");
+ // should have been autowired
+ assertEquals(kerry, rod1.getSpouse());
+
+ DependenciesBean rod1a = (DependenciesBean) xbf.getBean("rod1a");
+ // should have been autowired
+ assertEquals(kerry, rod1a.getSpouse());
+
+ DependenciesBean rod2 = (DependenciesBean) xbf.getBean("rod2");
+ // should have been autowired
+ assertEquals(kerry, rod2.getSpouse());
+
+ DependenciesBean rod2a = (DependenciesBean) xbf.getBean("rod2a");
+ // should have been set explicitly
+ assertEquals(kerry, rod2a.getSpouse());
+
+ ConstructorDependenciesBean rod3 = (ConstructorDependenciesBean) xbf.getBean("rod3");
+ IndexedTestBean other = (IndexedTestBean) xbf.getBean("other");
+ // should have been autowired
+ assertEquals(kerry, rod3.getSpouse1());
+ assertEquals(kerry, rod3.getSpouse2());
+ assertEquals(other, rod3.getOther());
+
+ ConstructorDependenciesBean rod3a = (ConstructorDependenciesBean) xbf.getBean("rod3a");
+ // should have been autowired
+ assertEquals(kerry, rod3a.getSpouse1());
+ assertEquals(kerry, rod3a.getSpouse2());
+ assertEquals(other, rod3a.getOther());
+
+ try {
+ xbf.getBean("rod4", ConstructorDependenciesBean.class);
+ fail("Must have thrown a FatalBeanException");
+ }
+ catch (FatalBeanException expected) {
+ }
+
+ DependenciesBean rod5 = (DependenciesBean) xbf.getBean("rod5");
+ // Should not have been autowired
+ assertNull(rod5.getSpouse());
+
+ BeanFactory appCtx = (BeanFactory) xbf.getBean("childAppCtx");
+ assertTrue(appCtx.containsBean("rod1"));
+ assertTrue(appCtx.containsBean("jenny"));
+ }
+
+ public void testAutowireWithDefault() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("default-autowire.xml", getClass()));
+
+ DependenciesBean rod1 = (DependenciesBean) xbf.getBean("rod1");
+ // should have been autowired
+ assertNotNull(rod1.getSpouse());
+ assertTrue(rod1.getSpouse().getName().equals("Kerry"));
+
+ DependenciesBean rod2 = (DependenciesBean) xbf.getBean("rod2");
+ // should have been autowired
+ assertNotNull(rod2.getSpouse());
+ assertTrue(rod2.getSpouse().getName().equals("Kerry"));
+
+ try {
+ xbf.getBean("rod3", DependenciesBean.class);
+ fail("Must have thrown UnsatisfiedDependencyException");
+ }
+ catch (UnsatisfiedDependencyException expected) {
+ }
+ }
+
+ public void testAutowireByConstructor() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("constructor-arg.xml", getClass()));
+ ConstructorDependenciesBean rod1 = (ConstructorDependenciesBean) xbf.getBean("rod1");
+ TestBean kerry = (TestBean) xbf.getBean("kerry2");
+ // should have been autowired
+ assertEquals(kerry, rod1.getSpouse1());
+ assertEquals(0, rod1.getAge());
+ assertEquals(null, rod1.getName());
+
+ ConstructorDependenciesBean rod2 = (ConstructorDependenciesBean) xbf.getBean("rod2");
+ TestBean kerry1 = (TestBean) xbf.getBean("kerry1");
+ TestBean kerry2 = (TestBean) xbf.getBean("kerry2");
+ // should have been autowired
+ assertEquals(kerry2, rod2.getSpouse1());
+ assertEquals(kerry1, rod2.getSpouse2());
+ assertEquals(0, rod2.getAge());
+ assertEquals(null, rod2.getName());
+
+ ConstructorDependenciesBean rod = (ConstructorDependenciesBean) xbf.getBean("rod3");
+ IndexedTestBean other = (IndexedTestBean) xbf.getBean("other");
+ // should have been autowired
+ assertEquals(kerry, rod.getSpouse1());
+ assertEquals(kerry, rod.getSpouse2());
+ assertEquals(other, rod.getOther());
+ assertEquals(0, rod.getAge());
+ assertEquals(null, rod.getName());
+
+ xbf.getBean("rod4", ConstructorDependenciesBean.class);
+ // should have been autowired
+ assertEquals(kerry, rod.getSpouse1());
+ assertEquals(kerry, rod.getSpouse2());
+ assertEquals(other, rod.getOther());
+ assertEquals(0, rod.getAge());
+ assertEquals(null, rod.getName());
+ }
+
+ public void testAutowireByConstructorWithSimpleValues() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("constructor-arg.xml", getClass()));
+
+ ConstructorDependenciesBean rod5 = (ConstructorDependenciesBean) xbf.getBean("rod5");
+ TestBean kerry1 = (TestBean) xbf.getBean("kerry1");
+ TestBean kerry2 = (TestBean) xbf.getBean("kerry2");
+ IndexedTestBean other = (IndexedTestBean) xbf.getBean("other");
+ // should have been autowired
+ assertEquals(kerry2, rod5.getSpouse1());
+ assertEquals(kerry1, rod5.getSpouse2());
+ assertEquals(other, rod5.getOther());
+ assertEquals(99, rod5.getAge());
+ assertEquals("myname", rod5.getName());
+
+ DerivedConstructorDependenciesBean rod6 = (DerivedConstructorDependenciesBean) xbf.getBean("rod6");
+ // should have been autowired
+ assertTrue(rod6.initialized);
+ assertTrue(!rod6.destroyed);
+ assertEquals(kerry2, rod6.getSpouse1());
+ assertEquals(kerry1, rod6.getSpouse2());
+ assertEquals(other, rod6.getOther());
+ assertEquals(0, rod6.getAge());
+ assertEquals(null, rod6.getName());
+
+ xbf.destroySingletons();
+ assertTrue(rod6.destroyed);
+ }
+
+ public void testRelatedCausesFromConstructorResolution() {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("constructor-arg.xml", getClass()));
+
+ try {
+ xbf.getBean("rod2Accessor");
+ }
+ catch (BeanCreationException ex) {
+ assertTrue(ex.toString().indexOf("touchy") != -1);
+ ex.printStackTrace();
+ assertNull(ex.getRelatedCauses());
+ }
+ }
+
+ public void testConstructorArgResolution() {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("constructor-arg.xml", getClass()));
+ TestBean kerry1 = (TestBean) xbf.getBean("kerry1");
+ TestBean kerry2 = (TestBean) xbf.getBean("kerry2");
+
+ ConstructorDependenciesBean rod9 = (ConstructorDependenciesBean) xbf.getBean("rod9");
+ assertEquals(99, rod9.getAge());
+ ConstructorDependenciesBean rod9a = (ConstructorDependenciesBean) xbf.getBean("rod9", new Object[] {new Integer(98)});
+ assertEquals(98, rod9a.getAge());
+ ConstructorDependenciesBean rod9b = (ConstructorDependenciesBean) xbf.getBean("rod9", new Object[] {"myName"});
+ assertEquals("myName", rod9b.getName());
+ ConstructorDependenciesBean rod9c = (ConstructorDependenciesBean) xbf.getBean("rod9", new Object[] {new Integer(97)});
+ assertEquals(97, rod9c.getAge());
+
+ ConstructorDependenciesBean rod10 = (ConstructorDependenciesBean) xbf.getBean("rod10");
+ assertEquals(null, rod10.getName());
+
+ ConstructorDependenciesBean rod11 = (ConstructorDependenciesBean) xbf.getBean("rod11");
+ assertEquals(kerry2, rod11.getSpouse1());
+
+ ConstructorDependenciesBean rod12 = (ConstructorDependenciesBean) xbf.getBean("rod12");
+ assertEquals(kerry1, rod12.getSpouse1());
+ assertNull(rod12.getSpouse2());
+
+ ConstructorDependenciesBean rod13 = (ConstructorDependenciesBean) xbf.getBean("rod13");
+ assertEquals(kerry1, rod13.getSpouse1());
+ assertEquals(kerry2, rod13.getSpouse2());
+
+ ConstructorDependenciesBean rod14 = (ConstructorDependenciesBean) xbf.getBean("rod14");
+ assertEquals(kerry1, rod14.getSpouse1());
+ assertEquals(kerry2, rod14.getSpouse2());
+
+ ConstructorDependenciesBean rod15 = (ConstructorDependenciesBean) xbf.getBean("rod15");
+ assertEquals(kerry2, rod15.getSpouse1());
+ assertEquals(kerry1, rod15.getSpouse2());
+
+ ConstructorDependenciesBean rod16 = (ConstructorDependenciesBean) xbf.getBean("rod16");
+ assertEquals(kerry2, rod16.getSpouse1());
+ assertEquals(kerry1, rod16.getSpouse2());
+ assertEquals(29, rod16.getAge());
+ }
+
+ public void testConstructorArgWithSingleMatch() {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("constructor-arg.xml", getClass()));
+ File file = (File) xbf.getBean("file");
+ assertEquals(File.separator + "test", file.getPath());
+ }
+
+ public void testThrowsExceptionOnTooManyArguments() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("constructor-arg.xml", getClass()));
+ try {
+ xbf.getBean("rod7", ConstructorDependenciesBean.class);
+ fail("Should have thrown BeanCreationException");
+ }
+ catch (BeanCreationException expected) {
+ }
+ }
+
+ public void testThrowsExceptionOnAmbiguousResolution() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("constructor-arg.xml", getClass()));
+ try {
+ xbf.getBean("rod8", ConstructorDependenciesBean.class);
+ fail("Must have thrown UnsatisfiedDependencyException");
+ }
+ catch (UnsatisfiedDependencyException expected) {
+ }
+ }
+
+ public void testDependsOn() {
+ doTestDependencies("dependencies-dependsOn.xml", 1);
+ }
+
+ public void testDependsOnInInnerBean() {
+ doTestDependencies("dependencies-dependsOn-inner.xml", 4);
+ }
+
+ public void testDependenciesThroughConstructorArguments() {
+ doTestDependencies("dependencies-carg.xml", 1);
+ }
+
+ public void testDependenciesThroughConstructorArgumentAutowiring() {
+ doTestDependencies("dependencies-carg-autowire.xml", 1);
+ }
+
+ public void testDependenciesThroughConstructorArgumentsInInnerBean() {
+ doTestDependencies("dependencies-carg-inner.xml", 1);
+ }
+
+ public void testDependenciesThroughProperties() {
+ doTestDependencies("dependencies-prop.xml", 1);
+ }
+
+ public void testDependenciesThroughPropertiesWithInTheMiddle() {
+ doTestDependencies("dependencies-prop-inTheMiddle.xml", 1);
+ }
+
+ public void testDependenciesThroughPropertyAutowiringByName() {
+ doTestDependencies("dependencies-prop-autowireByName.xml", 1);
+ }
+
+ public void testDependenciesThroughPropertyAutowiringByType() {
+ doTestDependencies("dependencies-prop-autowireByType.xml", 1);
+ }
+
+ public void testDependenciesThroughPropertiesInInnerBean() {
+ doTestDependencies("dependencies-prop-inner.xml", 1);
+ }
+
+ private void doTestDependencies(String filename, int nrOfHoldingBeans) {
+ PreparingBean1.prepared = false;
+ PreparingBean1.destroyed = false;
+ PreparingBean2.prepared = false;
+ PreparingBean2.destroyed = false;
+ DependingBean.destroyCount = 0;
+ HoldingBean.destroyCount = 0;
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource(filename, getClass()));
+ xbf.preInstantiateSingletons();
+ xbf.destroySingletons();
+ assertTrue(PreparingBean1.prepared);
+ assertTrue(PreparingBean1.destroyed);
+ assertTrue(PreparingBean2.prepared);
+ assertTrue(PreparingBean2.destroyed);
+ assertEquals(nrOfHoldingBeans, DependingBean.destroyCount);
+ if (!xbf.getBeansOfType(HoldingBean.class, false, false).isEmpty()) {
+ assertEquals(nrOfHoldingBeans, HoldingBean.destroyCount);
+ }
+ }
+
+ /**
+ * When using a BeanFactory. singletons are of course not pre-instantiated.
+ * So rubbish class names in bean defs must now not be 'resolved' when the
+ * bean def is being parsed, 'cos everything on a bean def is now lazy, but
+ * must rather only be picked up when the bean is instantiated.
+ */
+ public void testClassNotFoundWithDefaultBeanClassLoader() {
+ BeanFactory factory = new XmlBeanFactory(new ClassPathResource("classNotFound.xml", getClass()));
+ // cool, no errors, so the rubbish class name in the bean def was not resolved
+ try {
+ // let's resolve the bean definition; must blow up
+ factory.getBean("classNotFound");
+ fail("Must have thrown a CannotLoadBeanClassException");
+ }
+ catch (CannotLoadBeanClassException ex) {
+ assertTrue(ex.getResourceDescription().indexOf("classNotFound.xml") != -1);
+ assertTrue(ex.getCause() instanceof ClassNotFoundException);
+ }
+ }
+
+ public void testClassNotFoundWithNoBeanClassLoader() {
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
+ reader.setBeanClassLoader(null);
+ reader.loadBeanDefinitions(new ClassPathResource("classNotFound.xml", getClass()));
+ assertEquals("WhatALotOfRubbish", bf.getBeanDefinition("classNotFound").getBeanClassName());
+ }
+
+ public void testResourceAndInputStream() throws IOException {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("resource.xml", getClass()));
+ // comes from "resourceImport.xml"
+ ResourceTestBean resource1 = (ResourceTestBean) xbf.getBean("resource1");
+ // comes from "resource.xml"
+ ResourceTestBean resource2 = (ResourceTestBean) xbf.getBean("resource2");
+
+ assertTrue(resource1.getResource() instanceof ClassPathResource);
+ StringWriter writer = new StringWriter();
+ FileCopyUtils.copy(new InputStreamReader(resource1.getResource().getInputStream()), writer);
+ assertEquals("test", writer.toString());
+ writer = new StringWriter();
+ FileCopyUtils.copy(new InputStreamReader(resource1.getInputStream()), writer);
+ assertEquals("test", writer.toString());
+ writer = new StringWriter();
+ FileCopyUtils.copy(new InputStreamReader(resource2.getResource().getInputStream()), writer);
+ assertEquals("test", writer.toString());
+ writer = new StringWriter();
+ FileCopyUtils.copy(new InputStreamReader(resource2.getInputStream()), writer);
+ assertEquals("test", writer.toString());
+ }
+
+ public void testClassPathResourceWithImport() {
+ XmlBeanFactory xbf = new XmlBeanFactory(
+ new ClassPathResource("org/springframework/beans/factory/xml/resource.xml"));
+ // comes from "resourceImport.xml"
+ xbf.getBean("resource1", ResourceTestBean.class);
+ // comes from "resource.xml"
+ xbf.getBean("resource2", ResourceTestBean.class);
+ }
+
+ public void testUrlResourceWithImport() {
+ URL url = getClass().getResource("resource.xml");
+ XmlBeanFactory xbf = new XmlBeanFactory(new UrlResource(url));
+ // comes from "resourceImport.xml"
+ xbf.getBean("resource1", ResourceTestBean.class);
+ // comes from "resource.xml"
+ xbf.getBean("resource2", ResourceTestBean.class);
+ }
+
+ public void testFileSystemResourceWithImport() {
+ String file = getClass().getResource("resource.xml").getFile();
+ XmlBeanFactory xbf = new XmlBeanFactory(new FileSystemResource(file));
+ // comes from "resourceImport.xml"
+ xbf.getBean("resource1", ResourceTestBean.class);
+ // comes from "resource.xml"
+ xbf.getBean("resource2", ResourceTestBean.class);
+ }
+
+ public void testRecursiveImport() {
+ try {
+ XmlBeanFactory xbf = new XmlBeanFactory(
+ new ClassPathResource("org/springframework/beans/factory/xml/recursiveImport.xml"));
+ fail("Should have thrown BeanDefinitionStoreException");
+ }
+ catch (BeanDefinitionStoreException ex) {
+ // expected
+ ex.printStackTrace();
+ }
+ }
+
+
+ public void testLookupOverrideMethodsWithSetterInjection() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.loadBeanDefinitions(new ClassPathResource("overrides.xml", getClass()));
+
+ testLookupOverrideMethodsWithSetterInjection(xbf, "overrideOneMethod", true);
+ // Should work identically on subclass definition, in which lookup
+ // methods are inherited
+ testLookupOverrideMethodsWithSetterInjection(xbf, "overrideInheritedMethod", true);
+
+ // Check cost of repeated construction of beans with method overrides
+ // Will pick up misuse of CGLIB
+ int howMany = 100;
+ StopWatch sw = new StopWatch();
+ sw.start("Look up " + howMany + " prototype bean instances with method overrides");
+ for (int i = 0; i < howMany; i++) {
+ testLookupOverrideMethodsWithSetterInjection(xbf, "overrideOnPrototype", false);
+ }
+ sw.stop();
+ System.out.println(sw);
+ if (!LogFactory.getLog(DefaultListableBeanFactory.class).isDebugEnabled()) {
+ assertTrue(sw.getTotalTimeMillis() < 2000);
+ }
+
+ // Now test distinct bean with swapped value in factory, to ensure the two are independent
+ OverrideOneMethod swappedOom = (OverrideOneMethod) xbf.getBean("overrideOneMethodSwappedReturnValues");
+
+ TestBean tb = swappedOom.getPrototypeDependency();
+ assertEquals("David", tb.getName());
+ tb = swappedOom.protectedOverrideSingleton();
+ assertEquals("Jenny", tb.getName());
+ }
+
+ private void testLookupOverrideMethodsWithSetterInjection(BeanFactory xbf, String beanName, boolean singleton) {
+ OverrideOneMethod oom = (OverrideOneMethod) xbf.getBean(beanName);
+
+ if (singleton) {
+ assertSame(oom, xbf.getBean(beanName));
+ }
+ else {
+ assertNotSame(oom, xbf.getBean(beanName));
+ }
+
+ TestBean jenny1 = oom.getPrototypeDependency();
+ assertEquals("Jenny", jenny1.getName());
+ TestBean jenny2 = oom.getPrototypeDependency();
+ assertEquals("Jenny", jenny2.getName());
+ assertNotSame(jenny1, jenny2);
+
+ // Check that the bean can invoke the overridden method on itself
+ // This differs from Spring's AOP support, which has a distinct notion
+ // of a "target" object, meaning that the target needs explicit knowledge
+ // of AOP proxying to invoke an advised method on itself.
+ TestBean jenny3 = oom.invokesOverridenMethodOnSelf();
+ assertEquals("Jenny", jenny3.getName());
+ assertNotSame(jenny1, jenny3);
+
+ // Now try protected method, and singleton
+ TestBean dave1 = oom.protectedOverrideSingleton();
+ assertEquals("David", dave1.getName());
+ TestBean dave2 = oom.protectedOverrideSingleton();
+ assertEquals("David", dave2.getName());
+ assertSame(dave1, dave2);
+ }
+
+ public void testReplaceMethodOverrideWithSetterInjection() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.loadBeanDefinitions(new ClassPathResource("delegationOverrides.xml", getClass()));
+
+ OverrideOneMethod oom = (OverrideOneMethod) xbf.getBean("overrideOneMethod");
+
+ // Same contract as for overrides.xml
+ TestBean jenny1 = oom.getPrototypeDependency();
+ assertEquals("Jenny", jenny1.getName());
+ TestBean jenny2 = oom.getPrototypeDependency();
+ assertEquals("Jenny", jenny2.getName());
+ assertNotSame(jenny1, jenny2);
+
+ TestBean notJenny = oom.getPrototypeDependency("someParam");
+ assertTrue(!"Jenny".equals(notJenny.getName()));
+
+ // Now try protected method, and singleton
+ TestBean dave1 = oom.protectedOverrideSingleton();
+ assertEquals("David", dave1.getName());
+ TestBean dave2 = oom.protectedOverrideSingleton();
+ assertEquals("David", dave2.getName());
+ assertSame(dave1, dave2);
+
+ // Check unadvised behaviour
+ String str = "woierowijeiowiej";
+ assertEquals(str, oom.echo(str));
+
+ // Now test replace
+ String s = "this is not a palindrome";
+ String reverse = new StringBuffer(s).reverse().toString();
+ assertEquals("Should have overridden to reverse, not echo", reverse, oom.replaceMe(s));
+
+ assertEquals("Should have overridden no-arg overloaded replaceMe method to return fixed value",
+ FixedMethodReplacer.VALUE, oom.replaceMe());
+
+ OverrideOneMethodSubclass ooms = (OverrideOneMethodSubclass) xbf.getBean("replaceVoidMethod");
+ DoSomethingReplacer dos = (DoSomethingReplacer) xbf.getBean("doSomethingReplacer");
+ assertEquals(null, dos.lastArg);
+ String s1 = "";
+ String s2 = "foo bar black sheep";
+ ooms.doSomething(s1);
+ assertEquals(s1, dos.lastArg);
+ ooms.doSomething(s2);
+ assertEquals(s2, dos.lastArg);
+ }
+
+ public void testLookupOverrideOneMethodWithConstructorInjection() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.loadBeanDefinitions(new ClassPathResource("constructorOverrides.xml", getClass()));
+
+ ConstructorInjectedOverrides cio = (ConstructorInjectedOverrides) xbf.getBean("constructorOverrides");
+
+ // Check that the setter was invoked...
+ // We should be able to combine Constructor and
+ // Setter Injection
+ assertEquals("Setter string was set", "from property element", cio.getSetterString());
+
+ // Jenny is a singleton
+ TestBean jenny = (TestBean) xbf.getBean("jenny");
+ assertSame(jenny, cio.getTestBean());
+ assertSame(jenny, cio.getTestBean());
+ FactoryMethods fm1 = cio.createFactoryMethods();
+ FactoryMethods fm2 = cio.createFactoryMethods();
+ assertNotSame("FactoryMethods reference is to a prototype", fm1, fm2);
+ assertSame("The two prototypes hold the same singleton reference",
+ fm1.getTestBean(), fm2.getTestBean());
+ }
+
+ public void testRejectsOverrideOfBogusMethodName() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ try {
+ reader.loadBeanDefinitions(new ClassPathResource("invalidOverridesNoSuchMethod.xml", getClass()));
+ xbf.getBean("constructorOverrides");
+ fail("Shouldn't allow override of bogus method");
+ }
+ catch (BeanDefinitionStoreException ex) {
+ // Check that the bogus method name was included in the error message
+ assertTrue("Bogus method name correctly reported", ex.getMessage().indexOf("bogusMethod") != -1);
+ }
+ }
+
+ /**
+ * Assert the presence of this bug until we resolve it.
+ */
+ public void testSerializabilityOfMethodReplacer() throws Exception {
+ try {
+ BUGtestSerializableMethodReplacerAndSuperclass();
+ fail();
+ }
+ catch (AssertionFailedError ex) {
+ System.err.println("****** SPR-356: Objects with MethodReplace overrides are not serializable");
+ }
+ }
+
+ public void BUGtestSerializableMethodReplacerAndSuperclass() throws IOException, ClassNotFoundException {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.loadBeanDefinitions(new ClassPathResource("delegationOverrides.xml", getClass()));
+ SerializableMethodReplacerCandidate s = (SerializableMethodReplacerCandidate) xbf.getBean("serializableReplacer");
+ String forwards = "this is forwards";
+ String backwards = new StringBuffer(forwards).reverse().toString();
+ assertEquals(backwards, s.replaceMe(forwards));
+ assertTrue(SerializationTestUtils.isSerializable(s));
+ s = (SerializableMethodReplacerCandidate) SerializationTestUtils.serializeAndDeserialize(s);
+ assertEquals("Method replace still works after serialization and deserialization", backwards, s.replaceMe(forwards));
+ }
+
+ public void testInnerBeanInheritsScopeFromConcreteChildDefinition() {
+ DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
+ reader.loadBeanDefinitions(new ClassPathResource("overrides.xml", getClass()));
+ TestBean jenny = (TestBean) xbf.getBean("jennyChild");
+ assertEquals(1, jenny.getFriends().size());
+ assertTrue(jenny.getFriends().iterator().next() instanceof TestBean);
+ }
+
+ public void testConstructorArgWithSingleSimpleTypeMatch() {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("constructor-arg.xml", getClass()));
+
+ SingleSimpleTypeConstructorBean bean = (SingleSimpleTypeConstructorBean) xbf.getBean("beanWithBoolean");
+ assertTrue(bean.isSingleBoolean());
+
+ SingleSimpleTypeConstructorBean bean2 = (SingleSimpleTypeConstructorBean) xbf.getBean("beanWithBoolean2");
+ assertTrue(bean2.isSingleBoolean());
+ }
+
+ public void testConstructorArgWithDoubleSimpleTypeMatch() {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("constructor-arg.xml", getClass()));
+
+ SingleSimpleTypeConstructorBean bean = (SingleSimpleTypeConstructorBean) xbf.getBean("beanWithBooleanAndString");
+ assertTrue(bean.isSecondBoolean());
+ assertEquals("A String", bean.getTestString());
+
+ SingleSimpleTypeConstructorBean bean2 = (SingleSimpleTypeConstructorBean) xbf.getBean("beanWithBooleanAndString2");
+ assertTrue(bean2.isSecondBoolean());
+ assertEquals("A String", bean2.getTestString());
+ }
+
+ public void testDoubleBooleanAutowire() {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("constructor-arg.xml", getClass()));
+ DoubleBooleanConstructorBean bean = (DoubleBooleanConstructorBean) xbf.getBean("beanWithDoubleBoolean");
+ assertEquals(Boolean.TRUE, bean.boolean1);
+ assertEquals(Boolean.FALSE, bean.boolean2);
+ }
+
+ public void testDoubleBooleanAutowireWithIndex() {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("constructor-arg.xml", getClass()));
+ DoubleBooleanConstructorBean bean = (DoubleBooleanConstructorBean) xbf.getBean("beanWithDoubleBooleanAndIndex");
+ assertEquals(Boolean.FALSE, bean.boolean1);
+ assertEquals(Boolean.TRUE, bean.boolean2);
+ }
+
+ public void testWithDuplicateName() throws Exception {
+ try {
+ new XmlBeanFactory(new ClassPathResource("testWithDuplicateNames.xml", getClass()));
+ fail("Duplicate name not detected");
+ }
+ catch (BeansException ex) {
+ assertTrue(ex.getMessage().indexOf("Bean name 'foo'") > -1);
+ }
+ }
+
+ public void testWithDuplicateNameInAlias() throws Exception {
+ try {
+ new XmlBeanFactory(new ClassPathResource("testWithDuplicateNameInAlias.xml", getClass()));
+ fail("Duplicate name not detected");
+ }
+ catch (BeansException e) {
+ assertTrue(e.getMessage().indexOf("Bean name 'foo'") > -1);
+ }
+ }
+
+ public static class DoSomethingReplacer implements MethodReplacer {
+
+ public Object lastArg;
+
+ public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
+ assertEquals(1, args.length);
+ assertEquals("doSomething", method.getName());
+ lastArg = args[0];
+ return null;
+ }
+ }
+
+
+ public static class BadInitializer {
+
+ /** Init method */
+ public void init2() throws ServletException {
+ throw new ServletException();
+ }
+ }
+
+
+ public static class DoubleInitializer {
+
+ private int num;
+
+ public int getNum() {
+ return num;
+ }
+
+ public void setNum(int i) {
+ num = i;
+ }
+
+ /** Init method */
+ public void init() {
+ this.num *= 2;
+ }
+ }
+
+
+ public static class InitAndIB implements InitializingBean, DisposableBean {
+
+ public static boolean constructed;
+
+ public boolean afterPropertiesSetInvoked, initMethodInvoked, destroyed, customDestroyed;
+
+ public InitAndIB() {
+ constructed = true;
+ }
+
+ public void afterPropertiesSet() {
+ if (this.initMethodInvoked) {
+ fail();
+ }
+ if (this.afterPropertiesSetInvoked) {
+ throw new IllegalStateException("Already initialized");
+ }
+ this.afterPropertiesSetInvoked = true;
+ }
+
+ /** Init method */
+ public void customInit() throws ServletException {
+ if (!this.afterPropertiesSetInvoked) {
+ fail();
+ }
+ if (this.initMethodInvoked) {
+ throw new IllegalStateException("Already customInitialized");
+ }
+ this.initMethodInvoked = true;
+ }
+
+ public void destroy() {
+ if (this.customDestroyed) {
+ fail();
+ }
+ if (this.destroyed) {
+ throw new IllegalStateException("Already destroyed");
+ }
+ this.destroyed = true;
+ }
+
+ public void customDestroy() {
+ if (!this.destroyed) {
+ fail();
+ }
+ if (this.customDestroyed) {
+ throw new IllegalStateException("Already customDestroyed");
+ }
+ this.customDestroyed = true;
+ }
+ }
+
+
+ public static class PreparingBean1 implements DisposableBean {
+
+ public static boolean prepared = false;
+
+ public static boolean destroyed = false;
+
+ public PreparingBean1() {
+ prepared = true;
+ }
+
+ public void destroy() {
+ destroyed = true;
+ }
+ }
+
+
+ public static class PreparingBean2 implements DisposableBean {
+
+ public static boolean prepared = false;
+
+ public static boolean destroyed = false;
+
+ public PreparingBean2() {
+ prepared = true;
+ }
+
+ public void destroy() {
+ destroyed = true;
+ }
+ }
+
+
+ public static class DependingBean implements InitializingBean, DisposableBean {
+
+ public static int destroyCount = 0;
+
+ public boolean destroyed = false;
+
+ public DependingBean() {
+ }
+
+ public DependingBean(PreparingBean1 bean1, PreparingBean2 bean2) {
+ }
+
+ public void setBean1(PreparingBean1 bean1) {
+ }
+
+ public void setBean2(PreparingBean2 bean2) {
+ }
+
+ public void setInTheMiddleBean(InTheMiddleBean bean) {
+ }
+
+ public void afterPropertiesSet() {
+ if (!(PreparingBean1.prepared && PreparingBean2.prepared)) {
+ throw new IllegalStateException("Need prepared PreparingBeans!");
+ }
+ }
+
+ public void destroy() {
+ if (PreparingBean1.destroyed || PreparingBean2.destroyed) {
+ throw new IllegalStateException("Should not be destroyed after PreparingBeans");
+ }
+ destroyed = true;
+ destroyCount++;
+ }
+ }
+
+
+ public static class InTheMiddleBean {
+
+ public void setBean1(PreparingBean1 bean1) {
+ }
+
+ public void setBean2(PreparingBean2 bean2) {
+ }
+ }
+
+
+ public static class HoldingBean implements DisposableBean {
+
+ public static int destroyCount = 0;
+
+ private DependingBean dependingBean;
+
+ public boolean destroyed = false;
+
+ public void setDependingBean(DependingBean dependingBean) {
+ this.dependingBean = dependingBean;
+ }
+
+ public void destroy() {
+ if (this.dependingBean.destroyed) {
+ throw new IllegalStateException("Should not be destroyed after DependingBean");
+ }
+ this.destroyed = true;
+ destroyCount++;
+ }
+ }
+
+
+ public static class DoubleBooleanConstructorBean {
+
+ private Boolean boolean1;
+ private Boolean boolean2;
+
+ public DoubleBooleanConstructorBean(Boolean b1, Boolean b2) {
+ this.boolean1 = b1;
+ this.boolean2 = b2;
+ }
+ }
+
+
+ public static class WrappingPostProcessor implements BeanPostProcessor {
+
+ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+ return bean;
+ }
+
+ public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+ ProxyFactory pf = new ProxyFactory(bean);
+ return pf.getProxy();
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/XmlListableBeanFactoryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/XmlListableBeanFactoryTests.java
new file mode 100644
index 00000000000..321a8f2e6e1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/XmlListableBeanFactoryTests.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.AbstractListableBeanFactoryTests;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.DummyFactory;
+import org.springframework.beans.factory.LifecycleBean;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Juergen Hoeller
+ * @since 09.11.2003
+ */
+public class XmlListableBeanFactoryTests extends AbstractListableBeanFactoryTests {
+
+ private DefaultListableBeanFactory parent;
+
+ private XmlBeanFactory factory;
+
+ protected void setUp() {
+ parent = new DefaultListableBeanFactory();
+ Map m = new HashMap();
+ m.put("name", "Albert");
+ parent.registerBeanDefinition("father",
+ new RootBeanDefinition(TestBean.class, new MutablePropertyValues(m)));
+ m = new HashMap();
+ m.put("name", "Roderick");
+ parent.registerBeanDefinition("rod",
+ new RootBeanDefinition(TestBean.class, new MutablePropertyValues(m)));
+
+ this.factory = new XmlBeanFactory(new ClassPathResource("test.xml", getClass()), parent);
+ this.factory.addBeanPostProcessor(new BeanPostProcessor() {
+ public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
+ if (bean instanceof TestBean) {
+ ((TestBean) bean).setPostProcessed(true);
+ }
+ if (bean instanceof DummyFactory) {
+ ((DummyFactory) bean).setPostProcessed(true);
+ }
+ return bean;
+ }
+ public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
+ return bean;
+ }
+ });
+ this.factory.addBeanPostProcessor(new LifecycleBean.PostProcessor());
+ this.factory.addBeanPostProcessor(new ProtectedLifecycleBean.PostProcessor());
+ //this.factory.preInstantiateSingletons();
+ }
+
+ protected BeanFactory getBeanFactory() {
+ return factory;
+ }
+
+ public void testCount() {
+ assertCount(24);
+ }
+
+ public void testTestBeanCount() {
+ assertTestBeanCount(13);
+ }
+
+ public void testLifecycleMethods() throws Exception {
+ LifecycleBean bean = (LifecycleBean) getBeanFactory().getBean("lifecycle");
+ bean.businessMethod();
+ }
+
+ public void testProtectedLifecycleMethods() throws Exception {
+ ProtectedLifecycleBean bean = (ProtectedLifecycleBean) getBeanFactory().getBean("protectedLifecycle");
+ bean.businessMethod();
+ }
+
+ public void testDescriptionButNoProperties() throws Exception {
+ TestBean validEmpty = (TestBean) getBeanFactory().getBean("validEmptyWithDescription");
+ assertEquals(0, validEmpty.getAge());
+ }
+
+ /**
+ * Test that properties with name as well as id creating an alias up front.
+ */
+ public void testAutoAliasing() throws Exception {
+ List beanNames = Arrays.asList(getListableBeanFactory().getBeanDefinitionNames());
+
+ TestBean tb1 = (TestBean) getBeanFactory().getBean("aliased");
+ TestBean alias1 = (TestBean) getBeanFactory().getBean("myalias");
+ assertTrue(tb1 == alias1);
+ List tb1Aliases = Arrays.asList(getBeanFactory().getAliases("aliased"));
+ assertEquals(2, tb1Aliases.size());
+ assertTrue(tb1Aliases.contains("myalias"));
+ assertTrue(tb1Aliases.contains("youralias"));
+ assertTrue(beanNames.contains("aliased"));
+ assertFalse(beanNames.contains("myalias"));
+ assertFalse(beanNames.contains("youralias"));
+
+ TestBean tb2 = (TestBean) getBeanFactory().getBean("multiAliased");
+ TestBean alias2 = (TestBean) getBeanFactory().getBean("alias1");
+ TestBean alias3 = (TestBean) getBeanFactory().getBean("alias2");
+ TestBean alias3a = (TestBean) getBeanFactory().getBean("alias3");
+ TestBean alias3b = (TestBean) getBeanFactory().getBean("alias4");
+ assertTrue(tb2 == alias2);
+ assertTrue(tb2 == alias3);
+ assertTrue(tb2 == alias3a);
+ assertTrue(tb2 == alias3b);
+
+ List tb2Aliases = Arrays.asList(getBeanFactory().getAliases("multiAliased"));
+ assertEquals(4, tb2Aliases.size());
+ assertTrue(tb2Aliases.contains("alias1"));
+ assertTrue(tb2Aliases.contains("alias2"));
+ assertTrue(tb2Aliases.contains("alias3"));
+ assertTrue(tb2Aliases.contains("alias4"));
+ assertTrue(beanNames.contains("multiAliased"));
+ assertFalse(beanNames.contains("alias1"));
+ assertFalse(beanNames.contains("alias2"));
+ assertFalse(beanNames.contains("alias3"));
+ assertFalse(beanNames.contains("alias4"));
+
+ TestBean tb3 = (TestBean) getBeanFactory().getBean("aliasWithoutId1");
+ TestBean alias4 = (TestBean) getBeanFactory().getBean("aliasWithoutId2");
+ TestBean alias5 = (TestBean) getBeanFactory().getBean("aliasWithoutId3");
+ assertTrue(tb3 == alias4);
+ assertTrue(tb3 == alias5);
+ List tb3Aliases = Arrays.asList(getBeanFactory().getAliases("aliasWithoutId1"));
+ assertEquals(2, tb3Aliases.size());
+ assertTrue(tb3Aliases.contains("aliasWithoutId2"));
+ assertTrue(tb3Aliases.contains("aliasWithoutId3"));
+ assertTrue(beanNames.contains("aliasWithoutId1"));
+ assertFalse(beanNames.contains("aliasWithoutId2"));
+ assertFalse(beanNames.contains("aliasWithoutId3"));
+
+ TestBean tb4 = (TestBean) getBeanFactory().getBean(TestBean.class.getName() + "#0");
+ assertEquals(null, tb4.getName());
+
+ Map drs = getListableBeanFactory().getBeansOfType(DummyReferencer.class, false, false);
+ assertEquals(5, drs.size());
+ assertTrue(drs.containsKey(DummyReferencer.class.getName() + "#0"));
+ assertTrue(drs.containsKey(DummyReferencer.class.getName() + "#1"));
+ assertTrue(drs.containsKey(DummyReferencer.class.getName() + "#2"));
+ }
+
+ public void testFactoryNesting() {
+ ITestBean father = (ITestBean) getBeanFactory().getBean("father");
+ assertTrue("Bean from root context", father != null);
+
+ TestBean rod = (TestBean) getBeanFactory().getBean("rod");
+ assertTrue("Bean from child context", "Rod".equals(rod.getName()));
+ assertTrue("Bean has external reference", rod.getSpouse() == father);
+
+ rod = (TestBean) parent.getBean("rod");
+ assertTrue("Bean from root context", "Roderick".equals(rod.getName()));
+ }
+
+ public void testFactoryReferences() {
+ DummyFactory factory = (DummyFactory) getBeanFactory().getBean("&singletonFactory");
+
+ DummyReferencer ref = (DummyReferencer) getBeanFactory().getBean("factoryReferencer");
+ assertTrue(ref.getTestBean1() == ref.getTestBean2());
+ assertTrue(ref.getDummyFactory() == factory);
+
+ DummyReferencer ref2 = (DummyReferencer) getBeanFactory().getBean("factoryReferencerWithConstructor");
+ assertTrue(ref2.getTestBean1() == ref2.getTestBean2());
+ assertTrue(ref2.getDummyFactory() == factory);
+ }
+
+ public void testPrototypeReferences() {
+ // check that not broken by circular reference resolution mechanism
+ DummyReferencer ref1 = (DummyReferencer) getBeanFactory().getBean("prototypeReferencer");
+ assertTrue("Not referencing same bean twice", ref1.getTestBean1() != ref1.getTestBean2());
+ DummyReferencer ref2 = (DummyReferencer) getBeanFactory().getBean("prototypeReferencer");
+ assertTrue("Not the same referencer", ref1 != ref2);
+ assertTrue("Not referencing same bean twice", ref2.getTestBean1() != ref2.getTestBean2());
+ assertTrue("Not referencing same bean twice", ref1.getTestBean1() != ref2.getTestBean1());
+ assertTrue("Not referencing same bean twice", ref1.getTestBean2() != ref2.getTestBean2());
+ assertTrue("Not referencing same bean twice", ref1.getTestBean1() != ref2.getTestBean2());
+ }
+
+ public void testBeanPostProcessor() throws Exception {
+ TestBean kerry = (TestBean) getBeanFactory().getBean("kerry");
+ TestBean kathy = (TestBean) getBeanFactory().getBean("kathy");
+ DummyFactory factory = (DummyFactory) getBeanFactory().getBean("&singletonFactory");
+ TestBean factoryCreated = (TestBean) getBeanFactory().getBean("singletonFactory");
+ assertTrue(kerry.isPostProcessed());
+ assertTrue(kathy.isPostProcessed());
+ assertTrue(factory.isPostProcessed());
+ assertTrue(factoryCreated.isPostProcessed());
+ }
+
+ public void testEmptyValues() {
+ TestBean rod = (TestBean) getBeanFactory().getBean("rod");
+ TestBean kerry = (TestBean) getBeanFactory().getBean("kerry");
+ assertTrue("Touchy is empty", "".equals(rod.getTouchy()));
+ assertTrue("Touchy is empty", "".equals(kerry.getTouchy()));
+ }
+
+ public void testCommentsAndCdataInValue() {
+ TestBean bean = (TestBean) getBeanFactory().getBean("commentsInValue");
+ assertEquals("Failed to handle comments and CDATA properly", "this is a ", bean.getName());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/autowire-constructor-with-exclusion.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/autowire-constructor-with-exclusion.xml
new file mode 100644
index 00000000000..5952fa0c540
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/autowire-constructor-with-exclusion.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+ name=props1
+
+
+
+
+
+ name=props2
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/autowire-with-exclusion.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/autowire-with-exclusion.xml
new file mode 100644
index 00000000000..041092cdd92
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/autowire-with-exclusion.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+ name=props1
+
+
+
+
+
+ name=props2
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/autowire-with-inclusion.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/autowire-with-inclusion.xml
new file mode 100644
index 00000000000..271e66f5703
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/autowire-with-inclusion.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+ name=props1
+
+
+
+
+
+ name=props2
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/autowire-with-selective-inclusion.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/autowire-with-selective-inclusion.xml
new file mode 100644
index 00000000000..c49f3680e8c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/autowire-with-selective-inclusion.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+ name=props1
+
+
+
+
+
+ name=props2
+
+
+
+
+
+ name=someProps
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/autowire.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/autowire.xml
new file mode 100644
index 00000000000..0518c7c8c0e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/autowire.xml
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /org/springframework/beans/factory/xml/collections.xml
+
+
+
+
+
+
+ /org/springframework/beans/factory/xml/constructor-arg.xml
+ /org/springframework/beans/factory/xml/initializers.xml
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/beanEvents.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/beanEvents.xml
new file mode 100644
index 00000000000..110eb1ebaff
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/beanEvents.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/beanEventsImported.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/beanEventsImported.xml
new file mode 100644
index 00000000000..bdfc3c4c31e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/beanEventsImported.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/beanNameGeneration.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/beanNameGeneration.xml
new file mode 100644
index 00000000000..813049d1a59
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/beanNameGeneration.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/child.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/child.xml
new file mode 100644
index 00000000000..654e76e7fb5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/child.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+ override
+
+
+
+
+ override
+
+
+
+
+ override
+
+
+
+
+ prototypeOverridesInheritedSingleton
+
+
+
+
+ prototype-override
+
+
+
+
+ prototype-override
+
+
+
+
+ overrideParentBean
+
+
+
+
+
+
+ myname
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/classNotFound.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/classNotFound.xml
new file mode 100644
index 00000000000..58738edd74f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/classNotFound.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/collectionMerging.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/collectionMerging.xml
new file mode 100644
index 00000000000..0bd9225e535
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/collectionMerging.xml
@@ -0,0 +1,205 @@
+
+
+
+
+
+
+
+
+ Rob Harrop
+ Rod Johnson
+
+
+
+
+
+
+
+ Juergen Hoeller
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Rob Harrop
+
+
+
+
+
+
+
+ Sally Greenwood
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Sall
+ Kerry
+
+
+
+
+
+
+
+ Eva
+ Sally
+
+
+
+
+
+
+
+
+ Rob Harrop
+ Rod Johnson
+
+
+
+
+
+
+
+ Juergen Hoeller
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Rob Harrop
+
+
+
+
+
+
+
+ Sally Greenwood
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Sall
+ Kerry
+
+
+
+
+
+
+
+ Eva
+ Sally
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/collections.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/collections.xml
new file mode 100644
index 00000000000..c0dc059c7b7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/collections.xml
@@ -0,0 +1,376 @@
+
+
+
+
+ Jenny
+ 30
+
+
+
+
+
+
+
+
+ Simple bean, without any collections.
+
+
+ The name of the user
+ David
+
+ 27
+
+
+
+ Rod
+ 32
+
+ List of Rod's friends
+
+
+
+
+
+
+
+
+ Jenny
+ 30
+
+
+
+
+
+
+
+ David
+ 27
+
+
+
+ Rod
+ 32
+
+
+
+
+
+
+
+
+
+
+ loner
+ 26
+
+
+ My List
+
+
+
+
+
+
+
+
+
+ literal
+
+
+
+
+
+
+
+
+
+
+ literal
+
+
+
+
+
+
+
+
+ verbose
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ bar
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ bar
+ TWO
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ one
+
+
+
+
+
+
+
+
+ java.lang.String
+ java.lang.Exception
+
+
+
+
+
+
+
+ 0
+ 1
+ 2
+
+
+
+
+
+
+
+ bar
+ jenny
+
+
+
+ java.util.LinkedList
+
+
+
+
+
+
+ bar
+ jenny
+
+
+
+ java.util.LinkedList
+
+
+ true
+
+
+
+
+
+
+ bar
+ jenny
+
+
+
+ java.util.TreeSet
+
+
+
+
+
+
+ bar
+ jenny
+
+
+
+ java.util.TreeSet
+
+
+ true
+
+
+
+
+
+
+ bar
+ jenny
+
+
+
+ java.util.TreeMap
+
+
+
+
+
+
+ bar
+ jenny
+
+
+
+ java.util.TreeMap
+
+
+ true
+
+
+
+
+
+
+ My Map
+
+
+
+
+
+
+
+
+
+
+ My Set
+ NEVER
+ COMMIT
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/collectionsWithDefaultTypes.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/collectionsWithDefaultTypes.xml
new file mode 100644
index 00000000000..584063fde10
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/collectionsWithDefaultTypes.xml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+
+
+
+
+ 1
+ 2
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+ true
+
+
+
+ 2
+
+ false
+
+
+
+ 3
+
+ false
+
+
+
+ 4
+
+ true
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/complexFactoryCircle.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/complexFactoryCircle.xml
new file mode 100644
index 00000000000..c99a803abd8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/complexFactoryCircle.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PROPAGATION_REQUIRED
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PROPAGATION_REQUIRED
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/constructor-arg.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/constructor-arg.xml
new file mode 100644
index 00000000000..2221bdbfca9
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/constructor-arg.xml
@@ -0,0 +1,166 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ wife
+
+
+
+
+
+
+
+ wife
+
+
+
+
+ magic int value: 99 is the number of aliens who can dance on the tip of pin
+
+ 99
+
+
+ myname
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 99
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 29
+
+
+
+
+ Kerry1
+
+
+ 33
+
+
+
+
+
+ Kerry2
+
+
+ 32
+
+
+
+
+
+
+ /test
+
+
+
+
+
+
+
+
+
+
+
+ true
+ A String
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+ true
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/constructorOverrides.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/constructorOverrides.xml
new file mode 100644
index 00000000000..ea061046ce3
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/constructorOverrides.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+ from property element
+
+
+
+
+
+
+
+ Jenny
+ 30
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/default-autowire.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/default-autowire.xml
new file mode 100644
index 00000000000..0094234b090
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/default-autowire.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Kerry
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/default-lazy-init.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/default-lazy-init.xml
new file mode 100644
index 00000000000..5021766b1c0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/default-lazy-init.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/defaultLifecycleMethods.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/defaultLifecycleMethods.xml
new file mode 100644
index 00000000000..635df1adc85
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/defaultLifecycleMethods.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/delegationOverrides.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/delegationOverrides.xml
new file mode 100644
index 00000000000..6c85f27bb73
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/delegationOverrides.xml
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ String
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ String
+
+
+
+
+
+ Jenny
+ 30
+
+
+
+
+
+
+
+
+ Simple bean, without any collections.
+
+
+ The name of the user
+ David
+
+ 27
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-carg-autowire.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-carg-autowire.xml
new file mode 100644
index 00000000000..b05465fec7d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-carg-autowire.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-carg-inner.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-carg-inner.xml
new file mode 100644
index 00000000000..e8754f4c878
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-carg-inner.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-carg.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-carg.xml
new file mode 100644
index 00000000000..89b6f142db5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-carg.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-dependsOn-inner.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-dependsOn-inner.xml
new file mode 100644
index 00000000000..cffa6d766d1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-dependsOn-inner.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-dependsOn.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-dependsOn.xml
new file mode 100644
index 00000000000..dd06299f4c3
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-dependsOn.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-prop-autowireByName.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-prop-autowireByName.xml
new file mode 100644
index 00000000000..a51b221ec53
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-prop-autowireByName.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-prop-autowireByType.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-prop-autowireByType.xml
new file mode 100644
index 00000000000..cfc11301c77
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-prop-autowireByType.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-prop-inTheMiddle.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-prop-inTheMiddle.xml
new file mode 100644
index 00000000000..92968cf72b4
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-prop-inTheMiddle.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-prop-inner.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-prop-inner.xml
new file mode 100644
index 00000000000..d4100fbd1e7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-prop-inner.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-prop.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-prop.xml
new file mode 100644
index 00000000000..67f73e29441
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependencies-prop.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependenciesMaterializeThis.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependenciesMaterializeThis.xml
new file mode 100644
index 00000000000..ac060a882b2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/dependenciesMaterializeThis.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ boPrototype
+
+
+
+
+
+ org.springframework.beans.factory.xml.DummyBo
+
+
+ PROPAGATION_REQUIRED
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/factory-methods.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/factory-methods.xml
new file mode 100644
index 00000000000..41cdfe5e360
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/factory-methods.xml
@@ -0,0 +1,145 @@
+
+
+
+
+
+
+
+ setterString
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ setterString
+
+
+
+
+ 27
+ gotcha
+
+
+
+
+ 27
+
+
+
+
+
+ 27
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ setterString
+
+
+
+
+ testBeanOnlyPrototypeDISetterString
+
+
+
+ 27
+ gotcha
+
+
+
+
+
+ 27
+ gotcha
+ bogus
+
+
+
+
+
+ Juergen
+
+
+
+
+
+
+
+ Rod
+ 33
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ instanceFactory
+
+
+
+
+
+ true
+
+
+ someuser
+ somepw
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/factoryCircle.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/factoryCircle.xml
new file mode 100644
index 00000000000..f94371ee0c7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/factoryCircle.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/ignoreDefaultLifecycleMethods.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/ignoreDefaultLifecycleMethods.xml
new file mode 100644
index 00000000000..a10029da323
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/ignoreDefaultLifecycleMethods.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/initializers.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/initializers.xml
new file mode 100644
index 00000000000..1a6eb553328
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/initializers.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+ 7
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/invalid-factory.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/invalid-factory.xml
new file mode 100644
index 00000000000..4822140c206
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/invalid-factory.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+ false
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/invalid.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/invalid.xml
new file mode 100644
index 00000000000..57151714d49
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/invalid.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+ Jenny
+ 30
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/invalidOverridesNoSuchMethod.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/invalidOverridesNoSuchMethod.xml
new file mode 100644
index 00000000000..e8b85a509af
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/invalidOverridesNoSuchMethod.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Jenny
+ 30
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/invalidPerSchema.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/invalidPerSchema.xml
new file mode 100644
index 00000000000..430c8adc7e4
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/invalidPerSchema.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/local-collections-using-XSD.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/local-collections-using-XSD.xml
new file mode 100644
index 00000000000..da6d7405eb3
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/local-collections-using-XSD.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/no-such-factory-method.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/no-such-factory-method.xml
new file mode 100644
index 00000000000..251459cf61a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/no-such-factory-method.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+ setterString
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/overloadOverrides.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/overloadOverrides.xml
new file mode 100644
index 00000000000..4f2212256cf
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/overloadOverrides.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ interceptor
+
+
+
+ Jenny
+ 30
+
+
+
+
+ autoProxiedOverload
+ true
+ interceptor
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/overrides.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/overrides.xml
new file mode 100644
index 00000000000..bf0849bc98c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/overrides.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Jenny
+ 30
+
+
+
+
+
+
+
+
+
+ Jenny
+ 30
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Simple bean, without any collections.
+
+
+ The name of the user
+ David
+
+ 27
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/parent.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/parent.xml
new file mode 100644
index 00000000000..6f5675fffd6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/parent.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+ parent
+ 1
+
+
+
+ parent
+ 1
+
+
+
+ parent
+ 2
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/recursiveImport.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/recursiveImport.xml
new file mode 100644
index 00000000000..07088881edf
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/recursiveImport.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/reftypes.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/reftypes.xml
new file mode 100644
index 00000000000..c8adc19bb3d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/reftypes.xml
@@ -0,0 +1,186 @@
+
+
+
+
+
+ Jenny
+ 30
+
+
+
+
+
+
+
+
+
+
+ Andrew
+ 36
+
+
+
+
+
+
+
+
+
+
+ Georgia
+ 33
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ outer
+ 0
+
+
+
+ hasInner
+ 5
+
+
+ inner1
+ 6
+
+
+
+
+
+ inner2
+ 7
+
+
+
+ inner5
+ 6
+
+
+
+
+
+
+
+ inner3
+ 8
+
+
+
+
+ inner4
+ 9
+
+
+
+
+
+
+
+
+
+ inner1
+ 6
+
+
+
+
+
+ hasInner
+ 5
+
+
+ inner1
+ 6
+
+
+
+
+
+ inner2
+ 7
+
+
+
+ inner5
+ 6
+
+
+
+
+
+
+
+
+
+
+ inner3
+ 8
+
+
+
+
+
+ inner4
+ 9
+
+
+
+
+
+
+
+
+
+ inner1
+ 6
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/resource.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/resource.xml
new file mode 100644
index 00000000000..0bf9399d30f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/resource.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+ classpath:org/springframework/beans/factory/xml/test.properties
+
+
+ classpath:org/springframework/beans/factory/xml/test.properties
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/resourceImport.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/resourceImport.xml
new file mode 100644
index 00000000000..e5515885eff
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/resourceImport.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+ classpath:org/springframework/beans/factory/xml/test.properties
+
+
+ classpath:org/springframework/beans/factory/xml/test.properties
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/satisfiedAllDependencyCheck.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/satisfiedAllDependencyCheck.xml
new file mode 100644
index 00000000000..4b315b7582d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/satisfiedAllDependencyCheck.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+ 33
+ Rod
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/satisfiedObjectDependencyCheck.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/satisfiedObjectDependencyCheck.xml
new file mode 100644
index 00000000000..8c1d0d3f37c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/satisfiedObjectDependencyCheck.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/satisfiedSimpleDependencyCheck.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/satisfiedSimpleDependencyCheck.xml
new file mode 100644
index 00000000000..92981195029
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/satisfiedSimpleDependencyCheck.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ 33
+ Rod
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/schemaValidated.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/schemaValidated.xml
new file mode 100644
index 00000000000..3a45ffec354
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/schemaValidated.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/shortcutTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/shortcutTests.xml
new file mode 100644
index 00000000000..2d5762942ff
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/shortcutTests.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/shortcutWithErrorsTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/shortcutWithErrorsTests.xml
new file mode 100644
index 00000000000..d82595bac7a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/shortcutWithErrorsTests.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/CustomNamespaceHandlerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/CustomNamespaceHandlerTests.java
new file mode 100644
index 00000000000..0a9552c9a66
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/CustomNamespaceHandlerTests.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml.support;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import junit.framework.TestCase;
+import org.xml.sax.InputSource;
+
+import org.springframework.aop.Advisor;
+import org.springframework.aop.framework.Advised;
+import org.springframework.aop.interceptor.DebugInterceptor;
+import org.springframework.aop.interceptor.NopInterceptor;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver;
+import org.springframework.beans.factory.xml.NamespaceHandlerResolver;
+import org.springframework.beans.factory.xml.PluggableSchemaResolver;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+/**
+ * @author Rob Harrop
+ * @author Rick Evans
+ */
+public final class CustomNamespaceHandlerTests extends TestCase {
+
+ private DefaultListableBeanFactory beanFactory;
+
+
+ protected void setUp() throws Exception {
+ String location = "org/springframework/beans/factory/xml/support/customNamespace.properties";
+ NamespaceHandlerResolver resolver = new DefaultNamespaceHandlerResolver(getClass().getClassLoader(), location);
+ this.beanFactory = new DefaultListableBeanFactory();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this.beanFactory);
+ reader.setNamespaceHandlerResolver(resolver);
+ reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_XSD);
+ reader.setEntityResolver(new DummySchemaResolver());
+ reader.loadBeanDefinitions(getResource());
+ }
+
+
+ public void testSimpleParser() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("testBean");
+ assetTestBean(bean);
+ }
+
+ public void testSimpleDecorator() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("customisedTestBean");
+ assetTestBean(bean);
+ }
+
+ public void testProxyingDecorator() throws Exception {
+ ITestBean bean = (ITestBean) this.beanFactory.getBean("debuggingTestBean");
+ assetTestBean(bean);
+ assertTrue(AopUtils.isAopProxy(bean));
+ Advisor[] advisors = ((Advised) bean).getAdvisors();
+ assertEquals("Incorrect number of advisors", 1, advisors.length);
+ assertEquals("Incorrect advice class.", DebugInterceptor.class, advisors[0].getAdvice().getClass());
+ }
+
+ public void testChainedDecorators() throws Exception {
+ ITestBean bean = (ITestBean) this.beanFactory.getBean("chainedTestBean");
+ assetTestBean(bean);
+ assertTrue(AopUtils.isAopProxy(bean));
+ Advisor[] advisors = ((Advised) bean).getAdvisors();
+ assertEquals("Incorrect number of advisors", 2, advisors.length);
+ assertEquals("Incorrect advice class.", DebugInterceptor.class, advisors[0].getAdvice().getClass());
+ assertEquals("Incorrect advice class.", NopInterceptor.class, advisors[1].getAdvice().getClass());
+ }
+
+ public void testDecorationViaAttribute() throws Exception {
+ BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition("decorateWithAttribute");
+ assertEquals("foo", beanDefinition.getAttribute("objectName"));
+ }
+
+ /**
+ * http://opensource.atlassian.com/projects/spring/browse/SPR-2728
+ */
+ public void testCustomElementNestedWithinUtilList() throws Exception {
+ List things = (List) this.beanFactory.getBean("list.of.things");
+ assertNotNull(things);
+ assertEquals(2, things.size());
+ }
+
+ /**
+ * http://opensource.atlassian.com/projects/spring/browse/SPR-2728
+ */
+ public void testCustomElementNestedWithinUtilSet() throws Exception {
+ Set things = (Set) this.beanFactory.getBean("set.of.things");
+ assertNotNull(things);
+ assertEquals(2, things.size());
+ }
+
+ /**
+ * http://opensource.atlassian.com/projects/spring/browse/SPR-2728
+ */
+ public void testCustomElementNestedWithinUtilMap() throws Exception {
+ Map things = (Map) this.beanFactory.getBean("map.of.things");
+ assertNotNull(things);
+ assertEquals(2, things.size());
+ }
+
+
+ private void assetTestBean(ITestBean bean) {
+ assertEquals("Invalid name", "Rob Harrop", bean.getName());
+ assertEquals("Invalid age", 23, bean.getAge());
+ }
+
+ private Resource getResource() {
+ return new ClassPathResource("customNamespace.xml", getClass());
+ }
+
+
+ private final class DummySchemaResolver extends PluggableSchemaResolver {
+
+ public DummySchemaResolver() {
+ super(CustomNamespaceHandlerTests.this.getClass().getClassLoader());
+ }
+
+
+ public InputSource resolveEntity(String publicId, String systemId) throws IOException {
+ InputSource source = super.resolveEntity(publicId, systemId);
+ if (source == null) {
+ Resource resource = new ClassPathResource("org/springframework/beans/factory/xml/support/spring-test.xsd");
+ source = new InputSource(resource.getInputStream());
+ source.setPublicId(publicId);
+ source.setSystemId(systemId);
+ }
+ return source;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/DefaultNamespaceHandlerResolverTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/DefaultNamespaceHandlerResolverTests.java
new file mode 100644
index 00000000000..a3826d38574
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/DefaultNamespaceHandlerResolverTests.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml.support;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver;
+import org.springframework.beans.factory.xml.NamespaceHandler;
+import org.springframework.beans.factory.xml.UtilNamespaceHandler;
+import org.springframework.test.AssertThrows;
+
+/**
+ * Unit and integration tests for the {@link DefaultNamespaceHandlerResolver} class.
+ *
+ * @author Rob Harrop
+ * @author Rick Evans
+ */
+public class DefaultNamespaceHandlerResolverTests extends TestCase {
+
+ public void testResolvedMappedHandler() {
+ DefaultNamespaceHandlerResolver resolver = new DefaultNamespaceHandlerResolver(getClass().getClassLoader());
+ NamespaceHandler handler = resolver.resolve("http://www.springframework.org/schema/util");
+ assertNotNull("Handler should not be null.", handler);
+ assertEquals("Incorrect handler loaded", UtilNamespaceHandler.class, handler.getClass());
+ }
+
+ public void testResolvedMappedHandlerWithNoArgCtor() {
+ DefaultNamespaceHandlerResolver resolver = new DefaultNamespaceHandlerResolver();
+ NamespaceHandler handler = resolver.resolve("http://www.springframework.org/schema/util");
+ assertNotNull("Handler should not be null.", handler);
+ assertEquals("Incorrect handler loaded", UtilNamespaceHandler.class, handler.getClass());
+ }
+
+ public void testNonExistentHandlerClass() throws Exception {
+ String mappingPath = "org/springframework/beans/factory/xml/support/nonExistent.properties";
+ try {
+ new DefaultNamespaceHandlerResolver(getClass().getClassLoader(), mappingPath);
+ // pass
+ }
+ catch (Throwable ex) {
+ fail("Non-existent handler classes must be ignored: " + ex);
+ }
+ }
+
+ public void testResolveInvalidHandler() throws Exception {
+ String mappingPath = "org/springframework/beans/factory/xml/support/invalid.properties";
+ try {
+ new DefaultNamespaceHandlerResolver(getClass().getClassLoader(), mappingPath);
+ fail("Should not be able to map a class that doesn't implement NamespaceHandler");
+ }
+ catch (Throwable expected) {
+ }
+ }
+
+ public void testCtorWithNullClassLoaderArgument() throws Exception {
+ // simply must not bail...
+ new DefaultNamespaceHandlerResolver(null);
+ }
+
+ public void testCtorWithNullClassLoaderArgumentAndNullMappingLocationArgument() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new DefaultNamespaceHandlerResolver(null, null);
+ }
+ }.runTest();
+ }
+
+ public void testCtorWithNonExistentMappingLocationArgument() throws Exception {
+ // simply must not bail; we don't want non-existent resources to result in an Exception
+ new DefaultNamespaceHandlerResolver(null, "738trbc bobabloobop871");
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/TestNamespaceHandler.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/TestNamespaceHandler.java
new file mode 100644
index 00000000000..997e21db8d6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/TestNamespaceHandler.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.factory.xml.support;
+
+import org.springframework.aop.config.AbstractInterceptorDrivenBeanDefinitionDecorator;
+import org.springframework.aop.interceptor.DebugInterceptor;
+import org.springframework.aop.interceptor.NopInterceptor;
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.BeanDefinitionHolder;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
+import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
+import org.springframework.beans.factory.xml.BeanDefinitionParser;
+import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * @author Rob Harrop
+ */
+public class TestNamespaceHandler extends NamespaceHandlerSupport {
+
+ public void init() {
+ registerBeanDefinitionParser("testBean", new TestBeanDefinitionParser());
+ registerBeanDefinitionParser("person", new PersonDefinitionParser());
+
+ registerBeanDefinitionDecorator("set", new PropertyModifyingBeanDefinitionDecorator());
+ registerBeanDefinitionDecorator("debug", new DebugBeanDefinitionDecorator());
+ registerBeanDefinitionDecorator("nop", new NopInterceptorBeanDefinitionDecorator());
+ registerBeanDefinitionDecoratorForAttribute("object-name", new ObjectNameBeanDefinitionDecorator());
+ }
+
+ private static class TestBeanDefinitionParser implements BeanDefinitionParser {
+
+ public BeanDefinition parse(Element element, ParserContext parserContext) {
+ RootBeanDefinition definition = new RootBeanDefinition();
+ definition.setBeanClass(TestBean.class);
+
+ MutablePropertyValues mpvs = new MutablePropertyValues();
+ mpvs.addPropertyValue("name", element.getAttribute("name"));
+ mpvs.addPropertyValue("age", element.getAttribute("age"));
+ definition.setPropertyValues(mpvs);
+
+ parserContext.getRegistry().registerBeanDefinition(element.getAttribute("id"), definition);
+
+ return null;
+ }
+ }
+
+ private static final class PersonDefinitionParser extends AbstractSingleBeanDefinitionParser {
+
+ protected Class getBeanClass(Element element) {
+ return TestBean.class;
+ }
+
+ protected void doParse(Element element, BeanDefinitionBuilder builder) {
+ builder.addPropertyValue("name", element.getAttribute("name"));
+ builder.addPropertyValue("age", element.getAttribute("age"));
+ }
+ }
+
+ private static class PropertyModifyingBeanDefinitionDecorator implements BeanDefinitionDecorator {
+
+ public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
+ Element element = (Element) node;
+ BeanDefinition def = definition.getBeanDefinition();
+
+ MutablePropertyValues mpvs = (def.getPropertyValues() == null) ? new MutablePropertyValues() : def.getPropertyValues();
+ mpvs.addPropertyValue("name", element.getAttribute("name"));
+ mpvs.addPropertyValue("age", element.getAttribute("age"));
+
+ ((AbstractBeanDefinition) def).setPropertyValues(mpvs);
+ return definition;
+ }
+ }
+
+ private static class DebugBeanDefinitionDecorator extends AbstractInterceptorDrivenBeanDefinitionDecorator {
+
+ protected BeanDefinition createInterceptorDefinition(Node node) {
+ return new RootBeanDefinition(DebugInterceptor.class);
+ }
+ }
+
+ private static class NopInterceptorBeanDefinitionDecorator extends AbstractInterceptorDrivenBeanDefinitionDecorator {
+
+ protected BeanDefinition createInterceptorDefinition(Node node) {
+ return new RootBeanDefinition(NopInterceptor.class);
+ }
+ }
+
+ private static class ObjectNameBeanDefinitionDecorator implements BeanDefinitionDecorator {
+
+ public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
+ Attr objectNameAttribute = (Attr) node;
+ definition.getBeanDefinition().setAttribute("objectName", objectNameAttribute.getValue());
+ return definition;
+ }
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/customNamespace.properties b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/customNamespace.properties
new file mode 100644
index 00000000000..fe0eca6f07c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/customNamespace.properties
@@ -0,0 +1,2 @@
+http\://www.springframework.org/schema/beans/test=org.springframework.beans.factory.xml.support.TestNamespaceHandler
+http\://www.springframework.org/schema/util=org.springframework.beans.factory.xml.UtilNamespaceHandler
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/customNamespace.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/customNamespace.xml
new file mode 100644
index 00000000000..fdd268c8cdc
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/customNamespace.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/invalid.properties b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/invalid.properties
new file mode 100644
index 00000000000..f0c6c392ba4
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/invalid.properties
@@ -0,0 +1 @@
+http\://www.springframework.org/schema/test=java.lang.String
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/nonExistent.properties b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/nonExistent.properties
new file mode 100644
index 00000000000..0944d907a31
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/nonExistent.properties
@@ -0,0 +1 @@
+http\://www.springframework.org/schema/test=com.myapp.Foo
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/spring-test.xsd b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/spring-test.xsd
new file mode 100644
index 00000000000..ccf71f6c8e6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/support/spring-test.xsd
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/test.properties b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/test.properties
new file mode 100644
index 00000000000..30d74d25844
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/test.properties
@@ -0,0 +1 @@
+test
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/test.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/test.xml
new file mode 100644
index 00000000000..e67e3101362
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/test.xml
@@ -0,0 +1,127 @@
+
+
+
+
+
+
+
+ I have no properties and I'm happy without them.
+
+
+
+
+
+ aliased
+
+
+
+
+
+
+
+ aliased
+
+
+
+
+
+ aliased
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Rod
+ 31
+
+
+
+
+
+ Roderick
+
+
+
+
+ Kerry
+ 34
+
+
+
+
+
+ Kathy
+ 28
+
+
+
+
+ typeMismatch
+ 34x
+
+
+
+
+
+
+
+ true
+
+
+
+ true
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ listenerVeto
+ 66
+
+
+
+
+
+ this is a ]]>
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/testUtilNamespace.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/testUtilNamespace.xml
new file mode 100644
index 00000000000..052e27965e7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/testUtilNamespace.xml
@@ -0,0 +1,184 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ My scoped Map
+
+
+
+
+
+
+
+
+ Rob Harrop
+
+
+
+ My scoped List
+ Rob Harrop
+
+
+
+ Rob Harrop
+
+
+
+ My scoped Set
+ Rob Harrop
+
+
+
+
+
+ foo
+
+
+
+
+ bar
+
+
+
+
+
+
+ bar
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ min
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ bar2
+
+
+
+ bar2
+
+
+
+ local
+ local2
+
+
+
+ local
+ local2
+
+
+
+ local
+ local2
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/testWithDuplicateNameInAlias.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/testWithDuplicateNameInAlias.xml
new file mode 100644
index 00000000000..cc049ed23cd
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/testWithDuplicateNameInAlias.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/testWithDuplicateNames.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/testWithDuplicateNames.xml
new file mode 100644
index 00000000000..e991af7167a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/testWithDuplicateNames.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/unsatisfiedAllDependencyCheckMissingObjects.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/unsatisfiedAllDependencyCheckMissingObjects.xml
new file mode 100644
index 00000000000..19faed79258
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/unsatisfiedAllDependencyCheckMissingObjects.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+ 33
+ Rod
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/unsatisfiedAllDependencyCheckMissingSimple.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/unsatisfiedAllDependencyCheckMissingSimple.xml
new file mode 100644
index 00000000000..df21ad72626
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/unsatisfiedAllDependencyCheckMissingSimple.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ tony
+ -->
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/unsatisfiedObjectDependencyCheck.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/unsatisfiedObjectDependencyCheck.xml
new file mode 100644
index 00000000000..f18e9e77c29
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/unsatisfiedObjectDependencyCheck.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/unsatisfiedSimpleDependencyCheck.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/unsatisfiedSimpleDependencyCheck.xml
new file mode 100644
index 00000000000..8463f132a12
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/unsatisfiedSimpleDependencyCheck.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/validateWithDtd.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/validateWithDtd.xml
new file mode 100644
index 00000000000..91fdcd879f2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/validateWithDtd.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/validateWithXsd.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/validateWithXsd.xml
new file mode 100644
index 00000000000..cb08194ade8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/validateWithXsd.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/withMeta.xml b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/withMeta.xml
new file mode 100644
index 00000000000..3b8d004cd5f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/factory/xml/withMeta.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/BeanInfoTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/BeanInfoTests.java
new file mode 100644
index 00000000000..9be6a107f39
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/BeanInfoTests.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.propertyeditors;
+
+import java.beans.IntrospectionException;
+import java.beans.PropertyDescriptor;
+import java.beans.SimpleBeanInfo;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.BeanWrapper;
+import org.springframework.beans.BeanWrapperImpl;
+import org.springframework.beans.FatalBeanException;
+import org.springframework.core.JdkVersion;
+import org.springframework.util.Assert;
+
+/**
+ * @author Juergen Hoeller
+ * @since 06.03.2006
+ */
+public class BeanInfoTests extends TestCase {
+
+ public void testComplexObject() {
+ ValueBean bean = new ValueBean();
+ BeanWrapper bw = new BeanWrapperImpl(bean);
+ Integer value = new Integer(1);
+
+ bw.setPropertyValue("value", value);
+ assertEquals("value not set correctly", bean.getValue(), value);
+
+ value = new Integer(2);
+ bw.setPropertyValue("value", value.toString());
+ assertEquals("value not converted", bean.getValue(), value);
+
+ bw.setPropertyValue("value", null);
+ assertNull("value not null", bean.getValue());
+
+ bw.setPropertyValue("value", "");
+ assertNull("value not converted to null", bean.getValue());
+ }
+
+
+ public static class ValueBean {
+
+ private Integer value;
+
+ public Integer getValue() {
+ return value;
+ }
+
+ public void setValue(Integer value) {
+ this.value = value;
+ }
+ }
+
+
+ public static class ValueBeanBeanInfo extends SimpleBeanInfo {
+
+ public PropertyDescriptor[] getPropertyDescriptors() {
+ try {
+ PropertyDescriptor pd = new PropertyDescriptor("value", ValueBean.class);
+ pd.setPropertyEditorClass(MyNumberEditor.class);
+ return new PropertyDescriptor[] {pd};
+ }
+ catch (IntrospectionException ex) {
+ throw new FatalBeanException("Couldn't create PropertyDescriptor", ex);
+ }
+ }
+ }
+
+
+ public static class MyNumberEditor extends CustomNumberEditor {
+
+ private Object target;
+
+ public MyNumberEditor() throws IllegalArgumentException {
+ super(Integer.class, true);
+ }
+
+ public MyNumberEditor(Object target) throws IllegalArgumentException {
+ super(Integer.class, true);
+ this.target = target;
+ }
+
+ public void setAsText(String text) throws IllegalArgumentException {
+ if (JdkVersion.getMajorJavaVersion() >= JdkVersion.JAVA_15) {
+ Assert.isTrue(this.target instanceof ValueBean, "Target must be available on JDK 1.5+");
+ }
+ super.setAsText(text);
+ }
+
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/ByteArrayPropertyEditorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/ByteArrayPropertyEditorTests.java
new file mode 100644
index 00000000000..7c8ab4a56fe
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/ByteArrayPropertyEditorTests.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.propertyeditors;
+
+import junit.framework.TestCase;
+
+import java.beans.PropertyEditor;
+
+/**
+ * Unit tests for the {@link ByteArrayPropertyEditor} class.
+ *
+ * @author Rick Evans
+ */
+public final class ByteArrayPropertyEditorTests extends TestCase {
+
+ public void testSunnyDaySetAsText() throws Exception {
+ final String text = "Hideous towns make me throw... up";
+
+ PropertyEditor byteEditor = new ByteArrayPropertyEditor();
+ byteEditor.setAsText(text);
+
+ Object value = byteEditor.getValue();
+ assertNotNull(value);
+ assertTrue(value instanceof byte[]);
+ byte[] bytes = (byte[]) value;
+ for (int i = 0; i < text.length(); ++i) {
+ assertEquals("cyte[] differs at index '" + i + "'", text.charAt(i), bytes[i]);
+ }
+ assertEquals(text, byteEditor.getAsText());
+ }
+
+ public void testGetAsTextReturnsEmptyStringIfValueIsNull() throws Exception {
+ PropertyEditor byteEditor = new ByteArrayPropertyEditor();
+ assertEquals("", byteEditor.getAsText());
+
+ byteEditor.setAsText(null);
+ assertEquals("", byteEditor.getAsText());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/CharArrayPropertyEditorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/CharArrayPropertyEditorTests.java
new file mode 100644
index 00000000000..3f28d1c2512
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/CharArrayPropertyEditorTests.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.propertyeditors;
+
+import junit.framework.TestCase;
+
+import java.beans.PropertyEditor;
+
+/**
+ * Unit tests for the {@link CharArrayPropertyEditor} class.
+ *
+ * @author Rick Evans
+ */
+public final class CharArrayPropertyEditorTests extends TestCase {
+
+ public void testSunnyDaySetAsText() throws Exception {
+ final String text = "Hideous towns make me throw... up";
+
+ PropertyEditor charEditor = new CharArrayPropertyEditor();
+ charEditor.setAsText(text);
+
+ Object value = charEditor.getValue();
+ assertNotNull(value);
+ assertTrue(value instanceof char[]);
+ char[] chars = (char[]) value;
+ for (int i = 0; i < text.length(); ++i) {
+ assertEquals("char[] differs at index '" + i + "'", text.charAt(i), chars[i]);
+ }
+ assertEquals(text, charEditor.getAsText());
+ }
+
+ public void testGetAsTextReturnsEmptyStringIfValueIsNull() throws Exception {
+ PropertyEditor charEditor = new CharArrayPropertyEditor();
+ assertEquals("", charEditor.getAsText());
+
+ charEditor.setAsText(null);
+ assertEquals("", charEditor.getAsText());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/CustomCollectionEditorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/CustomCollectionEditorTests.java
new file mode 100644
index 00000000000..87ace2d0787
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/CustomCollectionEditorTests.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.propertyeditors;
+
+import junit.framework.TestCase;
+import org.springframework.test.AssertThrows;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Collection;
+
+/**
+ * Unit tests for the {@link CustomCollectionEditor} class.
+ *
+ * @author Rick Evans
+ */
+public final class CustomCollectionEditorTests extends TestCase {
+
+ public void testCtorWithNullCollectionType() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new CustomCollectionEditor(null);
+ }
+ }.runTest();
+ }
+
+ public void testCtorWithNonCollectionType() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new CustomCollectionEditor(String.class);
+ }
+ }.runTest();
+ }
+
+ public void testWithCollectionTypeThatDoesNotExposeAPublicNoArgCtor() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ CustomCollectionEditor editor = new CustomCollectionEditor(CollectionTypeWithNoNoArgCtor.class);
+ editor.setValue("1");
+ }
+ }.runTest();
+ }
+
+ public void testSunnyDaySetValue() throws Exception {
+ CustomCollectionEditor editor = new CustomCollectionEditor(ArrayList.class);
+ editor.setValue(new int[] {0, 1, 2});
+ Object value = editor.getValue();
+ assertNotNull(value);
+ assertTrue(value instanceof ArrayList);
+ List list = (List) value;
+ assertEquals("There must be 3 elements in the converted collection", 3, list.size());
+ assertEquals(new Integer(0), list.get(0));
+ assertEquals(new Integer(1), list.get(1));
+ assertEquals(new Integer(2), list.get(2));
+ }
+
+ public void testWhenTargetTypeIsExactlyTheCollectionInterfaceUsesFallbackCollectionType() throws Exception {
+ CustomCollectionEditor editor = new CustomCollectionEditor(Collection.class);
+ editor.setValue("0, 1, 2");
+ Collection value = (Collection) editor.getValue();
+ assertNotNull(value);
+ assertEquals("There must be 1 element in the converted collection", 1, value.size());
+ assertEquals("0, 1, 2", value.iterator().next());
+ }
+
+ public void testSunnyDaySetAsTextYieldsSingleValue() throws Exception {
+ CustomCollectionEditor editor = new CustomCollectionEditor(ArrayList.class);
+ editor.setValue("0, 1, 2");
+ Object value = editor.getValue();
+ assertNotNull(value);
+ assertTrue(value instanceof ArrayList);
+ List list = (List) value;
+ assertEquals("There must be 1 element in the converted collection", 1, list.size());
+ assertEquals("0, 1, 2", list.get(0));
+ }
+
+
+ private static final class CollectionTypeWithNoNoArgCtor extends ArrayList {
+
+ public CollectionTypeWithNoNoArgCtor(String anArg) {
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/CustomEditorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/CustomEditorTests.java
new file mode 100644
index 00000000000..cf2e3922175
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/CustomEditorTests.java
@@ -0,0 +1,1492 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.beans.propertyeditors;
+
+import java.beans.PropertyEditor;
+import java.beans.PropertyEditorSupport;
+import java.beans.PropertyVetoException;
+import java.io.File;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.nio.charset.Charset;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import java.util.regex.Pattern;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.BeanWrapper;
+import org.springframework.beans.BeanWrapperImpl;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.BooleanTestBean;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.IndexedTestBean;
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.NumberTestBean;
+import org.springframework.beans.PropertyValue;
+import org.springframework.beans.TestBean;
+import org.springframework.test.AssertThrows;
+
+/**
+ * Unit tests for the various PropertyEditors in Spring.
+ *
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ * @author Rob Harrop
+ * @author Arjen Poutsma
+ *
+ * @since 10.06.2003
+ */
+public class CustomEditorTests extends TestCase {
+
+ public void testComplexObject() {
+ TestBean tb = new TestBean();
+ String newName = "Rod";
+ String tbString = "Kerry_34";
+
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ bw.registerCustomEditor(ITestBean.class, new TestBeanEditor());
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue(new PropertyValue("age", new Integer(55)));
+ pvs.addPropertyValue(new PropertyValue("name", newName));
+ pvs.addPropertyValue(new PropertyValue("touchy", "valid"));
+ pvs.addPropertyValue(new PropertyValue("spouse", tbString));
+ bw.setPropertyValues(pvs);
+ assertTrue("spouse is non-null", tb.getSpouse() != null);
+ assertTrue("spouse name is Kerry and age is 34",
+ tb.getSpouse().getName().equals("Kerry") && tb.getSpouse().getAge() == 34);
+ }
+
+ public void testComplexObjectWithOldValueAccess() {
+ TestBean tb = new TestBean();
+ String newName = "Rod";
+ String tbString = "Kerry_34";
+
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ bw.setExtractOldValueForEditor(true);
+ bw.registerCustomEditor(ITestBean.class, new OldValueAccessingTestBeanEditor());
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue(new PropertyValue("age", new Integer(55)));
+ pvs.addPropertyValue(new PropertyValue("name", newName));
+ pvs.addPropertyValue(new PropertyValue("touchy", "valid"));
+ pvs.addPropertyValue(new PropertyValue("spouse", tbString));
+
+ bw.setPropertyValues(pvs);
+ assertTrue("spouse is non-null", tb.getSpouse() != null);
+ assertTrue("spouse name is Kerry and age is 34",
+ tb.getSpouse().getName().equals("Kerry") && tb.getSpouse().getAge() == 34);
+ ITestBean spouse = tb.getSpouse();
+
+ bw.setPropertyValues(pvs);
+ assertSame("Should have remained same object", spouse, tb.getSpouse());
+ }
+
+ public void testCustomEditorForSingleProperty() {
+ TestBean tb = new TestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ bw.registerCustomEditor(String.class, "name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("prefix" + text);
+ }
+ });
+ bw.setPropertyValue("name", "value");
+ bw.setPropertyValue("touchy", "value");
+ assertEquals("prefixvalue", bw.getPropertyValue("name"));
+ assertEquals("prefixvalue", tb.getName());
+ assertEquals("value", bw.getPropertyValue("touchy"));
+ assertEquals("value", tb.getTouchy());
+ }
+
+ public void testCustomEditorForAllStringProperties() {
+ TestBean tb = new TestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ bw.registerCustomEditor(String.class, new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("prefix" + text);
+ }
+ });
+ bw.setPropertyValue("name", "value");
+ bw.setPropertyValue("touchy", "value");
+ assertEquals("prefixvalue", bw.getPropertyValue("name"));
+ assertEquals("prefixvalue", tb.getName());
+ assertEquals("prefixvalue", bw.getPropertyValue("touchy"));
+ assertEquals("prefixvalue", tb.getTouchy());
+ }
+
+ public void testCustomEditorForSingleNestedProperty() {
+ TestBean tb = new TestBean();
+ tb.setSpouse(new TestBean());
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ bw.registerCustomEditor(String.class, "spouse.name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("prefix" + text);
+ }
+ });
+ bw.setPropertyValue("spouse.name", "value");
+ bw.setPropertyValue("touchy", "value");
+ assertEquals("prefixvalue", bw.getPropertyValue("spouse.name"));
+ assertEquals("prefixvalue", tb.getSpouse().getName());
+ assertEquals("value", bw.getPropertyValue("touchy"));
+ assertEquals("value", tb.getTouchy());
+ }
+
+ public void testCustomEditorForAllNestedStringProperties() {
+ TestBean tb = new TestBean();
+ tb.setSpouse(new TestBean());
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ bw.registerCustomEditor(String.class, new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("prefix" + text);
+ }
+ });
+ bw.setPropertyValue("spouse.name", "value");
+ bw.setPropertyValue("touchy", "value");
+ assertEquals("prefixvalue", bw.getPropertyValue("spouse.name"));
+ assertEquals("prefixvalue", tb.getSpouse().getName());
+ assertEquals("prefixvalue", bw.getPropertyValue("touchy"));
+ assertEquals("prefixvalue", tb.getTouchy());
+ }
+
+ public void testDefaultBooleanEditorForPrimitiveType() {
+ BooleanTestBean tb = new BooleanTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+
+ bw.setPropertyValue("bool1", "true");
+ assertTrue("Correct bool1 value", Boolean.TRUE.equals(bw.getPropertyValue("bool1")));
+ assertTrue("Correct bool1 value", tb.isBool1());
+
+ bw.setPropertyValue("bool1", "false");
+ assertTrue("Correct bool1 value", Boolean.FALSE.equals(bw.getPropertyValue("bool1")));
+ assertTrue("Correct bool1 value", !tb.isBool1());
+
+ bw.setPropertyValue("bool1", " true ");
+ assertTrue("Correct bool1 value", tb.isBool1());
+
+ bw.setPropertyValue("bool1", " false ");
+ assertTrue("Correct bool1 value", !tb.isBool1());
+
+ bw.setPropertyValue("bool1", "on");
+ assertTrue("Correct bool1 value", tb.isBool1());
+
+ bw.setPropertyValue("bool1", "off");
+ assertTrue("Correct bool1 value", !tb.isBool1());
+
+ bw.setPropertyValue("bool1", "yes");
+ assertTrue("Correct bool1 value", tb.isBool1());
+
+ bw.setPropertyValue("bool1", "no");
+ assertTrue("Correct bool1 value", !tb.isBool1());
+
+ bw.setPropertyValue("bool1", "1");
+ assertTrue("Correct bool1 value", tb.isBool1());
+
+ bw.setPropertyValue("bool1", "0");
+ assertTrue("Correct bool1 value", !tb.isBool1());
+
+ try {
+ bw.setPropertyValue("bool1", "argh");
+ fail("Should have thrown BeansException");
+ }
+ catch (BeansException ex) {
+ // expected
+ }
+ }
+
+ public void testDefaultBooleanEditorForWrapperType() {
+ BooleanTestBean tb = new BooleanTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+
+ bw.setPropertyValue("bool2", "true");
+ assertTrue("Correct bool2 value", Boolean.TRUE.equals(bw.getPropertyValue("bool2")));
+ assertTrue("Correct bool2 value", tb.getBool2().booleanValue());
+
+ bw.setPropertyValue("bool2", "false");
+ assertTrue("Correct bool2 value", Boolean.FALSE.equals(bw.getPropertyValue("bool2")));
+ assertTrue("Correct bool2 value", !tb.getBool2().booleanValue());
+
+ bw.setPropertyValue("bool2", "on");
+ assertTrue("Correct bool2 value", tb.getBool2().booleanValue());
+
+ bw.setPropertyValue("bool2", "off");
+ assertTrue("Correct bool2 value", !tb.getBool2().booleanValue());
+
+ bw.setPropertyValue("bool2", "yes");
+ assertTrue("Correct bool2 value", tb.getBool2().booleanValue());
+
+ bw.setPropertyValue("bool2", "no");
+ assertTrue("Correct bool2 value", !tb.getBool2().booleanValue());
+
+ bw.setPropertyValue("bool2", "1");
+ assertTrue("Correct bool2 value", tb.getBool2().booleanValue());
+
+ bw.setPropertyValue("bool2", "0");
+ assertTrue("Correct bool2 value", !tb.getBool2().booleanValue());
+
+ bw.setPropertyValue("bool2", "");
+ assertNull("Correct bool2 value", tb.getBool2());
+ }
+
+ public void testCustomBooleanEditorWithAllowEmpty() {
+ BooleanTestBean tb = new BooleanTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ bw.registerCustomEditor(Boolean.class, new CustomBooleanEditor(true));
+
+ bw.setPropertyValue("bool2", "true");
+ assertTrue("Correct bool2 value", Boolean.TRUE.equals(bw.getPropertyValue("bool2")));
+ assertTrue("Correct bool2 value", tb.getBool2().booleanValue());
+
+ bw.setPropertyValue("bool2", "false");
+ assertTrue("Correct bool2 value", Boolean.FALSE.equals(bw.getPropertyValue("bool2")));
+ assertTrue("Correct bool2 value", !tb.getBool2().booleanValue());
+
+ bw.setPropertyValue("bool2", "on");
+ assertTrue("Correct bool2 value", tb.getBool2().booleanValue());
+
+ bw.setPropertyValue("bool2", "off");
+ assertTrue("Correct bool2 value", !tb.getBool2().booleanValue());
+
+ bw.setPropertyValue("bool2", "yes");
+ assertTrue("Correct bool2 value", tb.getBool2().booleanValue());
+
+ bw.setPropertyValue("bool2", "no");
+ assertTrue("Correct bool2 value", !tb.getBool2().booleanValue());
+
+ bw.setPropertyValue("bool2", "1");
+ assertTrue("Correct bool2 value", tb.getBool2().booleanValue());
+
+ bw.setPropertyValue("bool2", "0");
+ assertTrue("Correct bool2 value", !tb.getBool2().booleanValue());
+
+ bw.setPropertyValue("bool2", "");
+ assertTrue("Correct bool2 value", bw.getPropertyValue("bool2") == null);
+ assertTrue("Correct bool2 value", tb.getBool2() == null);
+ }
+
+ public void testCustomBooleanEditorWithSpecialTrueAndFalseStrings() throws Exception {
+ final String trueString = "pechorin";
+ final String falseString = "nash";
+
+ CustomBooleanEditor editor = new CustomBooleanEditor(trueString, falseString, false);
+
+ editor.setAsText(trueString);
+ assertTrue(((Boolean) editor.getValue()).booleanValue());
+ assertEquals(trueString, editor.getAsText());
+ editor.setAsText(falseString);
+ assertFalse(((Boolean) editor.getValue()).booleanValue());
+ assertEquals(falseString, editor.getAsText());
+
+ editor.setAsText(trueString.toUpperCase());
+ assertTrue(((Boolean) editor.getValue()).booleanValue());
+ assertEquals(trueString, editor.getAsText());
+ editor.setAsText(falseString.toUpperCase());
+ assertFalse(((Boolean) editor.getValue()).booleanValue());
+ assertEquals(falseString, editor.getAsText());
+ }
+
+ public void testDefaultNumberEditor() {
+ NumberTestBean tb = new NumberTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+
+ bw.setPropertyValue("short1", "1");
+ bw.setPropertyValue("short2", "2");
+ bw.setPropertyValue("int1", "7");
+ bw.setPropertyValue("int2", "8");
+ bw.setPropertyValue("long1", "5");
+ bw.setPropertyValue("long2", "6");
+ bw.setPropertyValue("bigInteger", "3");
+ bw.setPropertyValue("float1", "7.1");
+ bw.setPropertyValue("float2", "8.1");
+ bw.setPropertyValue("double1", "5.1");
+ bw.setPropertyValue("double2", "6.1");
+ bw.setPropertyValue("bigDecimal", "4.5");
+
+ assertTrue("Correct short1 value", new Short("1").equals(bw.getPropertyValue("short1")));
+ assertTrue("Correct short1 value", tb.getShort1() == 1);
+ assertTrue("Correct short2 value", new Short("2").equals(bw.getPropertyValue("short2")));
+ assertTrue("Correct short2 value", new Short("2").equals(tb.getShort2()));
+ assertTrue("Correct int1 value", new Integer("7").equals(bw.getPropertyValue("int1")));
+ assertTrue("Correct int1 value", tb.getInt1() == 7);
+ assertTrue("Correct int2 value", new Integer("8").equals(bw.getPropertyValue("int2")));
+ assertTrue("Correct int2 value", new Integer("8").equals(tb.getInt2()));
+ assertTrue("Correct long1 value", new Long("5").equals(bw.getPropertyValue("long1")));
+ assertTrue("Correct long1 value", tb.getLong1() == 5);
+ assertTrue("Correct long2 value", new Long("6").equals(bw.getPropertyValue("long2")));
+ assertTrue("Correct long2 value", new Long("6").equals(tb.getLong2()));
+ assertTrue("Correct bigInteger value", new BigInteger("3").equals(bw.getPropertyValue("bigInteger")));
+ assertTrue("Correct bigInteger value", new BigInteger("3").equals(tb.getBigInteger()));
+ assertTrue("Correct float1 value", new Float("7.1").equals(bw.getPropertyValue("float1")));
+ assertTrue("Correct float1 value", new Float("7.1").equals(new Float(tb.getFloat1())));
+ assertTrue("Correct float2 value", new Float("8.1").equals(bw.getPropertyValue("float2")));
+ assertTrue("Correct float2 value", new Float("8.1").equals(tb.getFloat2()));
+ assertTrue("Correct double1 value", new Double("5.1").equals(bw.getPropertyValue("double1")));
+ assertTrue("Correct double1 value", tb.getDouble1() == 5.1);
+ assertTrue("Correct double2 value", new Double("6.1").equals(bw.getPropertyValue("double2")));
+ assertTrue("Correct double2 value", new Double("6.1").equals(tb.getDouble2()));
+ assertTrue("Correct bigDecimal value", new BigDecimal("4.5").equals(bw.getPropertyValue("bigDecimal")));
+ assertTrue("Correct bigDecimal value", new BigDecimal("4.5").equals(tb.getBigDecimal()));
+ }
+
+ public void testCustomNumberEditorWithoutAllowEmpty() {
+ NumberFormat nf = NumberFormat.getNumberInstance(Locale.GERMAN);
+ NumberTestBean tb = new NumberTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ bw.registerCustomEditor(short.class, new CustomNumberEditor(Short.class, nf, false));
+ bw.registerCustomEditor(Short.class, new CustomNumberEditor(Short.class, nf, false));
+ bw.registerCustomEditor(int.class, new CustomNumberEditor(Integer.class, nf, false));
+ bw.registerCustomEditor(Integer.class, new CustomNumberEditor(Integer.class, nf, false));
+ bw.registerCustomEditor(long.class, new CustomNumberEditor(Long.class, nf, false));
+ bw.registerCustomEditor(Long.class, new CustomNumberEditor(Long.class, nf, false));
+ bw.registerCustomEditor(BigInteger.class, new CustomNumberEditor(BigInteger.class, nf, false));
+ bw.registerCustomEditor(float.class, new CustomNumberEditor(Float.class, nf, false));
+ bw.registerCustomEditor(Float.class, new CustomNumberEditor(Float.class, nf, false));
+ bw.registerCustomEditor(double.class, new CustomNumberEditor(Double.class, nf, false));
+ bw.registerCustomEditor(Double.class, new CustomNumberEditor(Double.class, nf, false));
+ bw.registerCustomEditor(BigDecimal.class, new CustomNumberEditor(BigDecimal.class, nf, false));
+
+ bw.setPropertyValue("short1", "1");
+ bw.setPropertyValue("short2", "2");
+ bw.setPropertyValue("int1", "7");
+ bw.setPropertyValue("int2", "8");
+ bw.setPropertyValue("long1", "5");
+ bw.setPropertyValue("long2", "6");
+ bw.setPropertyValue("bigInteger", "3");
+ bw.setPropertyValue("float1", "7,1");
+ bw.setPropertyValue("float2", "8,1");
+ bw.setPropertyValue("double1", "5,1");
+ bw.setPropertyValue("double2", "6,1");
+ bw.setPropertyValue("bigDecimal", "4,5");
+
+ assertTrue("Correct short1 value", new Short("1").equals(bw.getPropertyValue("short1")));
+ assertTrue("Correct short1 value", tb.getShort1() == 1);
+ assertTrue("Correct short2 value", new Short("2").equals(bw.getPropertyValue("short2")));
+ assertTrue("Correct short2 value", new Short("2").equals(tb.getShort2()));
+ assertTrue("Correct int1 value", new Integer("7").equals(bw.getPropertyValue("int1")));
+ assertTrue("Correct int1 value", tb.getInt1() == 7);
+ assertTrue("Correct int2 value", new Integer("8").equals(bw.getPropertyValue("int2")));
+ assertTrue("Correct int2 value", new Integer("8").equals(tb.getInt2()));
+ assertTrue("Correct long1 value", new Long("5").equals(bw.getPropertyValue("long1")));
+ assertTrue("Correct long1 value", tb.getLong1() == 5);
+ assertTrue("Correct long2 value", new Long("6").equals(bw.getPropertyValue("long2")));
+ assertTrue("Correct long2 value", new Long("6").equals(tb.getLong2()));
+ assertTrue("Correct bigInteger value", new BigInteger("3").equals(bw.getPropertyValue("bigInteger")));
+ assertTrue("Correct bigInteger value", new BigInteger("3").equals(tb.getBigInteger()));
+ assertTrue("Correct float1 value", new Float("7.1").equals(bw.getPropertyValue("float1")));
+ assertTrue("Correct float1 value", new Float("7.1").equals(new Float(tb.getFloat1())));
+ assertTrue("Correct float2 value", new Float("8.1").equals(bw.getPropertyValue("float2")));
+ assertTrue("Correct float2 value", new Float("8.1").equals(tb.getFloat2()));
+ assertTrue("Correct double1 value", new Double("5.1").equals(bw.getPropertyValue("double1")));
+ assertTrue("Correct double1 value", tb.getDouble1() == 5.1);
+ assertTrue("Correct double2 value", new Double("6.1").equals(bw.getPropertyValue("double2")));
+ assertTrue("Correct double2 value", new Double("6.1").equals(tb.getDouble2()));
+ assertTrue("Correct bigDecimal value", new BigDecimal("4.5").equals(bw.getPropertyValue("bigDecimal")));
+ assertTrue("Correct bigDecimal value", new BigDecimal("4.5").equals(tb.getBigDecimal()));
+ }
+
+ public void testCustomNumberEditorCtorWithNullNumberType() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new CustomNumberEditor(null, true);
+ }
+ }.runTest();
+ }
+
+ public void testCustomNumberEditorCtorWithNonNumberType() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new CustomNumberEditor(String.class, true);
+ }
+ }.runTest();
+ }
+
+ public void testCustomNumberEditorWithAllowEmpty() {
+ NumberFormat nf = NumberFormat.getNumberInstance(Locale.GERMAN);
+ NumberTestBean tb = new NumberTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ bw.registerCustomEditor(long.class, new CustomNumberEditor(Long.class, nf, true));
+ bw.registerCustomEditor(Long.class, new CustomNumberEditor(Long.class, nf, true));
+
+ bw.setPropertyValue("long1", "5");
+ bw.setPropertyValue("long2", "6");
+ assertTrue("Correct long1 value", new Long("5").equals(bw.getPropertyValue("long1")));
+ assertTrue("Correct long1 value", tb.getLong1() == 5);
+ assertTrue("Correct long2 value", new Long("6").equals(bw.getPropertyValue("long2")));
+ assertTrue("Correct long2 value", new Long("6").equals(tb.getLong2()));
+
+ bw.setPropertyValue("long2", "");
+ assertTrue("Correct long2 value", bw.getPropertyValue("long2") == null);
+ assertTrue("Correct long2 value", tb.getLong2() == null);
+
+ try {
+ bw.setPropertyValue("long1", "");
+ fail("Should have thrown BeansException");
+ }
+ catch (BeansException ex) {
+ // expected
+ assertTrue("Correct long1 value", new Long("5").equals(bw.getPropertyValue("long1")));
+ assertTrue("Correct long1 value", tb.getLong1() == 5);
+ }
+ }
+
+ public void testCustomNumberEditorWithFrenchBigDecimal() throws Exception {
+ NumberFormat nf = NumberFormat.getNumberInstance(Locale.FRENCH);
+ NumberTestBean tb = new NumberTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ bw.registerCustomEditor(BigDecimal.class, new CustomNumberEditor(BigDecimal.class, nf, true));
+ bw.setPropertyValue("bigDecimal", "1000");
+ assertEquals(1000.0f, tb.getBigDecimal().floatValue(), 0f);
+ bw.setPropertyValue("bigDecimal", "1000,5");
+ assertEquals(1000.5f, tb.getBigDecimal().floatValue(), 0f);
+ bw.setPropertyValue("bigDecimal", "1 000,5");
+ assertEquals(1000.5f, tb.getBigDecimal().floatValue(), 0f);
+ }
+
+ public void testParseShortGreaterThanMaxValueWithoutNumberFormat() {
+ new AssertThrows(NumberFormatException.class, Short.MAX_VALUE + 1 + " is greater than max value") {
+ public void test() throws Exception {
+ CustomNumberEditor editor = new CustomNumberEditor(Short.class, true);
+ editor.setAsText(String.valueOf(Short.MAX_VALUE + 1));
+ }
+ }.runTest();
+ }
+
+ public void testByteArrayPropertyEditor() {
+ PrimitiveArrayBean bean = new PrimitiveArrayBean();
+ BeanWrapper bw = new BeanWrapperImpl(bean);
+ bw.setPropertyValue("byteArray", "myvalue");
+ assertEquals("myvalue", new String(bean.getByteArray()));
+ }
+
+ public void testCharArrayPropertyEditor() {
+ PrimitiveArrayBean bean = new PrimitiveArrayBean();
+ BeanWrapper bw = new BeanWrapperImpl(bean);
+ bw.setPropertyValue("charArray", "myvalue");
+ assertEquals("myvalue", new String(bean.getCharArray()));
+ }
+
+ public void testCharacterEditor() {
+ CharBean cb = new CharBean();
+ BeanWrapper bw = new BeanWrapperImpl(cb);
+
+ bw.setPropertyValue("myChar", new Character('c'));
+ assertEquals('c', cb.getMyChar());
+
+ bw.setPropertyValue("myChar", "c");
+ assertEquals('c', cb.getMyChar());
+
+ bw.setPropertyValue("myChar", "\u0041");
+ assertEquals('A', cb.getMyChar());
+
+ bw.setPropertyValue("myChar", "\\u0022");
+ assertEquals('"', cb.getMyChar());
+
+ CharacterEditor editor = new CharacterEditor(false);
+ editor.setAsText("M");
+ assertEquals("M", editor.getAsText());
+ }
+
+ public void testCharacterEditorWithAllowEmpty() {
+ CharBean cb = new CharBean();
+ BeanWrapper bw = new BeanWrapperImpl(cb);
+ bw.registerCustomEditor(Character.class, new CharacterEditor(true));
+
+ bw.setPropertyValue("myCharacter", new Character('c'));
+ assertEquals(new Character('c'), cb.getMyCharacter());
+
+ bw.setPropertyValue("myCharacter", "c");
+ assertEquals(new Character('c'), cb.getMyCharacter());
+
+ bw.setPropertyValue("myCharacter", "\u0041");
+ assertEquals(new Character('A'), cb.getMyCharacter());
+
+ bw.setPropertyValue("myCharacter", " ");
+ assertEquals(new Character(' '), cb.getMyCharacter());
+
+ bw.setPropertyValue("myCharacter", "");
+ assertNull(cb.getMyCharacter());
+ }
+
+ public void testCharacterEditorSetAsTextWithStringLongerThanOneCharacter() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ PropertyEditor charEditor = new CharacterEditor(false);
+ charEditor.setAsText("ColdWaterCanyon");
+ }
+ }.runTest();
+ }
+
+ public void testCharacterEditorGetAsTextReturnsEmptyStringIfValueIsNull() throws Exception {
+ PropertyEditor charEditor = new CharacterEditor(false);
+ assertEquals("", charEditor.getAsText());
+ charEditor = new CharacterEditor(true);
+ charEditor.setAsText(null);
+ assertEquals("", charEditor.getAsText());
+ charEditor.setAsText("");
+ assertEquals("", charEditor.getAsText());
+ charEditor.setAsText(" ");
+ assertEquals(" ", charEditor.getAsText());
+ }
+
+ public void testCharacterEditorSetAsTextWithNullNotAllowingEmptyAsNull() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ PropertyEditor charEditor = new CharacterEditor(false);
+ charEditor.setAsText(null);
+ }
+ }.runTest();
+ }
+
+ public void testClassEditor() {
+ PropertyEditor classEditor = new ClassEditor();
+ classEditor.setAsText("org.springframework.beans.TestBean");
+ assertEquals(TestBean.class, classEditor.getValue());
+ assertEquals("org.springframework.beans.TestBean", classEditor.getAsText());
+
+ classEditor.setAsText(null);
+ assertEquals("", classEditor.getAsText());
+ classEditor.setAsText("");
+ assertEquals("", classEditor.getAsText());
+ classEditor.setAsText("\t ");
+ assertEquals("", classEditor.getAsText());
+ }
+
+ public void testClassEditorWithNonExistentClass() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ PropertyEditor classEditor = new ClassEditor();
+ classEditor.setAsText("hairdresser.on.Fire");
+ }
+ }.runTest();
+ }
+
+ public void testClassEditorWithArray() {
+ PropertyEditor classEditor = new ClassEditor();
+ classEditor.setAsText("org.springframework.beans.TestBean[]");
+ assertEquals(TestBean[].class, classEditor.getValue());
+ assertEquals("org.springframework.beans.TestBean[]", classEditor.getAsText());
+ }
+
+ /*
+ * SPR_2165 - ClassEditor is inconsistent with multidimensional arrays
+ */
+ public void testGetAsTextWithTwoDimensionalArray() throws Exception {
+ String[][] chessboard = new String[8][8];
+ ClassEditor editor = new ClassEditor();
+ editor.setValue(chessboard.getClass());
+ assertEquals("java.lang.String[][]", editor.getAsText());
+ }
+
+ /*
+ * SPR_2165 - ClassEditor is inconsistent with multidimensional arrays
+ */
+ public void testGetAsTextWithRidiculousMultiDimensionalArray() throws Exception {
+ String[][][][][] ridiculousChessboard = new String[8][4][0][1][3];
+ ClassEditor editor = new ClassEditor();
+ editor.setValue(ridiculousChessboard.getClass());
+ assertEquals("java.lang.String[][][][][]", editor.getAsText());
+ }
+
+ public void testFileEditor() {
+ PropertyEditor fileEditor = new FileEditor();
+ fileEditor.setAsText("file:myfile.txt");
+ assertEquals(new File("myfile.txt"), fileEditor.getValue());
+ assertEquals((new File("myfile.txt")).getPath(), fileEditor.getAsText());
+ }
+
+ public void testFileEditorWithRelativePath() {
+ PropertyEditor fileEditor = new FileEditor();
+ try {
+ fileEditor.setAsText("myfile.txt");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected: should get resolved as class path resource,
+ // and there is no such resource in the class path...
+ }
+ }
+
+ public void testFileEditorWithAbsolutePath() {
+ PropertyEditor fileEditor = new FileEditor();
+ // testing on Windows
+ if (new File("C:/myfile.txt").isAbsolute()) {
+ fileEditor.setAsText("C:/myfile.txt");
+ assertEquals(new File("C:/myfile.txt"), fileEditor.getValue());
+ }
+ // testing on Unix
+ if (new File("/myfile.txt").isAbsolute()) {
+ fileEditor.setAsText("/myfile.txt");
+ assertEquals(new File("/myfile.txt"), fileEditor.getValue());
+ }
+ }
+
+ public void testLocaleEditor() {
+ PropertyEditor localeEditor = new LocaleEditor();
+ localeEditor.setAsText("en_CA");
+ assertEquals(Locale.CANADA, localeEditor.getValue());
+ assertEquals("en_CA", localeEditor.getAsText());
+
+ localeEditor = new LocaleEditor();
+ assertEquals("", localeEditor.getAsText());
+ }
+
+ public void testPatternEditor() {
+ final String REGEX = "a.*";
+
+ PropertyEditor patternEditor = new PatternEditor();
+ patternEditor.setAsText(REGEX);
+ assertEquals(Pattern.compile(REGEX).pattern(), ((Pattern) patternEditor.getValue()).pattern());
+ assertEquals(REGEX, patternEditor.getAsText());
+
+ patternEditor = new PatternEditor();
+ assertEquals("", patternEditor.getAsText());
+
+ patternEditor = new PatternEditor();
+ patternEditor.setAsText(null);
+ assertEquals("", patternEditor.getAsText());
+ }
+
+ public void testCustomBooleanEditor() {
+ CustomBooleanEditor editor = new CustomBooleanEditor(false);
+ editor.setAsText("true");
+ assertEquals(Boolean.TRUE, editor.getValue());
+ assertEquals("true", editor.getAsText());
+ editor.setAsText("false");
+ assertEquals(Boolean.FALSE, editor.getValue());
+ assertEquals("false", editor.getAsText());
+ editor.setValue(null);
+ assertEquals(null, editor.getValue());
+ assertEquals("", editor.getAsText());
+ }
+
+ public void testCustomBooleanEditorWithEmptyAsNull() {
+ CustomBooleanEditor editor = new CustomBooleanEditor(true);
+ editor.setAsText("true");
+ assertEquals(Boolean.TRUE, editor.getValue());
+ assertEquals("true", editor.getAsText());
+ editor.setAsText("false");
+ assertEquals(Boolean.FALSE, editor.getValue());
+ assertEquals("false", editor.getAsText());
+ editor.setValue(null);
+ assertEquals(null, editor.getValue());
+ assertEquals("", editor.getAsText());
+ }
+
+ public void testCustomDateEditor() {
+ CustomDateEditor editor = new CustomDateEditor(null, false);
+ editor.setValue(null);
+ assertEquals(null, editor.getValue());
+ assertEquals("", editor.getAsText());
+ }
+
+ public void testCustomDateEditorWithEmptyAsNull() {
+ CustomDateEditor editor = new CustomDateEditor(null, true);
+ editor.setValue(null);
+ assertEquals(null, editor.getValue());
+ assertEquals("", editor.getAsText());
+ }
+
+ public void testCustomDateEditorWithExactDateLength() {
+ int maxLength = 10;
+ String validDate = "01/01/2005";
+ String invalidDate = "01/01/05";
+
+ assertTrue(validDate.length() == maxLength);
+ assertFalse(invalidDate.length() == maxLength);
+
+ CustomDateEditor editor = new CustomDateEditor(new SimpleDateFormat("MM/dd/yyyy"), true, maxLength);
+
+ try {
+ editor.setAsText(validDate);
+ }
+ catch (IllegalArgumentException ex) {
+ fail("Exception shouldn't be thrown because this is a valid date");
+ }
+
+ try {
+ editor.setAsText(invalidDate);
+ fail("Exception should be thrown because this is an invalid date");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ assertTrue(ex.getMessage().indexOf("10") != -1);
+ }
+ }
+
+ public void testCustomNumberEditor() {
+ CustomNumberEditor editor = new CustomNumberEditor(Integer.class, false);
+ editor.setAsText("5");
+ assertEquals(new Integer(5), editor.getValue());
+ assertEquals("5", editor.getAsText());
+ editor.setValue(null);
+ assertEquals(null, editor.getValue());
+ assertEquals("", editor.getAsText());
+ }
+
+ public void testCustomNumberEditorWithHex() {
+ CustomNumberEditor editor = new CustomNumberEditor(Integer.class, false);
+ editor.setAsText("0x" + Integer.toHexString(64));
+ assertEquals(new Integer(64), editor.getValue());
+ }
+
+ public void testCustomNumberEditorWithEmptyAsNull() {
+ CustomNumberEditor editor = new CustomNumberEditor(Integer.class, true);
+ editor.setAsText("5");
+ assertEquals(new Integer(5), editor.getValue());
+ assertEquals("5", editor.getAsText());
+ editor.setAsText("");
+ assertEquals(null, editor.getValue());
+ assertEquals("", editor.getAsText());
+ editor.setValue(null);
+ assertEquals(null, editor.getValue());
+ assertEquals("", editor.getAsText());
+ }
+
+ public void testStringTrimmerEditor() {
+ StringTrimmerEditor editor = new StringTrimmerEditor(false);
+ editor.setAsText("test");
+ assertEquals("test", editor.getValue());
+ assertEquals("test", editor.getAsText());
+ editor.setAsText(" test ");
+ assertEquals("test", editor.getValue());
+ assertEquals("test", editor.getAsText());
+ editor.setAsText("");
+ assertEquals("", editor.getValue());
+ assertEquals("", editor.getAsText());
+ editor.setValue(null);
+ assertEquals("", editor.getAsText());
+ editor.setAsText(null);
+ assertEquals("", editor.getAsText());
+ }
+
+ public void testStringTrimmerEditorWithEmptyAsNull() {
+ StringTrimmerEditor editor = new StringTrimmerEditor(true);
+ editor.setAsText("test");
+ assertEquals("test", editor.getValue());
+ assertEquals("test", editor.getAsText());
+ editor.setAsText(" test ");
+ assertEquals("test", editor.getValue());
+ assertEquals("test", editor.getAsText());
+ editor.setAsText(" ");
+ assertEquals(null, editor.getValue());
+ assertEquals("", editor.getAsText());
+ editor.setValue(null);
+ assertEquals("", editor.getAsText());
+ }
+
+ public void testStringTrimmerEditorWithCharsToDelete() {
+ StringTrimmerEditor editor = new StringTrimmerEditor("\r\n\f", false);
+ editor.setAsText("te\ns\ft");
+ assertEquals("test", editor.getValue());
+ assertEquals("test", editor.getAsText());
+ editor.setAsText(" test ");
+ assertEquals("test", editor.getValue());
+ assertEquals("test", editor.getAsText());
+ editor.setAsText("");
+ assertEquals("", editor.getValue());
+ assertEquals("", editor.getAsText());
+ editor.setValue(null);
+ assertEquals("", editor.getAsText());
+ }
+
+ public void testStringTrimmerEditorWithCharsToDeleteAndEmptyAsNull() {
+ StringTrimmerEditor editor = new StringTrimmerEditor("\r\n\f", true);
+ editor.setAsText("te\ns\ft");
+ assertEquals("test", editor.getValue());
+ assertEquals("test", editor.getAsText());
+ editor.setAsText(" test ");
+ assertEquals("test", editor.getValue());
+ assertEquals("test", editor.getAsText());
+ editor.setAsText(" \n\f ");
+ assertEquals(null, editor.getValue());
+ assertEquals("", editor.getAsText());
+ editor.setValue(null);
+ assertEquals("", editor.getAsText());
+ }
+
+ public void testIndexedPropertiesWithCustomEditorForType() {
+ IndexedTestBean bean = new IndexedTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(bean);
+ bw.registerCustomEditor(String.class, new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("prefix" + text);
+ }
+ });
+ TestBean tb0 = bean.getArray()[0];
+ TestBean tb1 = bean.getArray()[1];
+ TestBean tb2 = ((TestBean) bean.getList().get(0));
+ TestBean tb3 = ((TestBean) bean.getList().get(1));
+ TestBean tb4 = ((TestBean) bean.getMap().get("key1"));
+ TestBean tb5 = ((TestBean) bean.getMap().get("key2"));
+ assertEquals("name0", tb0.getName());
+ assertEquals("name1", tb1.getName());
+ assertEquals("name2", tb2.getName());
+ assertEquals("name3", tb3.getName());
+ assertEquals("name4", tb4.getName());
+ assertEquals("name5", tb5.getName());
+ assertEquals("name0", bw.getPropertyValue("array[0].name"));
+ assertEquals("name1", bw.getPropertyValue("array[1].name"));
+ assertEquals("name2", bw.getPropertyValue("list[0].name"));
+ assertEquals("name3", bw.getPropertyValue("list[1].name"));
+ assertEquals("name4", bw.getPropertyValue("map[key1].name"));
+ assertEquals("name5", bw.getPropertyValue("map[key2].name"));
+ assertEquals("name4", bw.getPropertyValue("map['key1'].name"));
+ assertEquals("name5", bw.getPropertyValue("map[\"key2\"].name"));
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("array[0].name", "name5");
+ pvs.addPropertyValue("array[1].name", "name4");
+ pvs.addPropertyValue("list[0].name", "name3");
+ pvs.addPropertyValue("list[1].name", "name2");
+ pvs.addPropertyValue("map[key1].name", "name1");
+ pvs.addPropertyValue("map['key2'].name", "name0");
+ bw.setPropertyValues(pvs);
+ assertEquals("prefixname5", tb0.getName());
+ assertEquals("prefixname4", tb1.getName());
+ assertEquals("prefixname3", tb2.getName());
+ assertEquals("prefixname2", tb3.getName());
+ assertEquals("prefixname1", tb4.getName());
+ assertEquals("prefixname0", tb5.getName());
+ assertEquals("prefixname5", bw.getPropertyValue("array[0].name"));
+ assertEquals("prefixname4", bw.getPropertyValue("array[1].name"));
+ assertEquals("prefixname3", bw.getPropertyValue("list[0].name"));
+ assertEquals("prefixname2", bw.getPropertyValue("list[1].name"));
+ assertEquals("prefixname1", bw.getPropertyValue("map[\"key1\"].name"));
+ assertEquals("prefixname0", bw.getPropertyValue("map['key2'].name"));
+ }
+
+ public void testIndexedPropertiesWithCustomEditorForProperty() {
+ IndexedTestBean bean = new IndexedTestBean(false);
+ BeanWrapper bw = new BeanWrapperImpl(bean);
+ bw.registerCustomEditor(String.class, "array.name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("array" + text);
+ }
+ });
+ bw.registerCustomEditor(String.class, "list.name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("list" + text);
+ }
+ });
+ bw.registerCustomEditor(String.class, "map.name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("map" + text);
+ }
+ });
+ bean.populate();
+
+ TestBean tb0 = bean.getArray()[0];
+ TestBean tb1 = bean.getArray()[1];
+ TestBean tb2 = ((TestBean) bean.getList().get(0));
+ TestBean tb3 = ((TestBean) bean.getList().get(1));
+ TestBean tb4 = ((TestBean) bean.getMap().get("key1"));
+ TestBean tb5 = ((TestBean) bean.getMap().get("key2"));
+ assertEquals("name0", tb0.getName());
+ assertEquals("name1", tb1.getName());
+ assertEquals("name2", tb2.getName());
+ assertEquals("name3", tb3.getName());
+ assertEquals("name4", tb4.getName());
+ assertEquals("name5", tb5.getName());
+ assertEquals("name0", bw.getPropertyValue("array[0].name"));
+ assertEquals("name1", bw.getPropertyValue("array[1].name"));
+ assertEquals("name2", bw.getPropertyValue("list[0].name"));
+ assertEquals("name3", bw.getPropertyValue("list[1].name"));
+ assertEquals("name4", bw.getPropertyValue("map[key1].name"));
+ assertEquals("name5", bw.getPropertyValue("map[key2].name"));
+ assertEquals("name4", bw.getPropertyValue("map['key1'].name"));
+ assertEquals("name5", bw.getPropertyValue("map[\"key2\"].name"));
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("array[0].name", "name5");
+ pvs.addPropertyValue("array[1].name", "name4");
+ pvs.addPropertyValue("list[0].name", "name3");
+ pvs.addPropertyValue("list[1].name", "name2");
+ pvs.addPropertyValue("map[key1].name", "name1");
+ pvs.addPropertyValue("map['key2'].name", "name0");
+ bw.setPropertyValues(pvs);
+ assertEquals("arrayname5", tb0.getName());
+ assertEquals("arrayname4", tb1.getName());
+ assertEquals("listname3", tb2.getName());
+ assertEquals("listname2", tb3.getName());
+ assertEquals("mapname1", tb4.getName());
+ assertEquals("mapname0", tb5.getName());
+ assertEquals("arrayname5", bw.getPropertyValue("array[0].name"));
+ assertEquals("arrayname4", bw.getPropertyValue("array[1].name"));
+ assertEquals("listname3", bw.getPropertyValue("list[0].name"));
+ assertEquals("listname2", bw.getPropertyValue("list[1].name"));
+ assertEquals("mapname1", bw.getPropertyValue("map[\"key1\"].name"));
+ assertEquals("mapname0", bw.getPropertyValue("map['key2'].name"));
+ }
+
+ public void testIndexedPropertiesWithIndividualCustomEditorForProperty() {
+ IndexedTestBean bean = new IndexedTestBean(false);
+ BeanWrapper bw = new BeanWrapperImpl(bean);
+ bw.registerCustomEditor(String.class, "array[0].name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("array0" + text);
+ }
+ });
+ bw.registerCustomEditor(String.class, "array[1].name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("array1" + text);
+ }
+ });
+ bw.registerCustomEditor(String.class, "list[0].name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("list0" + text);
+ }
+ });
+ bw.registerCustomEditor(String.class, "list[1].name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("list1" + text);
+ }
+ });
+ bw.registerCustomEditor(String.class, "map[key1].name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("mapkey1" + text);
+ }
+ });
+ bw.registerCustomEditor(String.class, "map[key2].name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("mapkey2" + text);
+ }
+ });
+ bean.populate();
+
+ TestBean tb0 = bean.getArray()[0];
+ TestBean tb1 = bean.getArray()[1];
+ TestBean tb2 = ((TestBean) bean.getList().get(0));
+ TestBean tb3 = ((TestBean) bean.getList().get(1));
+ TestBean tb4 = ((TestBean) bean.getMap().get("key1"));
+ TestBean tb5 = ((TestBean) bean.getMap().get("key2"));
+ assertEquals("name0", tb0.getName());
+ assertEquals("name1", tb1.getName());
+ assertEquals("name2", tb2.getName());
+ assertEquals("name3", tb3.getName());
+ assertEquals("name4", tb4.getName());
+ assertEquals("name5", tb5.getName());
+ assertEquals("name0", bw.getPropertyValue("array[0].name"));
+ assertEquals("name1", bw.getPropertyValue("array[1].name"));
+ assertEquals("name2", bw.getPropertyValue("list[0].name"));
+ assertEquals("name3", bw.getPropertyValue("list[1].name"));
+ assertEquals("name4", bw.getPropertyValue("map[key1].name"));
+ assertEquals("name5", bw.getPropertyValue("map[key2].name"));
+ assertEquals("name4", bw.getPropertyValue("map['key1'].name"));
+ assertEquals("name5", bw.getPropertyValue("map[\"key2\"].name"));
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("array[0].name", "name5");
+ pvs.addPropertyValue("array[1].name", "name4");
+ pvs.addPropertyValue("list[0].name", "name3");
+ pvs.addPropertyValue("list[1].name", "name2");
+ pvs.addPropertyValue("map[key1].name", "name1");
+ pvs.addPropertyValue("map['key2'].name", "name0");
+ bw.setPropertyValues(pvs);
+ assertEquals("array0name5", tb0.getName());
+ assertEquals("array1name4", tb1.getName());
+ assertEquals("list0name3", tb2.getName());
+ assertEquals("list1name2", tb3.getName());
+ assertEquals("mapkey1name1", tb4.getName());
+ assertEquals("mapkey2name0", tb5.getName());
+ assertEquals("array0name5", bw.getPropertyValue("array[0].name"));
+ assertEquals("array1name4", bw.getPropertyValue("array[1].name"));
+ assertEquals("list0name3", bw.getPropertyValue("list[0].name"));
+ assertEquals("list1name2", bw.getPropertyValue("list[1].name"));
+ assertEquals("mapkey1name1", bw.getPropertyValue("map[\"key1\"].name"));
+ assertEquals("mapkey2name0", bw.getPropertyValue("map['key2'].name"));
+ }
+
+ public void testNestedIndexedPropertiesWithCustomEditorForProperty() {
+ IndexedTestBean bean = new IndexedTestBean();
+ TestBean tb0 = bean.getArray()[0];
+ TestBean tb1 = bean.getArray()[1];
+ TestBean tb2 = ((TestBean) bean.getList().get(0));
+ TestBean tb3 = ((TestBean) bean.getList().get(1));
+ TestBean tb4 = ((TestBean) bean.getMap().get("key1"));
+ TestBean tb5 = ((TestBean) bean.getMap().get("key2"));
+ tb0.setNestedIndexedBean(new IndexedTestBean());
+ tb1.setNestedIndexedBean(new IndexedTestBean());
+ tb2.setNestedIndexedBean(new IndexedTestBean());
+ tb3.setNestedIndexedBean(new IndexedTestBean());
+ tb4.setNestedIndexedBean(new IndexedTestBean());
+ tb5.setNestedIndexedBean(new IndexedTestBean());
+ BeanWrapper bw = new BeanWrapperImpl(bean);
+ bw.registerCustomEditor(String.class, "array.nestedIndexedBean.array.name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("array" + text);
+ }
+
+ public String getAsText() {
+ return ((String) getValue()).substring(5);
+ }
+ });
+ bw.registerCustomEditor(String.class, "list.nestedIndexedBean.list.name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("list" + text);
+ }
+
+ public String getAsText() {
+ return ((String) getValue()).substring(4);
+ }
+ });
+ bw.registerCustomEditor(String.class, "map.nestedIndexedBean.map.name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("map" + text);
+ }
+
+ public String getAsText() {
+ return ((String) getValue()).substring(4);
+ }
+ });
+ assertEquals("name0", tb0.getName());
+ assertEquals("name1", tb1.getName());
+ assertEquals("name2", tb2.getName());
+ assertEquals("name3", tb3.getName());
+ assertEquals("name4", tb4.getName());
+ assertEquals("name5", tb5.getName());
+ assertEquals("name0", bw.getPropertyValue("array[0].nestedIndexedBean.array[0].name"));
+ assertEquals("name1", bw.getPropertyValue("array[1].nestedIndexedBean.array[1].name"));
+ assertEquals("name2", bw.getPropertyValue("list[0].nestedIndexedBean.list[0].name"));
+ assertEquals("name3", bw.getPropertyValue("list[1].nestedIndexedBean.list[1].name"));
+ assertEquals("name4", bw.getPropertyValue("map[key1].nestedIndexedBean.map[key1].name"));
+ assertEquals("name5", bw.getPropertyValue("map['key2'].nestedIndexedBean.map[\"key2\"].name"));
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("array[0].nestedIndexedBean.array[0].name", "name5");
+ pvs.addPropertyValue("array[1].nestedIndexedBean.array[1].name", "name4");
+ pvs.addPropertyValue("list[0].nestedIndexedBean.list[0].name", "name3");
+ pvs.addPropertyValue("list[1].nestedIndexedBean.list[1].name", "name2");
+ pvs.addPropertyValue("map[key1].nestedIndexedBean.map[\"key1\"].name", "name1");
+ pvs.addPropertyValue("map['key2'].nestedIndexedBean.map[key2].name", "name0");
+ bw.setPropertyValues(pvs);
+ assertEquals("arrayname5", tb0.getNestedIndexedBean().getArray()[0].getName());
+ assertEquals("arrayname4", tb1.getNestedIndexedBean().getArray()[1].getName());
+ assertEquals("listname3", ((TestBean) tb2.getNestedIndexedBean().getList().get(0)).getName());
+ assertEquals("listname2", ((TestBean) tb3.getNestedIndexedBean().getList().get(1)).getName());
+ assertEquals("mapname1", ((TestBean) tb4.getNestedIndexedBean().getMap().get("key1")).getName());
+ assertEquals("mapname0", ((TestBean) tb5.getNestedIndexedBean().getMap().get("key2")).getName());
+ assertEquals("arrayname5", bw.getPropertyValue("array[0].nestedIndexedBean.array[0].name"));
+ assertEquals("arrayname4", bw.getPropertyValue("array[1].nestedIndexedBean.array[1].name"));
+ assertEquals("listname3", bw.getPropertyValue("list[0].nestedIndexedBean.list[0].name"));
+ assertEquals("listname2", bw.getPropertyValue("list[1].nestedIndexedBean.list[1].name"));
+ assertEquals("mapname1", bw.getPropertyValue("map['key1'].nestedIndexedBean.map[key1].name"));
+ assertEquals("mapname0", bw.getPropertyValue("map[key2].nestedIndexedBean.map[\"key2\"].name"));
+ }
+
+ public void testNestedIndexedPropertiesWithIndexedCustomEditorForProperty() {
+ IndexedTestBean bean = new IndexedTestBean();
+ TestBean tb0 = bean.getArray()[0];
+ TestBean tb1 = bean.getArray()[1];
+ TestBean tb2 = ((TestBean) bean.getList().get(0));
+ TestBean tb3 = ((TestBean) bean.getList().get(1));
+ TestBean tb4 = ((TestBean) bean.getMap().get("key1"));
+ TestBean tb5 = ((TestBean) bean.getMap().get("key2"));
+ tb0.setNestedIndexedBean(new IndexedTestBean());
+ tb1.setNestedIndexedBean(new IndexedTestBean());
+ tb2.setNestedIndexedBean(new IndexedTestBean());
+ tb3.setNestedIndexedBean(new IndexedTestBean());
+ tb4.setNestedIndexedBean(new IndexedTestBean());
+ tb5.setNestedIndexedBean(new IndexedTestBean());
+ BeanWrapper bw = new BeanWrapperImpl(bean);
+ bw.registerCustomEditor(String.class, "array[0].nestedIndexedBean.array[0].name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("array" + text);
+ }
+ });
+ bw.registerCustomEditor(String.class, "list.nestedIndexedBean.list[1].name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("list" + text);
+ }
+ });
+ bw.registerCustomEditor(String.class, "map[key1].nestedIndexedBean.map.name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("map" + text);
+ }
+ });
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("array[0].nestedIndexedBean.array[0].name", "name5");
+ pvs.addPropertyValue("array[1].nestedIndexedBean.array[1].name", "name4");
+ pvs.addPropertyValue("list[0].nestedIndexedBean.list[0].name", "name3");
+ pvs.addPropertyValue("list[1].nestedIndexedBean.list[1].name", "name2");
+ pvs.addPropertyValue("map[key1].nestedIndexedBean.map[\"key1\"].name", "name1");
+ pvs.addPropertyValue("map['key2'].nestedIndexedBean.map[key2].name", "name0");
+ bw.setPropertyValues(pvs);
+ assertEquals("arrayname5", tb0.getNestedIndexedBean().getArray()[0].getName());
+ assertEquals("name4", tb1.getNestedIndexedBean().getArray()[1].getName());
+ assertEquals("name3", ((TestBean) tb2.getNestedIndexedBean().getList().get(0)).getName());
+ assertEquals("listname2", ((TestBean) tb3.getNestedIndexedBean().getList().get(1)).getName());
+ assertEquals("mapname1", ((TestBean) tb4.getNestedIndexedBean().getMap().get("key1")).getName());
+ assertEquals("name0", ((TestBean) tb5.getNestedIndexedBean().getMap().get("key2")).getName());
+ }
+
+ public void testIndexedPropertiesWithDirectAccessAndPropertyEditors() {
+ IndexedTestBean bean = new IndexedTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(bean);
+ bw.registerCustomEditor(TestBean.class, "array", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue(new TestBean("array" + text, 99));
+ }
+
+ public String getAsText() {
+ return ((TestBean) getValue()).getName();
+ }
+ });
+ bw.registerCustomEditor(TestBean.class, "list", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue(new TestBean("list" + text, 99));
+ }
+
+ public String getAsText() {
+ return ((TestBean) getValue()).getName();
+ }
+ });
+ bw.registerCustomEditor(TestBean.class, "map", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue(new TestBean("map" + text, 99));
+ }
+
+ public String getAsText() {
+ return ((TestBean) getValue()).getName();
+ }
+ });
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("array[0]", "a");
+ pvs.addPropertyValue("array[1]", "b");
+ pvs.addPropertyValue("list[0]", "c");
+ pvs.addPropertyValue("list[1]", "d");
+ pvs.addPropertyValue("map[key1]", "e");
+ pvs.addPropertyValue("map['key2']", "f");
+ bw.setPropertyValues(pvs);
+ assertEquals("arraya", bean.getArray()[0].getName());
+ assertEquals("arrayb", bean.getArray()[1].getName());
+ assertEquals("listc", ((TestBean) bean.getList().get(0)).getName());
+ assertEquals("listd", ((TestBean) bean.getList().get(1)).getName());
+ assertEquals("mape", ((TestBean) bean.getMap().get("key1")).getName());
+ assertEquals("mapf", ((TestBean) bean.getMap().get("key2")).getName());
+ }
+
+ public void testIndexedPropertiesWithDirectAccessAndSpecificPropertyEditors() {
+ IndexedTestBean bean = new IndexedTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(bean);
+ bw.registerCustomEditor(TestBean.class, "array[0]", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue(new TestBean("array0" + text, 99));
+ }
+
+ public String getAsText() {
+ return ((TestBean) getValue()).getName();
+ }
+ });
+ bw.registerCustomEditor(TestBean.class, "array[1]", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue(new TestBean("array1" + text, 99));
+ }
+
+ public String getAsText() {
+ return ((TestBean) getValue()).getName();
+ }
+ });
+ bw.registerCustomEditor(TestBean.class, "list[0]", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue(new TestBean("list0" + text, 99));
+ }
+
+ public String getAsText() {
+ return ((TestBean) getValue()).getName();
+ }
+ });
+ bw.registerCustomEditor(TestBean.class, "list[1]", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue(new TestBean("list1" + text, 99));
+ }
+
+ public String getAsText() {
+ return ((TestBean) getValue()).getName();
+ }
+ });
+ bw.registerCustomEditor(TestBean.class, "map[key1]", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue(new TestBean("mapkey1" + text, 99));
+ }
+
+ public String getAsText() {
+ return ((TestBean) getValue()).getName();
+ }
+ });
+ bw.registerCustomEditor(TestBean.class, "map[key2]", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue(new TestBean("mapkey2" + text, 99));
+ }
+
+ public String getAsText() {
+ return ((TestBean) getValue()).getName();
+ }
+ });
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("array[0]", "a");
+ pvs.addPropertyValue("array[1]", "b");
+ pvs.addPropertyValue("list[0]", "c");
+ pvs.addPropertyValue("list[1]", "d");
+ pvs.addPropertyValue("map[key1]", "e");
+ pvs.addPropertyValue("map['key2']", "f");
+ bw.setPropertyValues(pvs);
+ assertEquals("array0a", bean.getArray()[0].getName());
+ assertEquals("array1b", bean.getArray()[1].getName());
+ assertEquals("list0c", ((TestBean) bean.getList().get(0)).getName());
+ assertEquals("list1d", ((TestBean) bean.getList().get(1)).getName());
+ assertEquals("mapkey1e", ((TestBean) bean.getMap().get("key1")).getName());
+ assertEquals("mapkey2f", ((TestBean) bean.getMap().get("key2")).getName());
+ }
+
+ public void testIndexedPropertiesWithListPropertyEditor() {
+ IndexedTestBean bean = new IndexedTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(bean);
+ bw.registerCustomEditor(List.class, "list", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ List result = new ArrayList();
+ result.add(new TestBean("list" + text, 99));
+ setValue(result);
+ }
+ });
+ bw.setPropertyValue("list", "1");
+ assertEquals("list1", ((TestBean) bean.getList().get(0)).getName());
+ bw.setPropertyValue("list[0]", "test");
+ assertEquals("test", bean.getList().get(0));
+ }
+
+ public void testConversionToOldCollections() throws PropertyVetoException {
+ OldCollectionsBean tb = new OldCollectionsBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ bw.registerCustomEditor(Vector.class, new CustomCollectionEditor(Vector.class));
+ bw.registerCustomEditor(Hashtable.class, new CustomMapEditor(Hashtable.class));
+
+ bw.setPropertyValue("vector", new String[] {"a", "b"});
+ assertEquals(2, tb.getVector().size());
+ assertEquals("a", tb.getVector().get(0));
+ assertEquals("b", tb.getVector().get(1));
+
+ bw.setPropertyValue("hashtable", Collections.singletonMap("foo", "bar"));
+ assertEquals(1, tb.getHashtable().size());
+ assertEquals("bar", tb.getHashtable().get("foo"));
+ }
+
+ public void testUninitializedArrayPropertyWithCustomEditor() {
+ IndexedTestBean bean = new IndexedTestBean(false);
+ BeanWrapper bw = new BeanWrapperImpl(bean);
+ PropertyEditor pe = new CustomNumberEditor(Integer.class, true);
+ bw.registerCustomEditor(null, "list.age", pe);
+ TestBean tb = new TestBean();
+ bw.setPropertyValue("list", new ArrayList());
+ bw.setPropertyValue("list[0]", tb);
+ assertEquals(tb, bean.getList().get(0));
+ assertEquals(pe, bw.findCustomEditor(int.class, "list.age"));
+ assertEquals(pe, bw.findCustomEditor(null, "list.age"));
+ assertEquals(pe, bw.findCustomEditor(int.class, "list[0].age"));
+ assertEquals(pe, bw.findCustomEditor(null, "list[0].age"));
+ }
+
+ public void testArrayToArrayConversion() throws PropertyVetoException {
+ IndexedTestBean tb = new IndexedTestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ bw.registerCustomEditor(TestBean.class, new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue(new TestBean(text, 99));
+ }
+ });
+ bw.setPropertyValue("array", new String[] {"a", "b"});
+ assertEquals(2, tb.getArray().length);
+ assertEquals("a", tb.getArray()[0].getName());
+ assertEquals("b", tb.getArray()[1].getName());
+ }
+
+ public void testArrayToStringConversion() throws PropertyVetoException {
+ TestBean tb = new TestBean();
+ BeanWrapper bw = new BeanWrapperImpl(tb);
+ bw.registerCustomEditor(String.class, new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("-" + text + "-");
+ }
+ });
+ bw.setPropertyValue("name", new String[] {"a", "b"});
+ assertEquals("-a,b-", tb.getName());
+ }
+
+ public void testClassArrayEditorSunnyDay() throws Exception {
+ ClassArrayEditor classArrayEditor = new ClassArrayEditor();
+ classArrayEditor.setAsText("java.lang.String,java.util.HashMap");
+ Class[] classes = (Class[]) classArrayEditor.getValue();
+ assertEquals(2, classes.length);
+ assertEquals(String.class, classes[0]);
+ assertEquals(HashMap.class, classes[1]);
+ assertEquals("java.lang.String,java.util.HashMap", classArrayEditor.getAsText());
+ // ensure setAsText can consume the return value of getAsText
+ classArrayEditor.setAsText(classArrayEditor.getAsText());
+ }
+
+ public void testClassArrayEditorSunnyDayWithArrayTypes() throws Exception {
+ ClassArrayEditor classArrayEditor = new ClassArrayEditor();
+ classArrayEditor.setAsText("java.lang.String[],java.util.Map[],int[],float[][][]");
+ Class[] classes = (Class[]) classArrayEditor.getValue();
+ assertEquals(4, classes.length);
+ assertEquals(String[].class, classes[0]);
+ assertEquals(Map[].class, classes[1]);
+ assertEquals(int[].class, classes[2]);
+ assertEquals(float[][][].class, classes[3]);
+ assertEquals("java.lang.String[],java.util.Map[],int[],float[][][]", classArrayEditor.getAsText());
+ // ensure setAsText can consume the return value of getAsText
+ classArrayEditor.setAsText(classArrayEditor.getAsText());
+ }
+
+ public void testClassArrayEditorSetAsTextWithNull() throws Exception {
+ ClassArrayEditor editor = new ClassArrayEditor();
+ editor.setAsText(null);
+ assertNull(editor.getValue());
+ assertEquals("", editor.getAsText());
+ }
+
+ public void testClassArrayEditorSetAsTextWithEmptyString() throws Exception {
+ ClassArrayEditor editor = new ClassArrayEditor();
+ editor.setAsText("");
+ assertNull(editor.getValue());
+ assertEquals("", editor.getAsText());
+ }
+
+ public void testClassArrayEditorSetAsTextWithWhitespaceString() throws Exception {
+ ClassArrayEditor editor = new ClassArrayEditor();
+ editor.setAsText("\n");
+ assertNull(editor.getValue());
+ assertEquals("", editor.getAsText());
+ }
+
+ public void testCharsetEditor() throws Exception {
+ CharsetEditor editor = new CharsetEditor();
+ String name = "UTF-8";
+ editor.setAsText(name);
+ Charset charset = Charset.forName(name);
+ assertEquals("Invalid Charset conversion", charset, editor.getValue());
+ editor.setValue(charset);
+ assertEquals("Invalid Charset conversion", name, editor.getAsText());
+ }
+
+
+ private static class TestBeanEditor extends PropertyEditorSupport {
+
+ public void setAsText(String text) {
+ TestBean tb = new TestBean();
+ StringTokenizer st = new StringTokenizer(text, "_");
+ tb.setName(st.nextToken());
+ tb.setAge(Integer.parseInt(st.nextToken()));
+ setValue(tb);
+ }
+ }
+
+
+ private static class OldValueAccessingTestBeanEditor extends PropertyEditorSupport {
+
+ public void setAsText(String text) {
+ TestBean tb = new TestBean();
+ StringTokenizer st = new StringTokenizer(text, "_");
+ tb.setName(st.nextToken());
+ tb.setAge(Integer.parseInt(st.nextToken()));
+ if (!tb.equals(getValue())) {
+ setValue(tb);
+ }
+ }
+ }
+
+
+ private static class PrimitiveArrayBean {
+
+ private byte[] byteArray;
+
+ private char[] charArray;
+
+ public byte[] getByteArray() {
+ return byteArray;
+ }
+
+ public void setByteArray(byte[] byteArray) {
+ this.byteArray = byteArray;
+ }
+
+ public char[] getCharArray() {
+ return charArray;
+ }
+
+ public void setCharArray(char[] charArray) {
+ this.charArray = charArray;
+ }
+ }
+
+
+ private static class CharBean {
+
+ private char myChar;
+
+ private Character myCharacter;
+
+ public char getMyChar() {
+ return myChar;
+ }
+
+ public void setMyChar(char myChar) {
+ this.myChar = myChar;
+ }
+
+ public Character getMyCharacter() {
+ return myCharacter;
+ }
+
+ public void setMyCharacter(Character myCharacter) {
+ this.myCharacter = myCharacter;
+ }
+ }
+
+
+ private static class OldCollectionsBean {
+
+ private Vector vector;
+
+ private Hashtable hashtable;
+
+ public Vector getVector() {
+ return vector;
+ }
+
+ public void setVector(Vector vector) {
+ this.vector = vector;
+ }
+
+ public Hashtable getHashtable() {
+ return hashtable;
+ }
+
+ public void setHashtable(Hashtable hashtable) {
+ this.hashtable = hashtable;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/FileEditorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/FileEditorTests.java
new file mode 100644
index 00000000000..3686a74ab98
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/FileEditorTests.java
@@ -0,0 +1,86 @@
+
+package org.springframework.beans.propertyeditors;
+
+import java.beans.PropertyEditor;
+import java.io.File;
+
+import junit.framework.TestCase;
+
+import org.springframework.test.AssertThrows;
+import org.springframework.util.ClassUtils;
+
+/**
+ * @author Thomas Risberg
+ */
+public final class FileEditorTests extends TestCase {
+
+ public void testClasspathFileName() throws Exception {
+ PropertyEditor fileEditor = new FileEditor();
+ fileEditor.setAsText("classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) + "/"
+ + ClassUtils.getShortName(getClass()) + ".class");
+ Object value = fileEditor.getValue();
+ assertTrue(value instanceof File);
+ File file = (File) value;
+ assertTrue(file.exists());
+ }
+
+ public void testWithNonExistentResource() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+
+ public void test() throws Exception {
+ PropertyEditor propertyEditor = new FileEditor();
+ propertyEditor.setAsText("classpath:no_way_this_file_is_found.doc");
+ }
+ }.runTest();
+ }
+
+ public void testWithNonExistentFile() throws Exception {
+ PropertyEditor fileEditor = new FileEditor();
+ fileEditor.setAsText("file:no_way_this_file_is_found.doc");
+ Object value = fileEditor.getValue();
+ assertTrue(value instanceof File);
+ File file = (File) value;
+ assertTrue(!file.exists());
+ }
+
+ public void testAbsoluteFileName() throws Exception {
+ PropertyEditor fileEditor = new FileEditor();
+ fileEditor.setAsText("/no_way_this_file_is_found.doc");
+ Object value = fileEditor.getValue();
+ assertTrue(value instanceof File);
+ File file = (File) value;
+ assertTrue(!file.exists());
+ }
+
+ public void testUnqualifiedFileNameFound() throws Exception {
+ PropertyEditor fileEditor = new FileEditor();
+ String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" + ClassUtils.getShortName(getClass())
+ + ".class";
+ fileEditor.setAsText(fileName);
+ Object value = fileEditor.getValue();
+ assertTrue(value instanceof File);
+ File file = (File) value;
+ assertTrue(file.exists());
+ String absolutePath = file.getAbsolutePath();
+ if (File.separatorChar == '\\') {
+ absolutePath = absolutePath.replace('\\', '/');
+ }
+ assertTrue(absolutePath.endsWith(fileName));
+ }
+
+ public void testUnqualifiedFileNameNotFound() throws Exception {
+ PropertyEditor fileEditor = new FileEditor();
+ String fileName = ClassUtils.classPackageAsResourcePath(getClass()) + "/" + ClassUtils.getShortName(getClass())
+ + ".clazz";
+ fileEditor.setAsText(fileName);
+ Object value = fileEditor.getValue();
+ assertTrue(value instanceof File);
+ File file = (File) value;
+ assertFalse(file.exists());
+ String absolutePath = file.getAbsolutePath();
+ if (File.separatorChar == '\\') {
+ absolutePath = absolutePath.replace('\\', '/');
+ }
+ assertTrue(absolutePath.endsWith(fileName));
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/InputStreamEditorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/InputStreamEditorTests.java
new file mode 100644
index 00000000000..5b83da915e0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/InputStreamEditorTests.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.propertyeditors;
+
+import junit.framework.TestCase;
+import org.springframework.test.AssertThrows;
+import org.springframework.util.ClassUtils;
+
+import java.io.InputStream;
+
+/**
+ * Unit tests for the {@link InputStreamEditor} class.
+ *
+ * @author Rick Evans
+ */
+public final class InputStreamEditorTests extends TestCase {
+
+ public void testCtorWithNullResourceEditor() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new InputStreamEditor(null);
+ }
+ }.runTest();
+ }
+
+ public void testSunnyDay() throws Exception {
+ InputStream stream = null;
+ try {
+ String resource = "classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) + "/" + ClassUtils.getShortName(getClass()) + ".class";
+ InputStreamEditor editor = new InputStreamEditor();
+ editor.setAsText(resource);
+ Object value = editor.getValue();
+ assertNotNull(value);
+ assertTrue(value instanceof InputStream);
+ stream = (InputStream) value;
+ assertTrue(stream.available() > 0);
+ } finally {
+ if (stream != null) {
+ stream.close();
+ }
+ }
+ }
+
+ public void testWhenResourceDoesNotExist() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ String resource = "classpath:bingo!";
+ InputStreamEditor editor = new InputStreamEditor();
+ editor.setAsText(resource);
+ }
+ }.runTest();
+ }
+
+ public void testGetAsTextReturnsNullByDefault() throws Exception {
+ assertNull(new InputStreamEditor().getAsText());
+ String resource = "classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) + "/" + ClassUtils.getShortName(getClass()) + ".class";
+ InputStreamEditor editor = new InputStreamEditor();
+ editor.setAsText(resource);
+ assertNull(editor.getAsText());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/PropertiesEditorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/PropertiesEditorTests.java
new file mode 100644
index 00000000000..3e8266ea2d2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/PropertiesEditorTests.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.propertyeditors;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+/**
+ * Test the conversion of Strings to {@link java.util.Properties} objects,
+ * and other property editors.
+ *
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ */
+public class PropertiesEditorTests extends TestCase {
+
+ public void testOneProperty() {
+ String s = "foo=bar";
+ PropertiesEditor pe= new PropertiesEditor();
+ pe.setAsText(s);
+ Properties p = (Properties) pe.getValue();
+ assertTrue("contains one entry", p.entrySet().size() == 1);
+ assertTrue("foo=bar", p.get("foo").equals("bar"));
+ }
+
+ public void testTwoProperties() {
+ String s = "foo=bar with whitespace\n" +
+ "me=mi";
+ PropertiesEditor pe= new PropertiesEditor();
+ pe.setAsText(s);
+ Properties p = (Properties) pe.getValue();
+ assertTrue("contains two entries", p.entrySet().size() == 2);
+ assertTrue("foo=bar with whitespace", p.get("foo").equals("bar with whitespace"));
+ assertTrue("me=mi", p.get("me").equals("mi"));
+ }
+
+ public void testHandlesEqualsInValue() {
+ String s = "foo=bar\n" +
+ "me=mi\n" +
+ "x=y=z";
+ PropertiesEditor pe= new PropertiesEditor();
+ pe.setAsText(s);
+ Properties p = (Properties) pe.getValue();
+ assertTrue("contains two entries", p.entrySet().size() == 3);
+ assertTrue("foo=bar", p.get("foo").equals("bar"));
+ assertTrue("me=mi", p.get("me").equals("mi"));
+ assertTrue("x='y=z'", p.get("x").equals("y=z"));
+ }
+
+ public void testHandlesEmptyProperty() {
+ String s = "foo=bar\nme=mi\nx=";
+ PropertiesEditor pe= new PropertiesEditor();
+ pe.setAsText(s);
+ Properties p = (Properties) pe.getValue();
+ assertTrue("contains two entries", p.entrySet().size() == 3);
+ assertTrue("foo=bar", p.get("foo").equals("bar"));
+ assertTrue("me=mi", p.get("me").equals("mi"));
+ assertTrue("x='y=z'", p.get("x").equals(""));
+ }
+
+ public void testHandlesEmptyPropertyWithoutEquals() {
+ String s = "foo\nme=mi\nx=x";
+ PropertiesEditor pe= new PropertiesEditor();
+ pe.setAsText(s);
+ Properties p = (Properties) pe.getValue();
+ assertTrue("contains three entries", p.entrySet().size() == 3);
+ assertTrue("foo is empty", p.get("foo").equals(""));
+ assertTrue("me=mi", p.get("me").equals("mi"));
+ }
+
+ /**
+ * Comments begin with #
+ */
+ public void testIgnoresCommentLinesAndEmptyLines() {
+ String s = "#Ignore this comment\n" +
+ "foo=bar\n" +
+ "#Another=comment more junk /\n" +
+ "me=mi\n" +
+ "x=x\n" +
+ "\n";
+ PropertiesEditor pe= new PropertiesEditor();
+ pe.setAsText(s);
+ Properties p = (Properties) pe.getValue();
+ assertTrue("contains three entries", p.entrySet().size() == 3);
+ assertTrue("foo is bar", p.get("foo").equals("bar"));
+ assertTrue("me=mi", p.get("me").equals("mi"));
+ }
+
+ /**
+ * We'll typically align by indenting with tabs or spaces.
+ * These should be ignored if at the beginning of a line.
+ * We must ensure that comment lines beginning with whitespace are
+ * still ignored: The standard syntax doesn't allow this on JDK 1.3.
+ */
+ public void testIgnoresLeadingSpacesAndTabs() {
+ String s = " #Ignore this comment\n" +
+ "\t\tfoo=bar\n" +
+ "\t#Another comment more junk \n" +
+ " me=mi\n" +
+ "x=x\n" +
+ "\n";
+ PropertiesEditor pe= new PropertiesEditor();
+ pe.setAsText(s);
+ Properties p = (Properties) pe.getValue();
+ assertTrue("contains 3 entries, not " + p.size(), p.size() == 3);
+ assertTrue("foo is bar", p.get("foo").equals("bar"));
+ assertTrue("me=mi", p.get("me").equals("mi"));
+ }
+
+ public void testNull() {
+ PropertiesEditor pe= new PropertiesEditor();
+ pe.setAsText(null);
+ Properties p = (Properties) pe.getValue();
+ assertEquals(0, p.size());
+ }
+
+ public void testEmptyString() {
+ PropertiesEditor pe = new PropertiesEditor();
+ pe.setAsText("");
+ Properties p = (Properties) pe.getValue();
+ assertTrue("empty string means empty properties", p.isEmpty());
+ }
+
+ public void testUsingMapAsValueSource() throws Exception {
+ Map map = new HashMap();
+ map.put("one", "1");
+ map.put("two", "2");
+ map.put("three", "3");
+ PropertiesEditor pe = new PropertiesEditor();
+ pe.setValue(map);
+ Object value = pe.getValue();
+ assertNotNull(value);
+ assertTrue(value instanceof Properties);
+ Properties props = (Properties) value;
+ assertEquals(3, props.size());
+ assertEquals("1", props.getProperty("one"));
+ assertEquals("2", props.getProperty("two"));
+ assertEquals("3", props.getProperty("three"));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/ResourceBundleEditorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/ResourceBundleEditorTests.java
new file mode 100644
index 00000000000..444e3a3d7f8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/ResourceBundleEditorTests.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.propertyeditors;
+
+import junit.framework.TestCase;
+import org.springframework.test.AssertThrows;
+
+import java.util.ResourceBundle;
+
+/**
+ * Unit tests for the {@link ResourceBundleEditor} class.
+ *
+ * @author Rick Evans
+ */
+public final class ResourceBundleEditorTests extends TestCase {
+
+ private static final String BASE_NAME = ResourceBundleEditorTests.class.getName();
+ private static final String MESSAGE_KEY = "punk";
+
+
+ public void testSetAsTextWithJustBaseName() throws Exception {
+ ResourceBundleEditor editor = new ResourceBundleEditor();
+ editor.setAsText(BASE_NAME);
+ Object value = editor.getValue();
+ assertNotNull("Returned ResourceBundle was null (must not be for valid setAsText(..) call).", value);
+ assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).", value instanceof ResourceBundle);
+ ResourceBundle bundle = (ResourceBundle) value;
+ String string = bundle.getString(MESSAGE_KEY);
+ assertEquals(MESSAGE_KEY, string);
+ }
+
+ public void testSetAsTextWithBaseNameThatEndsInDefaultSeparator() throws Exception {
+ ResourceBundleEditor editor = new ResourceBundleEditor();
+ editor.setAsText(BASE_NAME + "_");
+ Object value = editor.getValue();
+ assertNotNull("Returned ResourceBundle was null (must not be for valid setAsText(..) call).", value);
+ assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).", value instanceof ResourceBundle);
+ ResourceBundle bundle = (ResourceBundle) value;
+ String string = bundle.getString(MESSAGE_KEY);
+ assertEquals(MESSAGE_KEY, string);
+ }
+
+ public void testSetAsTextWithBaseNameAndLanguageCode() throws Exception {
+ ResourceBundleEditor editor = new ResourceBundleEditor();
+ editor.setAsText(BASE_NAME + "Lang" + "_en");
+ Object value = editor.getValue();
+ assertNotNull("Returned ResourceBundle was null (must not be for valid setAsText(..) call).", value);
+ assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).", value instanceof ResourceBundle);
+ ResourceBundle bundle = (ResourceBundle) value;
+ String string = bundle.getString(MESSAGE_KEY);
+ assertEquals("yob", string);
+ }
+
+ public void testSetAsTextWithBaseNameLanguageAndCountryCode() throws Exception {
+ ResourceBundleEditor editor = new ResourceBundleEditor();
+ editor.setAsText(BASE_NAME + "LangCountry" + "_en_GB");
+ Object value = editor.getValue();
+ assertNotNull("Returned ResourceBundle was null (must not be for valid setAsText(..) call).", value);
+ assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).", value instanceof ResourceBundle);
+ ResourceBundle bundle = (ResourceBundle) value;
+ String string = bundle.getString(MESSAGE_KEY);
+ assertEquals("chav", string);
+ }
+
+ public void testSetAsTextWithTheKitchenSink() throws Exception {
+ ResourceBundleEditor editor = new ResourceBundleEditor();
+ editor.setAsText(BASE_NAME + "LangCountryDialect" + "_en_GB_GLASGOW");
+ Object value = editor.getValue();
+ assertNotNull("Returned ResourceBundle was null (must not be for valid setAsText(..) call).", value);
+ assertTrue("Returned object was not a ResourceBundle (must be for valid setAsText(..) call).", value instanceof ResourceBundle);
+ ResourceBundle bundle = (ResourceBundle) value;
+ String string = bundle.getString(MESSAGE_KEY);
+ assertEquals("ned", string);
+ }
+
+ public void testSetAsTextWithNull() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ ResourceBundleEditor editor = new ResourceBundleEditor();
+ editor.setAsText(null);
+ }
+ }.runTest();
+ }
+
+ public void testSetAsTextWithEmptyString() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ ResourceBundleEditor editor = new ResourceBundleEditor();
+ editor.setAsText("");
+ }
+ }.runTest();
+ }
+
+ public void testSetAsTextWithWhiteSpaceString() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ ResourceBundleEditor editor = new ResourceBundleEditor();
+ editor.setAsText(" ");
+ }
+ }.runTest();
+ }
+
+ public void testSetAsTextWithJustSeparatorString() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ ResourceBundleEditor editor = new ResourceBundleEditor();
+ editor.setAsText("_");
+ }
+ }.runTest();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/ResourceBundleEditorTests.properties b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/ResourceBundleEditorTests.properties
new file mode 100644
index 00000000000..ecb69cb31fa
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/ResourceBundleEditorTests.properties
@@ -0,0 +1 @@
+punk=punk
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/ResourceBundleEditorTestsLangCountryDialect_en_GB_GLASGOW.properties b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/ResourceBundleEditorTestsLangCountryDialect_en_GB_GLASGOW.properties
new file mode 100644
index 00000000000..70055b65aee
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/ResourceBundleEditorTestsLangCountryDialect_en_GB_GLASGOW.properties
@@ -0,0 +1 @@
+punk=ned
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/ResourceBundleEditorTestsLangCountry_en_GB.properties b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/ResourceBundleEditorTestsLangCountry_en_GB.properties
new file mode 100644
index 00000000000..4b790a4c7bd
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/ResourceBundleEditorTestsLangCountry_en_GB.properties
@@ -0,0 +1 @@
+punk=chav
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/ResourceBundleEditorTestsLang_en.properties b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/ResourceBundleEditorTestsLang_en.properties
new file mode 100644
index 00000000000..de8a7b30222
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/ResourceBundleEditorTestsLang_en.properties
@@ -0,0 +1 @@
+punk=yob
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/StringArrayPropertyEditorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/StringArrayPropertyEditorTests.java
new file mode 100644
index 00000000000..3ef0b9efc7b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/StringArrayPropertyEditorTests.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.propertyeditors;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class StringArrayPropertyEditorTests extends TestCase {
+
+ public void testWithDefaultSeparator() throws Exception {
+ StringArrayPropertyEditor editor = new StringArrayPropertyEditor();
+ editor.setAsText("0,1,2");
+ Object value = editor.getValue();
+ assertNotNull(value);
+ assertTrue(value instanceof String[]);
+ String[] array = (String[]) value;
+ for (int i = 0; i < array.length; ++i) {
+ assertEquals("" + i, array[i]);
+ }
+ assertEquals("0,1,2", editor.getAsText());
+ }
+
+ public void testWithCustomSeparator() throws Exception {
+ StringArrayPropertyEditor editor = new StringArrayPropertyEditor(":");
+ editor.setAsText("0:1:2");
+ Object value = editor.getValue();
+ assertTrue(value instanceof String[]);
+ String[] array = (String[]) value;
+ for (int i = 0; i < array.length; ++i) {
+ assertEquals("" + i, array[i]);
+ }
+ assertEquals("0:1:2", editor.getAsText());
+ }
+
+ public void testWithCharsToDelete() throws Exception {
+ StringArrayPropertyEditor editor = new StringArrayPropertyEditor(",", "\r\n", false);
+ editor.setAsText("0\r,1,\n2");
+ Object value = editor.getValue();
+ assertTrue(value instanceof String[]);
+ String[] array = (String[]) value;
+ for (int i = 0; i < array.length; ++i) {
+ assertEquals("" + i, array[i]);
+ }
+ assertEquals("0,1,2", editor.getAsText());
+ }
+
+ public void testWithEmptyArray() throws Exception {
+ StringArrayPropertyEditor editor = new StringArrayPropertyEditor();
+ editor.setAsText("");
+ Object value = editor.getValue();
+ assertTrue(value instanceof String[]);
+ assertEquals(0, ((String[]) value).length);
+ }
+
+ public void testWithEmptyArrayAsNull() throws Exception {
+ StringArrayPropertyEditor editor = new StringArrayPropertyEditor(",", true);
+ editor.setAsText("");
+ assertNull(editor.getValue());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/URIEditorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/URIEditorTests.java
new file mode 100644
index 00000000000..c9390414211
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/URIEditorTests.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.beans.propertyeditors;
+
+import java.beans.PropertyEditor;
+import java.net.URI;
+
+import junit.framework.TestCase;
+
+import org.springframework.util.ClassUtils;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class URIEditorTests extends TestCase {
+
+ public void testStandardURI() throws Exception {
+ PropertyEditor uriEditor = new URIEditor();
+ uriEditor.setAsText("mailto:juergen.hoeller@interface21.com");
+ Object value = uriEditor.getValue();
+ assertTrue(value instanceof URI);
+ URI uri = (URI) value;
+ assertEquals(uri.toString(), uriEditor.getAsText());
+ }
+
+ public void testStandardURL() throws Exception {
+ PropertyEditor uriEditor = new URIEditor();
+ uriEditor.setAsText("http://www.springframework.org");
+ Object value = uriEditor.getValue();
+ assertTrue(value instanceof URI);
+ URI uri = (URI) value;
+ assertEquals(uri.toString(), uriEditor.getAsText());
+ }
+
+ public void testStandardURLWithWhitespace() throws Exception {
+ PropertyEditor uriEditor = new URIEditor();
+ uriEditor.setAsText(" http://www.springframework.org ");
+ Object value = uriEditor.getValue();
+ assertTrue(value instanceof URI);
+ URI uri = (URI) value;
+ assertEquals(uri.toString(), uriEditor.getAsText());
+ }
+
+ public void testClasspathURL() throws Exception {
+ PropertyEditor uriEditor = new URIEditor(getClass().getClassLoader());
+ uriEditor.setAsText("classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) +
+ "/" + ClassUtils.getShortName(getClass()) + ".class");
+ Object value = uriEditor.getValue();
+ assertTrue(value instanceof URI);
+ URI uri = (URI) value;
+ assertEquals(uri.toString(), uriEditor.getAsText());
+ assertTrue(!uri.getScheme().startsWith("classpath"));
+ }
+
+ public void testClasspathURLWithWhitespace() throws Exception {
+ PropertyEditor uriEditor = new URIEditor(getClass().getClassLoader());
+ uriEditor.setAsText(" classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) +
+ "/" + ClassUtils.getShortName(getClass()) + ".class ");
+ Object value = uriEditor.getValue();
+ assertTrue(value instanceof URI);
+ URI uri = (URI) value;
+ assertEquals(uri.toString(), uriEditor.getAsText());
+ assertTrue(!uri.getScheme().startsWith("classpath"));
+ }
+
+ public void testClasspathURLAsIs() throws Exception {
+ PropertyEditor uriEditor = new URIEditor();
+ uriEditor.setAsText("classpath:test.txt");
+ Object value = uriEditor.getValue();
+ assertTrue(value instanceof URI);
+ URI uri = (URI) value;
+ assertEquals(uri.toString(), uriEditor.getAsText());
+ assertTrue(uri.getScheme().startsWith("classpath"));
+ }
+
+ public void testWithNonExistentResource() throws Exception {
+ PropertyEditor uriEditor = new URIEditor();
+ uriEditor.setAsText("gonna:/freak/in/the/morning/freak/in/the.evening");
+ Object value = uriEditor.getValue();
+ assertTrue(value instanceof URI);
+ URI uri = (URI) value;
+ assertEquals(uri.toString(), uriEditor.getAsText());
+ }
+
+ public void testSetAsTextWithNull() throws Exception {
+ PropertyEditor uriEditor = new URIEditor();
+ uriEditor.setAsText(null);
+ assertNull(uriEditor.getValue());
+ assertEquals("", uriEditor.getAsText());
+ }
+
+ public void testGetAsTextReturnsEmptyStringIfValueNotSet() throws Exception {
+ PropertyEditor uriEditor = new URIEditor();
+ assertEquals("", uriEditor.getAsText());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/URLEditorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/URLEditorTests.java
new file mode 100644
index 00000000000..1ac1be38c3d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/propertyeditors/URLEditorTests.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.beans.propertyeditors;
+
+import java.beans.PropertyEditor;
+import java.net.URL;
+
+import junit.framework.TestCase;
+
+import org.springframework.test.AssertThrows;
+import org.springframework.util.ClassUtils;
+
+/**
+ * @author Rick Evans
+ */
+public final class URLEditorTests extends TestCase {
+
+ public void testStandardURI() throws Exception {
+ PropertyEditor urlEditor = new URLEditor();
+ urlEditor.setAsText("mailto:juergen.hoeller@interface21.com");
+ Object value = urlEditor.getValue();
+ assertTrue(value instanceof URL);
+ URL url = (URL) value;
+ assertEquals(url.toExternalForm(), urlEditor.getAsText());
+ }
+
+ public void testStandardURL() throws Exception {
+ PropertyEditor urlEditor = new URLEditor();
+ urlEditor.setAsText("http://www.springframework.org");
+ Object value = urlEditor.getValue();
+ assertTrue(value instanceof URL);
+ URL url = (URL) value;
+ assertEquals(url.toExternalForm(), urlEditor.getAsText());
+ }
+
+ public void testClasspathURL() throws Exception {
+ PropertyEditor urlEditor = new URLEditor();
+ urlEditor.setAsText("classpath:" + ClassUtils.classPackageAsResourcePath(getClass()) +
+ "/" + ClassUtils.getShortName(getClass()) + ".class");
+ Object value = urlEditor.getValue();
+ assertTrue(value instanceof URL);
+ URL url = (URL) value;
+ assertEquals(url.toExternalForm(), urlEditor.getAsText());
+ assertTrue(!url.getProtocol().startsWith("classpath"));
+ }
+
+ public void testWithNonExistentResource() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ PropertyEditor urlEditor = new URLEditor();
+ urlEditor.setAsText("gonna:/freak/in/the/morning/freak/in/the.evening");
+ }
+ }.runTest();
+ }
+
+ public void testSetAsTextWithNull() throws Exception {
+ PropertyEditor urlEditor = new URLEditor();
+ urlEditor.setAsText(null);
+ assertNull(urlEditor.getValue());
+ assertEquals("", urlEditor.getAsText());
+ }
+
+ public void testGetAsTextReturnsEmptyStringIfValueNotSet() throws Exception {
+ PropertyEditor urlEditor = new URLEditor();
+ assertEquals("", urlEditor.getAsText());
+ }
+
+ public void testCtorWithNullResourceEditor() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new URLEditor(null);
+ }
+ }.runTest();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/support/DerivedFromProtectedBaseBean.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/support/DerivedFromProtectedBaseBean.java
new file mode 100644
index 00000000000..fc41a86301f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/support/DerivedFromProtectedBaseBean.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.support;
+
+/**
+ * @author Juergen Hoeller
+ * @since 29.07.2004
+ */
+public class DerivedFromProtectedBaseBean extends ProtectedBaseBean {
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/support/PagedListHolderTests.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/support/PagedListHolderTests.java
new file mode 100644
index 00000000000..42b04bf6c02
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/support/PagedListHolderTests.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.support;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.BeanWrapper;
+import org.springframework.beans.BeanWrapperImpl;
+import org.springframework.beans.TestBean;
+
+/**
+ * @author Juergen Hoeller
+ * @author Jean-Pierre PAWLAK
+ * @since 20.05.2003
+ */
+public class PagedListHolderTests extends TestCase {
+
+ public void testPagedListHolder() {
+ TestBean tb1 = new TestBean();
+ tb1.setName("eva");
+ tb1.setAge(25);
+ TestBean tb2 = new TestBean();
+ tb2.setName("juergen");
+ tb2.setAge(99);
+ TestBean tb3 = new TestBean();
+ tb3.setName("Rod");
+ tb3.setAge(32);
+ List tbs = new ArrayList();
+ tbs.add(tb1);
+ tbs.add(tb2);
+ tbs.add(tb3);
+
+ PagedListHolder holder = new PagedListHolder(tbs);
+ assertTrue("Correct source", holder.getSource() == tbs);
+ assertTrue("Correct number of elements", holder.getNrOfElements() == 3);
+ assertTrue("Correct number of pages", holder.getPageCount() == 1);
+ assertTrue("Correct page size", holder.getPageSize() == PagedListHolder.DEFAULT_PAGE_SIZE);
+ assertTrue("Correct page number", holder.getPage() == 0);
+ assertTrue("First page", holder.isFirstPage());
+ assertTrue("Last page", holder.isLastPage());
+ assertTrue("Correct first element", holder.getFirstElementOnPage() == 0);
+ assertTrue("Correct first element", holder.getLastElementOnPage() == 2);
+ assertTrue("Correct page list size", holder.getPageList().size() == 3);
+ assertTrue("Correct page list contents", holder.getPageList().get(0) == tb1);
+ assertTrue("Correct page list contents", holder.getPageList().get(1) == tb2);
+ assertTrue("Correct page list contents", holder.getPageList().get(2) == tb3);
+
+ holder.setPageSize(2);
+ assertTrue("Correct number of pages", holder.getPageCount() == 2);
+ assertTrue("Correct page size", holder.getPageSize() == 2);
+ assertTrue("Correct page number", holder.getPage() == 0);
+ assertTrue("First page", holder.isFirstPage());
+ assertFalse("Last page", holder.isLastPage());
+ assertTrue("Correct first element", holder.getFirstElementOnPage() == 0);
+ assertTrue("Correct last element", holder.getLastElementOnPage() == 1);
+ assertTrue("Correct page list size", holder.getPageList().size() == 2);
+ assertTrue("Correct page list contents", holder.getPageList().get(0) == tb1);
+ assertTrue("Correct page list contents", holder.getPageList().get(1) == tb2);
+
+ holder.setPage(1);
+ assertTrue("Correct page number", holder.getPage() == 1);
+ assertFalse("First page", holder.isFirstPage());
+ assertTrue("Last page", holder.isLastPage());
+ assertTrue("Correct first element", holder.getFirstElementOnPage() == 2);
+ assertTrue("Correct last element", holder.getLastElementOnPage() == 2);
+ assertTrue("Correct page list size", holder.getPageList().size() == 1);
+ assertTrue("Correct page list contents", holder.getPageList().get(0) == tb3);
+
+ holder.setPageSize(3);
+ assertTrue("Correct number of pages", holder.getPageCount() == 1);
+ assertTrue("Correct page size", holder.getPageSize() == 3);
+ assertTrue("Correct page number", holder.getPage() == 0);
+ assertTrue("First page", holder.isFirstPage());
+ assertTrue("Last page", holder.isLastPage());
+ assertTrue("Correct first element", holder.getFirstElementOnPage() == 0);
+ assertTrue("Correct last element", holder.getLastElementOnPage() == 2);
+
+ holder.setPage(1);
+ holder.setPageSize(2);
+ assertTrue("Correct number of pages", holder.getPageCount() == 2);
+ assertTrue("Correct page size", holder.getPageSize() == 2);
+ assertTrue("Correct page number", holder.getPage() == 1);
+ assertFalse("First page", holder.isFirstPage());
+ assertTrue("Last page", holder.isLastPage());
+ assertTrue("Correct first element", holder.getFirstElementOnPage() == 2);
+ assertTrue("Correct last element", holder.getLastElementOnPage() == 2);
+
+ holder.setPageSize(2);
+ holder.setPage(1);
+ ((MutableSortDefinition) holder.getSort()).setProperty("name");
+ ((MutableSortDefinition) holder.getSort()).setIgnoreCase(false);
+ holder.resort();
+ assertTrue("Correct source", holder.getSource() == tbs);
+ assertTrue("Correct number of elements", holder.getNrOfElements() == 3);
+ assertTrue("Correct number of pages", holder.getPageCount() == 2);
+ assertTrue("Correct page size", holder.getPageSize() == 2);
+ assertTrue("Correct page number", holder.getPage() == 0);
+ assertTrue("First page", holder.isFirstPage());
+ assertFalse("Last page", holder.isLastPage());
+ assertTrue("Correct first element", holder.getFirstElementOnPage() == 0);
+ assertTrue("Correct last element", holder.getLastElementOnPage() == 1);
+ assertTrue("Correct page list size", holder.getPageList().size() == 2);
+ assertTrue("Correct page list contents", holder.getPageList().get(0) == tb3);
+ assertTrue("Correct page list contents", holder.getPageList().get(1) == tb1);
+
+ ((MutableSortDefinition) holder.getSort()).setProperty("name");
+ holder.resort();
+ assertTrue("Correct page list contents", holder.getPageList().get(0) == tb2);
+ assertTrue("Correct page list contents", holder.getPageList().get(1) == tb1);
+
+ ((MutableSortDefinition) holder.getSort()).setProperty("name");
+ holder.resort();
+ assertTrue("Correct page list contents", holder.getPageList().get(0) == tb3);
+ assertTrue("Correct page list contents", holder.getPageList().get(1) == tb1);
+
+ holder.setPage(1);
+ assertTrue("Correct page list size", holder.getPageList().size() == 1);
+ assertTrue("Correct page list contents", holder.getPageList().get(0) == tb2);
+
+ ((MutableSortDefinition) holder.getSort()).setProperty("age");
+ holder.resort();
+ assertTrue("Correct page list contents", holder.getPageList().get(0) == tb1);
+ assertTrue("Correct page list contents", holder.getPageList().get(1) == tb3);
+
+ ((MutableSortDefinition) holder.getSort()).setIgnoreCase(true);
+ holder.resort();
+ assertTrue("Correct page list contents", holder.getPageList().get(0) == tb1);
+ assertTrue("Correct page list contents", holder.getPageList().get(1) == tb3);
+
+ holder.nextPage();
+ assertEquals(1, holder.getPage());
+ holder.previousPage();
+ assertEquals(0, holder.getPage());
+ holder.nextPage();
+ assertEquals(1, holder.getPage());
+ holder.nextPage();
+ assertEquals(1, holder.getPage());
+ holder.previousPage();
+ assertEquals(0, holder.getPage());
+ holder.previousPage();
+ assertEquals(0, holder.getPage());
+ }
+
+
+
+ public static class MockFilter {
+
+ private String name = "";
+ private String age = "";
+ private String extendedInfo = "";
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getAge() {
+ return age;
+ }
+
+ public void setAge(String age) {
+ this.age = age;
+ }
+
+ public String getExtendedInfo() {
+ return extendedInfo;
+ }
+
+ public void setExtendedInfo(String extendedInfo) {
+ this.extendedInfo = extendedInfo;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof MockFilter)) return false;
+
+ final MockFilter mockFilter = (MockFilter) o;
+
+ if (!age.equals(mockFilter.age)) return false;
+ if (!extendedInfo.equals(mockFilter.extendedInfo)) return false;
+ if (!name.equals(mockFilter.name)) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = name.hashCode();
+ result = 29 * result + age.hashCode();
+ result = 29 * result + extendedInfo.hashCode();
+ return result;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/beans/support/ProtectedBaseBean.java b/org.springframework.testsuite/src/test/java/org/springframework/beans/support/ProtectedBaseBean.java
new file mode 100644
index 00000000000..84c8e675a0b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/beans/support/ProtectedBaseBean.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.beans.support;
+
+/**
+ * @author Juergen Hoeller
+ * @since 29.07.2004
+ */
+class ProtectedBaseBean {
+
+ private String someProperty;
+
+ public void setSomeProperty(String someProperty) {
+ this.someProperty = someProperty;
+ }
+
+ public String getSomeProperty() {
+ return someProperty;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/cache/ehcache/EhCacheSupportTests.java b/org.springframework.testsuite/src/test/java/org/springframework/cache/ehcache/EhCacheSupportTests.java
new file mode 100644
index 00000000000..d187414aa14
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/cache/ehcache/EhCacheSupportTests.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.cache.ehcache;
+
+import junit.framework.TestCase;
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.CacheManager;
+import net.sf.ehcache.Ehcache;
+import net.sf.ehcache.constructs.blocking.BlockingCache;
+import net.sf.ehcache.constructs.blocking.CacheEntryFactory;
+import net.sf.ehcache.constructs.blocking.SelfPopulatingCache;
+import net.sf.ehcache.constructs.blocking.UpdatingCacheEntryFactory;
+import net.sf.ehcache.constructs.blocking.UpdatingSelfPopulatingCache;
+
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Dmitriy Kopylenko
+ * @author Juergen Hoeller
+ * @since 27.09.2004
+ */
+public class EhCacheSupportTests extends TestCase {
+
+ public void testLoadingBlankCacheManager() throws Exception {
+ EhCacheManagerFactoryBean cacheManagerFb = new EhCacheManagerFactoryBean();
+ assertEquals(CacheManager.class, cacheManagerFb.getObjectType());
+ assertTrue("Singleton property", cacheManagerFb.isSingleton());
+ cacheManagerFb.afterPropertiesSet();
+ try {
+ CacheManager cm = (CacheManager) cacheManagerFb.getObject();
+ assertTrue("Loaded CacheManager with no caches", cm.getCacheNames().length == 0);
+ Cache myCache1 = cm.getCache("myCache1");
+ assertTrue("No myCache1 defined", myCache1 == null);
+ }
+ finally {
+ cacheManagerFb.destroy();
+ }
+ }
+
+ public void testLoadingCacheManagerFromConfigFile() throws Exception {
+ EhCacheManagerFactoryBean cacheManagerFb = new EhCacheManagerFactoryBean();
+ cacheManagerFb.setConfigLocation(new ClassPathResource("testEhcache.xml", getClass()));
+ cacheManagerFb.setCacheManagerName("myCacheManager");
+ cacheManagerFb.afterPropertiesSet();
+ try {
+ CacheManager cm = (CacheManager) cacheManagerFb.getObject();
+ assertTrue("Correct number of caches loaded", cm.getCacheNames().length == 1);
+ Cache myCache1 = cm.getCache("myCache1");
+ assertFalse("myCache1 is not eternal", myCache1.isEternal());
+ assertTrue("myCache1.maxElements == 300", myCache1.getMaxElementsInMemory() == 300);
+ }
+ finally {
+ cacheManagerFb.destroy();
+ }
+ }
+
+ public void testEhCacheFactoryBeanWithDefaultCacheManager() throws Exception {
+ doTestEhCacheFactoryBean(false);
+ }
+
+ public void testEhCacheFactoryBeanWithExplicitCacheManager() throws Exception {
+ doTestEhCacheFactoryBean(true);
+ }
+
+ private void doTestEhCacheFactoryBean(boolean useCacheManagerFb) throws Exception {
+ Cache cache = null;
+ EhCacheManagerFactoryBean cacheManagerFb = null;
+ try {
+ EhCacheFactoryBean cacheFb = new EhCacheFactoryBean();
+ assertEquals(Ehcache.class, cacheFb.getObjectType());
+ assertTrue("Singleton property", cacheFb.isSingleton());
+ if (useCacheManagerFb) {
+ cacheManagerFb = new EhCacheManagerFactoryBean();
+ cacheManagerFb.setConfigLocation(new ClassPathResource("testEhcache.xml", getClass()));
+ cacheManagerFb.afterPropertiesSet();
+ cacheFb.setCacheManager((CacheManager) cacheManagerFb.getObject());
+ }
+
+ cacheFb.setCacheName("myCache1");
+ cacheFb.afterPropertiesSet();
+ cache = (Cache) cacheFb.getObject();
+ assertEquals("myCache1", cache.getName());
+ if (useCacheManagerFb){
+ assertEquals("myCache1.maxElements", 300, cache.getMaxElementsInMemory());
+ }
+ else {
+ assertEquals("myCache1.maxElements", 10000, cache.getMaxElementsInMemory());
+ }
+
+ // Cache region is not defined. Should create one with default properties.
+ cacheFb = new EhCacheFactoryBean();
+ if (useCacheManagerFb) {
+ cacheFb.setCacheManager((CacheManager) cacheManagerFb.getObject());
+ }
+ cacheFb.setCacheName("undefinedCache");
+ cacheFb.afterPropertiesSet();
+ cache = (Cache) cacheFb.getObject();
+ assertEquals("undefinedCache", cache.getName());
+ assertTrue("default maxElements is correct", cache.getMaxElementsInMemory() == 10000);
+ assertTrue("default overflowToDisk is correct", cache.isOverflowToDisk());
+ assertFalse("default eternal is correct", cache.isEternal());
+ assertTrue("default timeToLive is correct", cache.getTimeToLiveSeconds() == 120);
+ assertTrue("default timeToIdle is correct", cache.getTimeToIdleSeconds() == 120);
+ assertTrue("default diskPersistent is correct", !cache.isDiskPersistent());
+ assertTrue("default diskExpiryThreadIntervalSeconds is correct", cache.getDiskExpiryThreadIntervalSeconds() == 120);
+
+ // overriding the default properties
+ cacheFb = new EhCacheFactoryBean();
+ if (useCacheManagerFb) {
+ cacheFb.setCacheManager((CacheManager) cacheManagerFb.getObject());
+ }
+ cacheFb.setBeanName("undefinedCache2");
+ cacheFb.setMaxElementsInMemory(5);
+ cacheFb.setOverflowToDisk(false);
+ cacheFb.setEternal(true);
+ cacheFb.setTimeToLive(8);
+ cacheFb.setTimeToIdle(7);
+ cacheFb.setDiskPersistent(true);
+ cacheFb.setDiskExpiryThreadIntervalSeconds(10);
+ cacheFb.afterPropertiesSet();
+ cache = (Cache) cacheFb.getObject();
+
+ assertEquals("undefinedCache2", cache.getName());
+ assertTrue("overridden maxElements is correct", cache.getMaxElementsInMemory() == 5);
+ assertFalse("overridden overflowToDisk is correct", cache.isOverflowToDisk());
+ assertTrue("overridden eternal is correct", cache.isEternal());
+ assertTrue("default timeToLive is correct", cache.getTimeToLiveSeconds() == 8);
+ assertTrue("default timeToIdle is correct", cache.getTimeToIdleSeconds() == 7);
+ assertTrue("overridden diskPersistent is correct", cache.isDiskPersistent());
+ assertTrue("overridden diskExpiryThreadIntervalSeconds is correct", cache.getDiskExpiryThreadIntervalSeconds() == 10);
+ }
+ finally {
+ if (useCacheManagerFb) {
+ cacheManagerFb.destroy();
+ }
+ else {
+ CacheManager.getInstance().shutdown();
+ }
+ }
+ }
+
+ public void testEhCacheFactoryBeanWithBlockingCache() throws Exception {
+ EhCacheManagerFactoryBean cacheManagerFb = new EhCacheManagerFactoryBean();
+ cacheManagerFb.afterPropertiesSet();
+ try {
+ CacheManager cm = (CacheManager) cacheManagerFb.getObject();
+ EhCacheFactoryBean cacheFb = new EhCacheFactoryBean();
+ cacheFb.setCacheManager(cm);
+ cacheFb.setCacheName("myCache1");
+ cacheFb.setBlocking(true);
+ cacheFb.afterPropertiesSet();
+ Ehcache myCache1 = cm.getEhcache("myCache1");
+ assertTrue(myCache1 instanceof BlockingCache);
+ }
+ finally {
+ cacheManagerFb.destroy();
+ }
+ }
+
+ public void testEhCacheFactoryBeanWithSelfPopulatingCache() throws Exception {
+ EhCacheManagerFactoryBean cacheManagerFb = new EhCacheManagerFactoryBean();
+ cacheManagerFb.afterPropertiesSet();
+ try {
+ CacheManager cm = (CacheManager) cacheManagerFb.getObject();
+ EhCacheFactoryBean cacheFb = new EhCacheFactoryBean();
+ cacheFb.setCacheManager(cm);
+ cacheFb.setCacheName("myCache1");
+ cacheFb.setCacheEntryFactory(new CacheEntryFactory() {
+ public Object createEntry(Object key) throws Exception {
+ return key;
+ }
+ });
+ cacheFb.afterPropertiesSet();
+ Ehcache myCache1 = cm.getEhcache("myCache1");
+ assertTrue(myCache1 instanceof SelfPopulatingCache);
+ assertEquals("myKey1", myCache1.get("myKey1").getValue());
+ }
+ finally {
+ cacheManagerFb.destroy();
+ }
+ }
+
+ public void testEhCacheFactoryBeanWithUpdatingSelfPopulatingCache() throws Exception {
+ EhCacheManagerFactoryBean cacheManagerFb = new EhCacheManagerFactoryBean();
+ cacheManagerFb.afterPropertiesSet();
+ try {
+ CacheManager cm = (CacheManager) cacheManagerFb.getObject();
+ EhCacheFactoryBean cacheFb = new EhCacheFactoryBean();
+ cacheFb.setCacheManager(cm);
+ cacheFb.setCacheName("myCache1");
+ cacheFb.setCacheEntryFactory(new UpdatingCacheEntryFactory() {
+ public Object createEntry(Object key) throws Exception {
+ return key;
+ }
+ public void updateEntryValue(Object key, Object value) throws Exception {
+ }
+ });
+ cacheFb.afterPropertiesSet();
+ Ehcache myCache1 = cm.getEhcache("myCache1");
+ assertTrue(myCache1 instanceof UpdatingSelfPopulatingCache);
+ assertEquals("myKey1", myCache1.get("myKey1").getValue());
+ }
+ finally {
+ cacheManagerFb.destroy();
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/cache/ehcache/testEhcache.xml b/org.springframework.testsuite/src/test/java/org/springframework/cache/ehcache/testEhcache.xml
new file mode 100644
index 00000000000..dcac796151c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/cache/ehcache/testEhcache.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/ACATester.java b/org.springframework.testsuite/src/test/java/org/springframework/context/ACATester.java
new file mode 100644
index 00000000000..1bda64a785f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/ACATester.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.context;
+
+import java.util.Locale;
+
+public class ACATester implements ApplicationContextAware {
+
+ private ApplicationContext ac;
+
+ public void setApplicationContext(ApplicationContext ctx) throws ApplicationContextException {
+ // check reinitialization
+ if (this.ac != null) {
+ throw new IllegalStateException("Already initialized");
+ }
+
+ // check message source availability
+ if (ctx != null) {
+ try {
+ ctx.getMessage("code1", null, Locale.getDefault());
+ }
+ catch (NoSuchMessageException ex) {
+ // expected
+ }
+ }
+
+ this.ac = ctx;
+ }
+
+ public ApplicationContext getApplicationContext() {
+ return ac;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/AbstractApplicationContextTests.java b/org.springframework.testsuite/src/test/java/org/springframework/context/AbstractApplicationContextTests.java
new file mode 100644
index 00000000000..d014d770e16
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/AbstractApplicationContextTests.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.context;
+
+import java.util.Locale;
+
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.AbstractListableBeanFactoryTests;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.LifecycleBean;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public abstract class AbstractApplicationContextTests extends AbstractListableBeanFactoryTests {
+
+ /** Must be supplied as XML */
+ public static final String TEST_NAMESPACE = "testNamespace";
+
+ protected ConfigurableApplicationContext applicationContext;
+
+ /** Subclass must register this */
+ protected TestListener listener = new TestListener();
+
+ protected TestListener parentListener = new TestListener();
+
+ protected void setUp() throws Exception {
+ this.applicationContext = createContext();
+ }
+
+ protected BeanFactory getBeanFactory() {
+ return applicationContext;
+ }
+
+ protected ApplicationContext getApplicationContext() {
+ return applicationContext;
+ }
+
+ /**
+ * Must register a TestListener.
+ * Must register standard beans.
+ * Parent must register rod with name Roderick
+ * and father with name Albert.
+ */
+ protected abstract ConfigurableApplicationContext createContext() throws Exception;
+
+ public void testContextAwareSingletonWasCalledBack() throws Exception {
+ ACATester aca = (ACATester) applicationContext.getBean("aca");
+ assertTrue("has had context set", aca.getApplicationContext() == applicationContext);
+ Object aca2 = applicationContext.getBean("aca");
+ assertTrue("Same instance", aca == aca2);
+ assertTrue("Says is singleton", applicationContext.isSingleton("aca"));
+ }
+
+ public void testContextAwarePrototypeWasCalledBack() throws Exception {
+ ACATester aca = (ACATester) applicationContext.getBean("aca-prototype");
+ assertTrue("has had context set", aca.getApplicationContext() == applicationContext);
+ Object aca2 = applicationContext.getBean("aca-prototype");
+ assertTrue("NOT Same instance", aca != aca2);
+ assertTrue("Says is prototype", !applicationContext.isSingleton("aca-prototype"));
+ }
+
+ public void testParentNonNull() {
+ assertTrue("parent isn't null", applicationContext.getParent() != null);
+ }
+
+ public void testGrandparentNull() {
+ assertTrue("grandparent is null", applicationContext.getParent().getParent() == null);
+ }
+
+ public void testOverrideWorked() throws Exception {
+ TestBean rod = (TestBean) applicationContext.getParent().getBean("rod");
+ assertTrue("Parent's name differs", rod.getName().equals("Roderick"));
+ }
+
+ public void testGrandparentDefinitionFound() throws Exception {
+ TestBean dad = (TestBean) applicationContext.getBean("father");
+ assertTrue("Dad has correct name", dad.getName().equals("Albert"));
+ }
+
+ public void testGrandparentTypedDefinitionFound() throws Exception {
+ TestBean dad = (TestBean) applicationContext.getBean("father", TestBean.class);
+ assertTrue("Dad has correct name", dad.getName().equals("Albert"));
+ }
+
+ public void testCloseTriggersDestroy() {
+ LifecycleBean lb = (LifecycleBean) applicationContext.getBean("lifecycle");
+ assertTrue("Not destroyed", !lb.isDestroyed());
+ applicationContext.close();
+ if (applicationContext.getParent() != null) {
+ ((ConfigurableApplicationContext) applicationContext.getParent()).close();
+ }
+ assertTrue("Destroyed", lb.isDestroyed());
+ applicationContext.close();
+ if (applicationContext.getParent() != null) {
+ ((ConfigurableApplicationContext) applicationContext.getParent()).close();
+ }
+ assertTrue("Destroyed", lb.isDestroyed());
+ }
+
+ public void testMessageSource() throws NoSuchMessageException {
+ assertEquals("message1", applicationContext.getMessage("code1", null, Locale.getDefault()));
+ assertEquals("message2", applicationContext.getMessage("code2", null, Locale.getDefault()));
+
+ try {
+ applicationContext.getMessage("code0", null, Locale.getDefault());
+ fail("looking for code0 should throw a NoSuchMessageException");
+ }
+ catch (NoSuchMessageException ex) {
+ // that's how it should be
+ }
+ }
+
+ public void testEvents() throws Exception {
+ listener.zeroCounter();
+ parentListener.zeroCounter();
+ assertTrue("0 events before publication", listener.getEventCount() == 0);
+ assertTrue("0 parent events before publication", parentListener.getEventCount() == 0);
+ this.applicationContext.publishEvent(new MyEvent(this));
+ assertTrue("1 events after publication, not " + listener.getEventCount(), listener.getEventCount() == 1);
+ assertTrue("1 parent events after publication", parentListener.getEventCount() == 1);
+ }
+
+ public void testBeanAutomaticallyHearsEvents() throws Exception {
+ //String[] listenerNames = ((ListableBeanFactory) applicationContext).getBeanDefinitionNames(ApplicationListener.class);
+ //assertTrue("listeners include beanThatListens", Arrays.asList(listenerNames).contains("beanThatListens"));
+ BeanThatListens b = (BeanThatListens) applicationContext.getBean("beanThatListens");
+ b.zero();
+ assertTrue("0 events before publication", b.getEventCount() == 0);
+ this.applicationContext.publishEvent(new MyEvent(this));
+ assertTrue("1 events after publication, not " + b.getEventCount(), b.getEventCount() == 1);
+ }
+
+
+ public static class MyEvent extends ApplicationEvent {
+
+ public MyEvent(Object source) {
+ super(source);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/BeanThatBroadcasts.java b/org.springframework.testsuite/src/test/java/org/springframework/context/BeanThatBroadcasts.java
new file mode 100644
index 00000000000..f525d38fe16
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/BeanThatBroadcasts.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.context;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class BeanThatBroadcasts implements ApplicationContextAware {
+
+ public ApplicationContext applicationContext;
+
+ public int receivedCount;
+
+
+ public void setApplicationContext(ApplicationContext applicationContext) {
+ this.applicationContext = applicationContext;
+ if (applicationContext.getDisplayName().indexOf("listener") != -1) {
+ applicationContext.getBean("listener");
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/BeanThatListens.java b/org.springframework.testsuite/src/test/java/org/springframework/context/BeanThatListens.java
new file mode 100644
index 00000000000..9ab3f8ea40d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/BeanThatListens.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.context;
+
+import java.util.Map;
+
+/**
+ * A stub {@link ApplicationListener}.
+ *
+ * @author Thomas Risberg
+ * @author Juergen Hoeller
+ */
+public class BeanThatListens implements ApplicationListener {
+
+ private BeanThatBroadcasts beanThatBroadcasts;
+
+ private int eventCount;
+
+
+ public BeanThatListens() {
+ }
+
+ public BeanThatListens(BeanThatBroadcasts beanThatBroadcasts) {
+ this.beanThatBroadcasts = beanThatBroadcasts;
+ Map beans = beanThatBroadcasts.applicationContext.getBeansOfType(BeanThatListens.class);
+ if (!beans.isEmpty()) {
+ throw new IllegalStateException("Shouldn't have found any BeanThatListens instances");
+ }
+ }
+
+
+ public void onApplicationEvent(ApplicationEvent event) {
+ eventCount++;
+ if (beanThatBroadcasts != null) {
+ beanThatBroadcasts.receivedCount++;
+ }
+ }
+
+ public int getEventCount() {
+ return eventCount;
+ }
+
+ public void zero() {
+ eventCount = 0;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/LifecycleContextBean.java b/org.springframework.testsuite/src/test/java/org/springframework/context/LifecycleContextBean.java
new file mode 100644
index 00000000000..c3aba92b5f8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/LifecycleContextBean.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.context;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.LifecycleBean;
+
+/**
+ * Simple bean to test ApplicationContext lifecycle methods for beans
+ *
+ * @author Colin Sampaleanu
+ * @since 03.07.2004
+ */
+public class LifecycleContextBean extends LifecycleBean implements ApplicationContextAware {
+
+ protected ApplicationContext owningContext;
+
+ public void setBeanFactory(BeanFactory beanFactory) {
+ super.setBeanFactory(beanFactory);
+ if (this.owningContext != null)
+ throw new RuntimeException("Factory called setBeanFactory after setApplicationContext");
+ }
+
+ public void afterPropertiesSet() {
+ super.afterPropertiesSet();
+ if (this.owningContext == null)
+ throw new RuntimeException("Factory didn't call setAppliationContext before afterPropertiesSet on lifecycle bean");
+ }
+
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ if (this.owningFactory == null)
+ throw new RuntimeException("Factory called setApplicationContext before setBeanFactory");
+
+ this.owningContext = applicationContext;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/TestListener.java b/org.springframework.testsuite/src/test/java/org/springframework/context/TestListener.java
new file mode 100644
index 00000000000..d3fb51d0511
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/TestListener.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.context;
+
+/**
+ * Listener that maintains a global count of events.
+ *
+ * @author Rod Johnson
+ * @since January 21, 2001
+ */
+public class TestListener implements ApplicationListener {
+
+ private int eventCount;
+
+ public int getEventCount() {
+ return eventCount;
+ }
+
+ public void zeroCounter() {
+ eventCount = 0;
+ }
+
+ public void onApplicationEvent(ApplicationEvent e) {
+ ++eventCount;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/access/ContextBeanFactoryReferenceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/context/access/ContextBeanFactoryReferenceTests.java
new file mode 100644
index 00000000000..11d79f4e81d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/access/ContextBeanFactoryReferenceTests.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.context.access;
+
+import junit.framework.TestCase;
+
+import org.easymock.MockControl;
+import org.springframework.context.ConfigurableApplicationContext;
+
+/**
+ * Unit test for ContextBeanFactoryReference
+ *
+ * @author Colin Sampaleanu
+ */
+public class ContextBeanFactoryReferenceTests extends TestCase {
+
+ public void testAllOperations() {
+ MockControl control = MockControl.createControl(ConfigurableApplicationContext.class);
+ ConfigurableApplicationContext ctx = (ConfigurableApplicationContext) control.getMock();
+
+ ctx.close();
+ control.replay();
+
+ ContextBeanFactoryReference bfr = new ContextBeanFactoryReference(ctx);
+
+ assertNotNull(bfr.getFactory());
+ bfr.release();
+
+ try {
+ bfr.getFactory();
+ }
+ catch (IllegalStateException e) {
+ // expected
+ }
+
+ control.verify();
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/access/ContextJndiBeanFactoryLocatorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/context/access/ContextJndiBeanFactoryLocatorTests.java
new file mode 100644
index 00000000000..551102540aa
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/access/ContextJndiBeanFactoryLocatorTests.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.context.access;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.access.BootstrapException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.mock.jndi.SimpleNamingContextBuilder;
+
+/**
+ * @author Colin Sampaleanu
+ */
+public class ContextJndiBeanFactoryLocatorTests extends TestCase {
+
+ public static final String BEAN_FACTORY_PATH_ENVIRONMENT_KEY = "java:comp/env/ejb/BeanFactoryPath";
+
+ public void testBeanFactoryPathRequiredFromJndiEnvironment() throws Exception {
+ // Set up initial context but don't bind anything
+ SimpleNamingContextBuilder.emptyActivatedContextBuilder();
+
+ ContextJndiBeanFactoryLocator jbfl = new ContextJndiBeanFactoryLocator();
+ try {
+ jbfl.useBeanFactory(BEAN_FACTORY_PATH_ENVIRONMENT_KEY);
+ fail();
+ }
+ catch (BootstrapException ex) {
+ // Check for helpful JNDI message
+ assertTrue(ex.getMessage().indexOf(BEAN_FACTORY_PATH_ENVIRONMENT_KEY) != -1);
+ }
+ }
+
+ public void testBeanFactoryPathFromJndiEnvironmentNotFound() throws Exception {
+ SimpleNamingContextBuilder sncb = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
+
+ String bogusPath = "RUBBISH/com/xxxx/framework/server/test1.xml";
+
+ // Set up initial context
+ sncb.bind(BEAN_FACTORY_PATH_ENVIRONMENT_KEY, bogusPath);
+
+ ContextJndiBeanFactoryLocator jbfl = new ContextJndiBeanFactoryLocator();
+ try {
+ jbfl.useBeanFactory(BEAN_FACTORY_PATH_ENVIRONMENT_KEY);
+ fail();
+ }
+ catch (BeansException ex) {
+ // Check for helpful JNDI message
+ assertTrue(ex.getMessage().indexOf(bogusPath) != -1);
+ }
+ }
+
+ public void testBeanFactoryPathFromJndiEnvironmentNotValidXml() throws Exception {
+ SimpleNamingContextBuilder sncb = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
+
+ String nonXmlPath = "com/xxxx/framework/server/SlsbEndpointBean.class";
+
+ // Set up initial context
+ sncb.bind(BEAN_FACTORY_PATH_ENVIRONMENT_KEY, nonXmlPath);
+
+ ContextJndiBeanFactoryLocator jbfl = new ContextJndiBeanFactoryLocator();
+ try {
+ jbfl.useBeanFactory(BEAN_FACTORY_PATH_ENVIRONMENT_KEY);
+ fail();
+ }
+ catch (BeansException ex) {
+ // Check for helpful JNDI message
+ assertTrue(ex.getMessage().indexOf(nonXmlPath) != -1);
+ }
+ }
+
+ public void testBeanFactoryPathFromJndiEnvironmentWithSingleFile() throws Exception {
+ SimpleNamingContextBuilder sncb = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
+
+ String path = "org/springframework/beans/factory/xml/collections.xml";
+
+ // Set up initial context
+ sncb.bind(BEAN_FACTORY_PATH_ENVIRONMENT_KEY, path);
+
+ ContextJndiBeanFactoryLocator jbfl = new ContextJndiBeanFactoryLocator();
+ BeanFactory bf = jbfl.useBeanFactory(BEAN_FACTORY_PATH_ENVIRONMENT_KEY).getFactory();
+ assertTrue(bf.containsBean("rod"));
+ assertTrue(bf instanceof ApplicationContext);
+ }
+
+ public void testBeanFactoryPathFromJndiEnvironmentWithMultipleFiles() throws Exception {
+ SimpleNamingContextBuilder sncb = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
+
+ String path = "/org/springframework/beans/factory/xml/collections.xml /org/springframework/beans/factory/xml/parent.xml";
+
+ // Set up initial context
+ sncb.bind(BEAN_FACTORY_PATH_ENVIRONMENT_KEY, path);
+
+ ContextJndiBeanFactoryLocator jbfl = new ContextJndiBeanFactoryLocator();
+ BeanFactory bf = jbfl.useBeanFactory(BEAN_FACTORY_PATH_ENVIRONMENT_KEY).getFactory();
+ assertTrue(bf.containsBean("rod"));
+ assertTrue(bf.containsBean("inheritedTestBean"));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/access/ContextSingletonBeanFactoryLocatorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/context/access/ContextSingletonBeanFactoryLocatorTests.java
new file mode 100644
index 00000000000..32068bd0098
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/access/ContextSingletonBeanFactoryLocatorTests.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.context.access;
+
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.access.BeanFactoryLocator;
+import org.springframework.beans.factory.access.BeanFactoryReference;
+import org.springframework.beans.factory.access.SingletonBeanFactoryLocatorTests;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.util.ClassUtils;
+
+/**
+ * @author Colin Sampaleanu
+ * @author Juergen Hoeller
+ */
+public class ContextSingletonBeanFactoryLocatorTests extends SingletonBeanFactoryLocatorTests {
+
+ public void testBaseBeanFactoryDefs() {
+ // Just test the base BeanFactory/AppContext defs we are going to work
+ // with in other tests.
+ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
+ new String[] {"/org/springframework/beans/factory/access/beans1.xml",
+ "/org/springframework/beans/factory/access/beans2.xml"});
+ }
+
+ public void testBasicFunctionality() {
+ // Just use definition file from the SingletonBeanFactoryLocator test,
+ // since it is completely valid.
+ ContextSingletonBeanFactoryLocator facLoc = new ContextSingletonBeanFactoryLocator(
+ "classpath*:" + ClassUtils.addResourcePathToPackagePath(
+ SingletonBeanFactoryLocatorTests.class, "ref1.xml"));
+
+ basicFunctionalityTest(facLoc);
+
+ BeanFactoryReference bfr = facLoc.useBeanFactory("a.qualified.name.of.some.sort");
+ BeanFactory fac = bfr.getFactory();
+ assertTrue(fac instanceof ApplicationContext);
+ assertEquals("a.qualified.name.of.some.sort", ((ApplicationContext) fac).getId());
+ assertEquals("a.qualified.name.of.some.sort", ((ApplicationContext) fac).getDisplayName());
+ BeanFactoryReference bfr2 = facLoc.useBeanFactory("another.qualified.name");
+ BeanFactory fac2 = bfr2.getFactory();
+ assertEquals("another.qualified.name", ((ApplicationContext) fac2).getId());
+ assertEquals("another.qualified.name", ((ApplicationContext) fac2).getDisplayName());
+ assertTrue(fac2 instanceof ApplicationContext);
+ }
+
+ /**
+ * This test can run multiple times, but due to static keyed lookup of the locators,
+ * 2nd and subsequent calls will actuall get back same locator instance. This is not
+ * really an issue, since the contained bean factories will still be loaded and released.
+ */
+ public void testGetInstance() {
+ // Try with and without 'classpath*:' prefix, and with 'classpath:' prefix.
+ BeanFactoryLocator facLoc = ContextSingletonBeanFactoryLocator.getInstance(
+ ClassUtils.addResourcePathToPackagePath(
+ SingletonBeanFactoryLocatorTests.class, "ref1.xml"));
+ getInstanceTest1(facLoc);
+
+ facLoc = ContextSingletonBeanFactoryLocator.getInstance(
+ "classpath*:" + ClassUtils.addResourcePathToPackagePath(
+ SingletonBeanFactoryLocatorTests.class, "ref1.xml"));
+ getInstanceTest2(facLoc);
+
+ // This will actually get another locator instance, as the key is the resource name.
+ facLoc = ContextSingletonBeanFactoryLocator.getInstance(
+ "classpath:" + ClassUtils.addResourcePathToPackagePath(
+ SingletonBeanFactoryLocatorTests.class, "ref1.xml"));
+ getInstanceTest3(facLoc);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/access/DefaultLocatorFactoryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/context/access/DefaultLocatorFactoryTests.java
new file mode 100644
index 00000000000..3d0aa67148b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/access/DefaultLocatorFactoryTests.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.context.access;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.factory.access.BeanFactoryLocator;
+
+/**
+ * @author Colin Sampaleanu
+ */
+public class DefaultLocatorFactoryTests extends TestCase {
+
+ /*
+ * Class to test for BeanFactoryLocator getInstance()
+ */
+ public void testGetInstance() {
+ BeanFactoryLocator bf = DefaultLocatorFactory.getInstance();
+ BeanFactoryLocator bf2 = DefaultLocatorFactory.getInstance();
+ assertTrue(bf.equals(bf2));
+ }
+
+ /*
+ * Class to test for BeanFactoryLocator getInstance(String)
+ */
+ public void testGetInstanceString() {
+ BeanFactoryLocator bf = DefaultLocatorFactory.getInstance("my-bean-refs.xml");
+ BeanFactoryLocator bf2 = DefaultLocatorFactory.getInstance("my-bean-refs.xml");
+ assertTrue(bf.equals(bf2));
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/config/ContextNamespaceHandlerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/context/config/ContextNamespaceHandlerTests.java
new file mode 100644
index 00000000000..3c45157c242
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/config/ContextNamespaceHandlerTests.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * 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.springframework.context.config;
+
+import java.util.Date;
+import java.util.Map;
+
+import junit.framework.TestCase;
+import org.springframework.beans.factory.config.PropertyOverrideConfigurer;
+import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * @author Arjen Poutsma
+ * @since 2.5.6
+ */
+public class ContextNamespaceHandlerTests extends TestCase {
+
+ private ApplicationContext applicationContext;
+
+ protected void setUp() throws Exception {
+ applicationContext = new ClassPathXmlApplicationContext("contextNamespaceHandlerTests.xml", getClass());
+ }
+
+ public void testPropertyPlaceholder() throws Exception {
+ Map beans = applicationContext.getBeansOfType(PropertyPlaceholderConfigurer.class);
+ assertFalse("No PropertyPlaceHolderConfigurer found", beans.isEmpty());
+ String s = (String) applicationContext.getBean("string");
+ assertEquals("No properties replaced", "bar", s);
+ }
+
+ public void testPropertyOverride() throws Exception {
+ Map beans = applicationContext.getBeansOfType(PropertyOverrideConfigurer.class);
+ assertFalse("No PropertyOverrideConfigurer found", beans.isEmpty());
+ Date date = (Date) applicationContext.getBean("date");
+ assertEquals("No properties overriden", 42, date.getMinutes());
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/config/contextNamespaceHandlerTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/context/config/contextNamespaceHandlerTests.xml
new file mode 100644
index 00000000000..c0b09682602
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/config/contextNamespaceHandlerTests.xml
@@ -0,0 +1,27 @@
+
+
+
+
+ bar
+
+
+
+
+
+
+
+
+
+ 42
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/event/ApplicationContextEventTests.java b/org.springframework.testsuite/src/test/java/org/springframework/context/event/ApplicationContextEventTests.java
new file mode 100644
index 00000000000..9069496e4ee
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/event/ApplicationContextEventTests.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.context.event;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+import org.aopalliance.intercept.MethodInvocation;
+import org.easymock.MockControl;
+import org.easymock.internal.AlwaysMatcher;
+import org.easymock.internal.EqualsMatcher;
+
+import org.springframework.beans.FatalBeanException;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.BeanCurrentlyInCreationException;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.BeanThatBroadcasts;
+import org.springframework.context.BeanThatListens;
+import org.springframework.context.support.StaticApplicationContext;
+import org.springframework.test.AssertThrows;
+
+/**
+ * Unit and integration tests for the ApplicationContext event support.
+ *
+ * @author Alef Arendsen
+ * @author Rick Evans
+ */
+public class ApplicationContextEventTests extends TestCase {
+
+ private AbstractApplicationEventMulticaster getMulticaster() {
+ return new AbstractApplicationEventMulticaster() {
+ public void multicastEvent(ApplicationEvent event) {
+ }
+ };
+ }
+
+ public void testMulticasterNewCollectionClass() {
+ AbstractApplicationEventMulticaster mc = getMulticaster();
+
+ mc.addApplicationListener(new NoOpApplicationListener());
+
+ mc.setCollectionClass(ArrayList.class);
+
+ assertEquals(1, mc.getApplicationListeners().size());
+ assertEquals(ArrayList.class, mc.getApplicationListeners().getClass());
+ }
+
+ public void testMulticasterInvalidCollectionClass_NotEvenACollectionType() {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ AbstractApplicationEventMulticaster mc = getMulticaster();
+ mc.setCollectionClass(ApplicationContextEventTests.class);
+ }
+ }.runTest();
+ }
+
+ public void testMulticasterInvalidCollectionClass_PassingAnInterfaceNotAConcreteClass() {
+ new AssertThrows(FatalBeanException.class) {
+ public void test() throws Exception {
+ AbstractApplicationEventMulticaster mc = getMulticaster();
+ mc.setCollectionClass(List.class);
+ }
+ }.runTest();
+ }
+
+ public void testMulticasterNullCollectionClass() {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ AbstractApplicationEventMulticaster mc = getMulticaster();
+ mc.setCollectionClass(null);
+ }
+ }.runTest();
+ }
+
+ public void testMulticasterRemoveAll() {
+ AbstractApplicationEventMulticaster mc = getMulticaster();
+ mc.addApplicationListener(new NoOpApplicationListener());
+ mc.removeAllListeners();
+
+ assertEquals(0, mc.getApplicationListeners().size());
+ }
+
+ public void testMulticasterRemoveOne() {
+ AbstractApplicationEventMulticaster mc = getMulticaster();
+ ApplicationListener one = new NoOpApplicationListener();
+ ApplicationListener two = new NoOpApplicationListener();
+ mc.addApplicationListener(one);
+ mc.addApplicationListener(two);
+
+ mc.removeApplicationListener(one);
+
+ assertEquals(1, mc.getApplicationListeners().size());
+ assertTrue("Remaining listener present", mc.getApplicationListeners().contains(two));
+ }
+
+ public void testSimpleApplicationEventMulticaster() {
+ MockControl ctrl = MockControl.createControl(ApplicationListener.class);
+ ApplicationListener listener = (ApplicationListener) ctrl.getMock();
+
+ ApplicationEvent evt = new ContextClosedEvent(new StaticApplicationContext());
+ listener.onApplicationEvent(evt);
+ ctrl.setMatcher(new EqualsMatcher());
+
+ SimpleApplicationEventMulticaster smc = new SimpleApplicationEventMulticaster();
+ smc.addApplicationListener(listener);
+
+ ctrl.replay();
+
+ smc.multicastEvent(evt);
+
+ ctrl.verify();
+ }
+
+ public void testEvenPublicationInterceptor() throws Throwable {
+ MockControl invCtrl = MockControl.createControl(MethodInvocation.class);
+ MethodInvocation invocation = (MethodInvocation) invCtrl.getMock();
+
+ MockControl ctxCtrl = MockControl.createControl(ApplicationContext.class);
+ ApplicationContext ctx = (ApplicationContext) ctxCtrl.getMock();
+
+ EventPublicationInterceptor interceptor =
+ new EventPublicationInterceptor();
+ interceptor.setApplicationEventClass(MyEvent.class);
+ interceptor.setApplicationEventPublisher(ctx);
+ interceptor.afterPropertiesSet();
+
+ invocation.proceed();
+ invCtrl.setReturnValue(new Object());
+
+ invocation.getThis();
+ invCtrl.setReturnValue(new Object());
+ ctx.publishEvent(new MyEvent(new Object()));
+ ctxCtrl.setDefaultMatcher(new AlwaysMatcher());
+
+ ctxCtrl.replay();
+ invCtrl.replay();
+
+ interceptor.invoke(invocation);
+
+ ctxCtrl.verify();
+ invCtrl.verify();
+ }
+
+ public void testListenerAndBroadcasterWithUnresolvableCircularReference() {
+ StaticApplicationContext context = new StaticApplicationContext();
+ context.setDisplayName("listener context");
+ context.registerBeanDefinition("broadcaster", new RootBeanDefinition(BeanThatBroadcasts.class));
+ RootBeanDefinition listenerDef = new RootBeanDefinition(BeanThatListens.class);
+ listenerDef.getConstructorArgumentValues().addGenericArgumentValue(new RuntimeBeanReference("broadcaster"));
+ context.registerBeanDefinition("listener", listenerDef);
+ try {
+ context.refresh();
+ fail("Should have thrown BeanCreationException with nested BeanCurrentlyInCreationException");
+ }
+ catch (BeanCreationException ex) {
+ assertTrue(ex.contains(BeanCurrentlyInCreationException.class));
+ }
+ }
+
+ public void testListenerAndBroadcasterWithResolvableCircularReference() {
+ StaticApplicationContext context = new StaticApplicationContext();
+ context.registerBeanDefinition("broadcaster", new RootBeanDefinition(BeanThatBroadcasts.class));
+ RootBeanDefinition listenerDef = new RootBeanDefinition(BeanThatListens.class);
+ listenerDef.getConstructorArgumentValues().addGenericArgumentValue(new RuntimeBeanReference("broadcaster"));
+ context.registerBeanDefinition("listener", listenerDef);
+ context.refresh();
+
+ BeanThatBroadcasts broadcaster = (BeanThatBroadcasts) context.getBean("broadcaster");
+ context.publishEvent(new MyEvent(context));
+ assertEquals("The event was not received by the listener", 2, broadcaster.receivedCount);
+ }
+
+
+ public static class MyEvent extends ApplicationEvent {
+
+ public MyEvent(Object source) {
+ super(source);
+ }
+ }
+
+
+ private static final class NoOpApplicationListener implements ApplicationListener {
+
+ public void onApplicationEvent(ApplicationEvent event) {
+ }
+
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/event/EventPublicationInterceptorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/context/event/EventPublicationInterceptorTests.java
new file mode 100644
index 00000000000..8f4f919073a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/event/EventPublicationInterceptorTests.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.context.event;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.TestListener;
+import org.springframework.context.support.StaticApplicationContext;
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Dmitriy Kopylenko
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ */
+public class EventPublicationInterceptorTests extends TestCase {
+
+ public void testWithNoApplicationEventClassSupplied() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ EventPublicationInterceptor interceptor = new EventPublicationInterceptor();
+ ApplicationContext ctx = new StaticApplicationContext();
+ interceptor.setApplicationEventPublisher(ctx);
+ interceptor.afterPropertiesSet();
+ }
+ }.runTest();
+ }
+
+ public void testWithNonApplicationEventClassSupplied() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ EventPublicationInterceptor interceptor = new EventPublicationInterceptor();
+ ApplicationContext ctx = new StaticApplicationContext();
+ interceptor.setApplicationEventPublisher(ctx);
+ interceptor.setApplicationEventClass(getClass());
+ interceptor.afterPropertiesSet();
+ }
+ }.runTest();
+ }
+
+ public void testWithAbstractStraightApplicationEventClassSupplied() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ EventPublicationInterceptor interceptor = new EventPublicationInterceptor();
+ ApplicationContext ctx = new StaticApplicationContext();
+ interceptor.setApplicationEventPublisher(ctx);
+ interceptor.setApplicationEventClass(ApplicationEvent.class);
+ interceptor.afterPropertiesSet();
+ }
+ }.runTest();
+ }
+
+ public void testWithApplicationEventClassThatDoesntExposeAValidCtor() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ EventPublicationInterceptor interceptor = new EventPublicationInterceptor();
+ ApplicationContext ctx = new StaticApplicationContext();
+ interceptor.setApplicationEventPublisher(ctx);
+ interceptor.setApplicationEventClass(TestEventWithNoValidOneArgObjectCtor.class);
+ interceptor.afterPropertiesSet();
+ }
+ }.runTest();
+ }
+
+ public void testExpectedBehavior() throws Exception {
+ TestBean target = new TestBean();
+ final TestListener listener = new TestListener();
+
+ class TestContext extends StaticApplicationContext {
+ protected void onRefresh() throws BeansException {
+ addListener(listener);
+ }
+ }
+
+ StaticApplicationContext ctx = new TestContext();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("applicationEventClass", TestEvent.class.getName());
+ // should automatically receive applicationEventPublisher reference
+ ctx.registerSingleton("publisher", EventPublicationInterceptor.class, pvs);
+ ctx.registerSingleton("otherListener", FactoryBeanTestListener.class);
+ ctx.refresh();
+
+ EventPublicationInterceptor interceptor =
+ (EventPublicationInterceptor) ctx.getBean("publisher");
+ ProxyFactory factory = new ProxyFactory(target);
+ factory.addAdvice(0, interceptor);
+
+ ITestBean testBean = (ITestBean) factory.getProxy();
+
+ // invoke any method on the advised proxy to see if the interceptor has been invoked
+ testBean.getAge();
+
+ // two events: ContextRefreshedEvent and TestEvent
+ assertTrue("Interceptor must have published 2 events", listener.getEventCount() == 2);
+ TestListener otherListener = (TestListener) ctx.getBean("&otherListener");
+ assertTrue("Interceptor must have published 2 events", otherListener.getEventCount() == 2);
+ }
+
+
+ public static class TestEvent extends ApplicationEvent {
+
+ public TestEvent(Object source) {
+ super(source);
+ }
+ }
+
+
+ public static final class TestEventWithNoValidOneArgObjectCtor extends ApplicationEvent {
+
+ public TestEventWithNoValidOneArgObjectCtor() {
+ super("");
+ }
+ }
+
+
+ public static class FactoryBeanTestListener extends TestListener implements FactoryBean {
+
+ public Object getObject() throws Exception {
+ return "test";
+ }
+
+ public Class getObjectType() {
+ return String.class;
+ }
+
+ public boolean isSingleton() {
+ return true;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/event/LifecycleEventTests.java b/org.springframework.testsuite/src/test/java/org/springframework/context/event/LifecycleEventTests.java
new file mode 100644
index 00000000000..5fa2f37ccf5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/event/LifecycleEventTests.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.context.event;
+
+import junit.framework.TestCase;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.Lifecycle;
+import org.springframework.context.support.StaticApplicationContext;
+
+/**
+ * @author Mark Fisher
+ * @author Juergen Hoeller
+ */
+public class LifecycleEventTests extends TestCase {
+
+ public void testContextStartedEvent() {
+ StaticApplicationContext context = new StaticApplicationContext();
+ context.registerSingleton("lifecycle", LifecycleTestBean.class);
+ context.registerSingleton("listener", LifecycleListener.class);
+ context.refresh();
+ LifecycleTestBean lifecycleBean = (LifecycleTestBean) context.getBean("lifecycle");
+ LifecycleListener listener = (LifecycleListener) context.getBean("listener");
+ assertFalse(lifecycleBean.isRunning());
+ assertEquals(0, listener.getStartedCount());
+ context.start();
+ assertTrue(lifecycleBean.isRunning());
+ assertEquals(1, listener.getStartedCount());
+ assertSame(context, listener.getApplicationContext());
+ }
+
+ public void testContextStoppedEvent() {
+ StaticApplicationContext context = new StaticApplicationContext();
+ context.registerSingleton("lifecycle", LifecycleTestBean.class);
+ context.registerSingleton("listener", LifecycleListener.class);
+ context.refresh();
+ LifecycleTestBean lifecycleBean = (LifecycleTestBean) context.getBean("lifecycle");
+ LifecycleListener listener = (LifecycleListener) context.getBean("listener");
+ assertFalse(lifecycleBean.isRunning());
+ context.start();
+ assertTrue(lifecycleBean.isRunning());
+ assertEquals(0, listener.getStoppedCount());
+ context.stop();
+ assertFalse(lifecycleBean.isRunning());
+ assertEquals(1, listener.getStoppedCount());
+ assertSame(context, listener.getApplicationContext());
+ }
+
+
+ private static class LifecycleListener implements ApplicationListener {
+
+ private ApplicationContext context;
+
+ private int startedCount;
+
+ private int stoppedCount;
+
+ public void onApplicationEvent(ApplicationEvent event) {
+ if (event instanceof ContextStartedEvent) {
+ this.context = ((ContextStartedEvent) event).getApplicationContext();
+ this.startedCount++;
+ }
+ else if (event instanceof ContextStoppedEvent) {
+ this.context = ((ContextStoppedEvent) event).getApplicationContext();
+ this.stoppedCount++;
+ }
+ }
+
+ public ApplicationContext getApplicationContext() {
+ return this.context;
+ }
+
+ public int getStartedCount() {
+ return this.startedCount;
+ }
+
+ public int getStoppedCount() {
+ return this.stoppedCount;
+ }
+ }
+
+
+ private static class LifecycleTestBean implements Lifecycle {
+
+ private boolean running;
+
+ public boolean isRunning() {
+ return this.running;
+ }
+
+ public void start() {
+ this.running = true;
+ }
+
+ public void stop() {
+ this.running = false;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/ApplicationContextLifecycleTests.java b/org.springframework.testsuite/src/test/java/org/springframework/context/support/ApplicationContextLifecycleTests.java
new file mode 100644
index 00000000000..4e46cc786af
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/ApplicationContextLifecycleTests.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.context.support;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Mark Fisher
+ */
+public class ApplicationContextLifecycleTests extends TestCase {
+
+ public void testBeansStart() {
+ AbstractApplicationContext context = new ClassPathXmlApplicationContext("lifecycleTests.xml", getClass());
+ context.start();
+ LifecycleTestBean bean1 = (LifecycleTestBean) context.getBean("bean1");
+ LifecycleTestBean bean2 = (LifecycleTestBean) context.getBean("bean2");
+ LifecycleTestBean bean3 = (LifecycleTestBean) context.getBean("bean3");
+ LifecycleTestBean bean4 = (LifecycleTestBean) context.getBean("bean4");
+ String error = "bean was not started";
+ assertTrue(error, bean1.isRunning());
+ assertTrue(error, bean2.isRunning());
+ assertTrue(error, bean3.isRunning());
+ assertTrue(error, bean4.isRunning());
+ }
+
+ public void testBeansStop() {
+ AbstractApplicationContext context = new ClassPathXmlApplicationContext("lifecycleTests.xml", getClass());
+ context.start();
+ LifecycleTestBean bean1 = (LifecycleTestBean) context.getBean("bean1");
+ LifecycleTestBean bean2 = (LifecycleTestBean) context.getBean("bean2");
+ LifecycleTestBean bean3 = (LifecycleTestBean) context.getBean("bean3");
+ LifecycleTestBean bean4 = (LifecycleTestBean) context.getBean("bean4");
+ String startError = "bean was not started";
+ assertTrue(startError, bean1.isRunning());
+ assertTrue(startError, bean2.isRunning());
+ assertTrue(startError, bean3.isRunning());
+ assertTrue(startError, bean4.isRunning());
+ context.stop();
+ String stopError = "bean was not stopped";
+ assertFalse(stopError, bean1.isRunning());
+ assertFalse(stopError, bean2.isRunning());
+ assertFalse(stopError, bean3.isRunning());
+ assertFalse(stopError, bean4.isRunning());
+ }
+
+ public void testStartOrder() {
+ AbstractApplicationContext context = new ClassPathXmlApplicationContext("lifecycleTests.xml", getClass());
+ context.start();
+ LifecycleTestBean bean1 = (LifecycleTestBean) context.getBean("bean1");
+ LifecycleTestBean bean2 = (LifecycleTestBean) context.getBean("bean2");
+ LifecycleTestBean bean3 = (LifecycleTestBean) context.getBean("bean3");
+ LifecycleTestBean bean4 = (LifecycleTestBean) context.getBean("bean4");
+ String notStartedError = "bean was not started";
+ assertTrue(notStartedError, bean1.getStartOrder() > 0);
+ assertTrue(notStartedError, bean2.getStartOrder() > 0);
+ assertTrue(notStartedError, bean3.getStartOrder() > 0);
+ assertTrue(notStartedError, bean4.getStartOrder() > 0);
+ String orderError = "dependent bean must start after the bean it depends on";
+ assertTrue(orderError, bean2.getStartOrder() > bean1.getStartOrder());
+ assertTrue(orderError, bean3.getStartOrder() > bean2.getStartOrder());
+ assertTrue(orderError, bean4.getStartOrder() > bean2.getStartOrder());
+ }
+
+ public void testStopOrder() {
+ AbstractApplicationContext context = new ClassPathXmlApplicationContext("lifecycleTests.xml", getClass());
+ context.start();
+ context.stop();
+ LifecycleTestBean bean1 = (LifecycleTestBean) context.getBean("bean1");
+ LifecycleTestBean bean2 = (LifecycleTestBean) context.getBean("bean2");
+ LifecycleTestBean bean3 = (LifecycleTestBean) context.getBean("bean3");
+ LifecycleTestBean bean4 = (LifecycleTestBean) context.getBean("bean4");
+ String notStoppedError = "bean was not stopped";
+ assertTrue(notStoppedError, bean1.getStopOrder() > 0);
+ assertTrue(notStoppedError, bean2.getStopOrder() > 0);
+ assertTrue(notStoppedError, bean3.getStopOrder() > 0);
+ assertTrue(notStoppedError, bean4.getStopOrder() > 0);
+ String orderError = "dependent bean must stop before the bean it depends on";
+ assertTrue(orderError, bean2.getStopOrder() < bean1.getStopOrder());
+ assertTrue(orderError, bean3.getStopOrder() < bean2.getStopOrder());
+ assertTrue(orderError, bean4.getStopOrder() < bean2.getStopOrder());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/Assembler.java b/org.springframework.testsuite/src/test/java/org/springframework/context/support/Assembler.java
new file mode 100644
index 00000000000..f3171912192
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/Assembler.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.context.support;
+
+/**
+ * @author Alef Arendsen
+ */
+public class Assembler implements TestIF {
+
+ private Service service;
+ private Logic l;
+ private String name;
+
+ public void setService(Service service) {
+ this.service = service;
+ }
+
+ public void setLogic(Logic l) {
+ this.l = l;
+ }
+
+ public void setBeanName(String name) {
+ this.name = name;
+ }
+
+ public void test() {
+ }
+
+ public void output() {
+ System.out.println("Bean " + name);
+ l.output();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/AutowiredService.java b/org.springframework.testsuite/src/test/java/org/springframework/context/support/AutowiredService.java
new file mode 100644
index 00000000000..285e8348bde
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/AutowiredService.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.context.support;
+
+import org.springframework.context.MessageSource;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class AutowiredService {
+
+ private MessageSource messageSource;
+
+ public void setMessageSource(MessageSource messageSource) {
+ if (this.messageSource != null) {
+ throw new IllegalArgumentException("MessageSource should not be set twice");
+ }
+ this.messageSource = messageSource;
+ }
+
+ public MessageSource getMessageSource() {
+ return messageSource;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/ClassPathXmlApplicationContextTests.java b/org.springframework.testsuite/src/test/java/org/springframework/context/support/ClassPathXmlApplicationContextTests.java
new file mode 100644
index 00000000000..4f1c6c0b6a7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/ClassPathXmlApplicationContextTests.java
@@ -0,0 +1,371 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.context.support;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.support.AopUtils;
+import org.springframework.beans.ResourceTestBean;
+import org.springframework.beans.TypeMismatchException;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.BeanFactoryUtils;
+import org.springframework.beans.factory.CannotLoadBeanClassException;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.MessageSource;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.core.io.Resource;
+import org.springframework.util.FileCopyUtils;
+import org.springframework.util.ObjectUtils;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class ClassPathXmlApplicationContextTests extends TestCase {
+
+ public void testSingleConfigLocation() {
+ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
+ "/org/springframework/context/support/simpleContext.xml");
+ assertTrue(ctx.containsBean("someMessageSource"));
+ ctx.close();
+ }
+
+ public void testMultipleConfigLocations() {
+ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
+ new String[] {
+ "/org/springframework/context/support/test/contextB.xml",
+ "/org/springframework/context/support/test/contextC.xml",
+ "/org/springframework/context/support/test/contextA.xml"});
+ assertTrue(ctx.containsBean("service"));
+ assertTrue(ctx.containsBean("logicOne"));
+ assertTrue(ctx.containsBean("logicTwo"));
+ Service service = (Service) ctx.getBean("service");
+ ctx.refresh();
+ assertTrue(service.isProperlyDestroyed());
+ service = (Service) ctx.getBean("service");
+ ctx.close();
+ assertTrue(service.isProperlyDestroyed());
+ }
+
+ public void testConfigLocationPattern() {
+ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
+ "/org/springframework/context/support/test/context*.xml");
+ assertTrue(ctx.containsBean("service"));
+ assertTrue(ctx.containsBean("logicOne"));
+ assertTrue(ctx.containsBean("logicTwo"));
+ Service service = (Service) ctx.getBean("service");
+ ctx.close();
+ assertTrue(service.isProperlyDestroyed());
+ }
+
+ public void testSingleConfigLocationWithClass() {
+ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
+ "simpleContext.xml", getClass());
+ assertTrue(ctx.containsBean("someMessageSource"));
+ ctx.close();
+ }
+
+ public void testAliasWithPlaceholder() {
+ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
+ new String[] {
+ "/org/springframework/context/support/test/contextB.xml",
+ "/org/springframework/context/support/test/aliased-contextC.xml",
+ "/org/springframework/context/support/test/contextA.xml"});
+ assertTrue(ctx.containsBean("service"));
+ assertTrue(ctx.containsBean("logicOne"));
+ assertTrue(ctx.containsBean("logicTwo"));
+ ctx.refresh();
+ }
+
+ public void testContextWithInvalidValueType() throws IOException {
+ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
+ new String[] {"/org/springframework/context/support/invalidValueType.xml"}, false);
+ try {
+ context.refresh();
+ fail("Should have thrown BeanCreationException");
+ }
+ catch (BeanCreationException ex) {
+ assertTrue(ex.contains(TypeMismatchException.class));
+ assertTrue(ex.toString().indexOf("someMessageSource") != -1);
+ assertTrue(ex.toString().indexOf("useCodeAsDefaultMessage") != -1);
+ checkExceptionFromInvalidValueType(ex);
+ checkExceptionFromInvalidValueType(new ExceptionInInitializerError(ex));
+ assertFalse(context.isActive());
+ }
+ }
+
+ private void checkExceptionFromInvalidValueType(Throwable ex) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ex.printStackTrace(new PrintStream(baos));
+ String dump = FileCopyUtils.copyToString(
+ new InputStreamReader(new ByteArrayInputStream(baos.toByteArray())));
+ assertTrue(dump.indexOf("someMessageSource") != -1);
+ assertTrue(dump.indexOf("useCodeAsDefaultMessage") != -1);
+ }
+
+ public void testContextWithInvalidLazyClass() {
+ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
+ "invalidClass.xml", getClass());
+ assertTrue(ctx.containsBean("someMessageSource"));
+ try {
+ ctx.getBean("someMessageSource");
+ fail("Should have thrown CannotLoadBeanClassException");
+ }
+ catch (CannotLoadBeanClassException ex) {
+ assertTrue(ex.contains(ClassNotFoundException.class));
+ }
+ ctx.close();
+ }
+
+ public void testContextWithClassNameThatContainsPlaceholder() {
+ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
+ "classWithPlaceholder.xml", getClass());
+ assertTrue(ctx.containsBean("someMessageSource"));
+ assertTrue(ctx.getBean("someMessageSource") instanceof StaticMessageSource);
+ ctx.close();
+ }
+
+ public void testMultipleConfigLocationsWithClass() {
+ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
+ new String[] {"test/contextB.xml", "test/contextC.xml", "test/contextA.xml"}, getClass());
+ assertTrue(ctx.containsBean("service"));
+ assertTrue(ctx.containsBean("logicOne"));
+ assertTrue(ctx.containsBean("logicTwo"));
+ ctx.close();
+ }
+
+ public void testFactoryBeanAndApplicationListener() {
+ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
+ "/org/springframework/context/support/test/context*.xml");
+ ctx.getBeanFactory().registerSingleton("manualFBAAL", new FactoryBeanAndApplicationListener());
+ assertEquals(2, ctx.getBeansOfType(ApplicationListener.class).size());
+ ctx.close();
+ }
+
+ public void testMessageSourceAware() {
+ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
+ "/org/springframework/context/support/test/context*.xml");
+ MessageSource messageSource = (MessageSource) ctx.getBean("messageSource");
+ Service service1 = (Service) ctx.getBean("service");
+ assertEquals(ctx, service1.getMessageSource());
+ Service service2 = (Service) ctx.getBean("service2");
+ assertEquals(ctx, service2.getMessageSource());
+ AutowiredService autowiredService1 = (AutowiredService) ctx.getBean("autowiredService");
+ assertEquals(messageSource, autowiredService1.getMessageSource());
+ AutowiredService autowiredService2 = (AutowiredService) ctx.getBean("autowiredService2");
+ assertEquals(messageSource, autowiredService2.getMessageSource());
+ ctx.close();
+ }
+
+ public void testResourceArrayPropertyEditor() throws IOException {
+ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
+ "/org/springframework/context/support/test/context*.xml");
+ Service service = (Service) ctx.getBean("service");
+ assertEquals(3, service.getResources().length);
+ List resources = Arrays.asList(service.getResources());
+ assertTrue(resources.contains(
+ new FileSystemResource(new ClassPathResource("/org/springframework/context/support/test/contextA.xml").getFile())));
+ assertTrue(resources.contains(
+ new FileSystemResource(new ClassPathResource("/org/springframework/context/support/test/contextB.xml").getFile())));
+ assertTrue(resources.contains(
+ new FileSystemResource(new ClassPathResource("/org/springframework/context/support/test/contextC.xml").getFile())));
+ ctx.close();
+ }
+
+ public void testChildWithProxy() throws Exception {
+ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
+ "/org/springframework/context/support/test/context*.xml");
+ ClassPathXmlApplicationContext child = new ClassPathXmlApplicationContext(
+ new String[] {"/org/springframework/context/support/childWithProxy.xml"}, ctx);
+ assertTrue(AopUtils.isAopProxy(child.getBean("assemblerOne")));
+ assertTrue(AopUtils.isAopProxy(child.getBean("assemblerTwo")));
+ ctx.close();
+ }
+
+ public void testAliasForParentContext() {
+ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
+ "/org/springframework/context/support/simpleContext.xml");
+ assertTrue(ctx.containsBean("someMessageSource"));
+
+ ClassPathXmlApplicationContext child = new ClassPathXmlApplicationContext(
+ new String[] {"/org/springframework/context/support/aliasForParent.xml"}, ctx);
+ assertTrue(child.containsBean("someMessageSource"));
+ assertTrue(child.containsBean("yourMessageSource"));
+ assertTrue(child.containsBean("myMessageSource"));
+ assertTrue(child.isSingleton("someMessageSource"));
+ assertTrue(child.isSingleton("yourMessageSource"));
+ assertTrue(child.isSingleton("myMessageSource"));
+ assertEquals(StaticMessageSource.class, child.getType("someMessageSource"));
+ assertEquals(StaticMessageSource.class, child.getType("yourMessageSource"));
+ assertEquals(StaticMessageSource.class, child.getType("myMessageSource"));
+
+ Object someMs = child.getBean("someMessageSource");
+ Object yourMs = child.getBean("yourMessageSource");
+ Object myMs = child.getBean("myMessageSource");
+ assertSame(someMs, yourMs);
+ assertSame(someMs, myMs);
+
+ String[] aliases = child.getAliases("someMessageSource");
+ assertEquals(2, aliases.length);
+ assertEquals("myMessageSource", aliases[0]);
+ assertEquals("yourMessageSource", aliases[1]);
+ aliases = child.getAliases("myMessageSource");
+ assertEquals(2, aliases.length);
+ assertEquals("someMessageSource", aliases[0]);
+ assertEquals("yourMessageSource", aliases[1]);
+
+ child.close();
+ ctx.close();
+ }
+
+ public void testAliasThatOverridesParent() {
+ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
+ "/org/springframework/context/support/simpleContext.xml");
+ Object someMs = ctx.getBean("someMessageSource");
+
+ ClassPathXmlApplicationContext child = new ClassPathXmlApplicationContext(
+ new String[] {"/org/springframework/context/support/aliasThatOverridesParent.xml"}, ctx);
+ Object myMs = child.getBean("myMessageSource");
+ Object someMs2 = child.getBean("someMessageSource");
+ assertSame(myMs, someMs2);
+ assertNotSame(someMs, someMs2);
+ assertOneMessageSourceOnly(child, myMs);
+ }
+
+ public void testAliasThatOverridesEarlierBean() {
+ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
+ new String[] {"/org/springframework/context/support/simpleContext.xml",
+ "/org/springframework/context/support/aliasThatOverridesParent.xml"});
+ Object myMs = ctx.getBean("myMessageSource");
+ Object someMs2 = ctx.getBean("someMessageSource");
+ assertSame(myMs, someMs2);
+ assertOneMessageSourceOnly(ctx, myMs);
+ }
+
+ private void assertOneMessageSourceOnly(ClassPathXmlApplicationContext ctx, Object myMessageSource) {
+ String[] beanNamesForType = ctx.getBeanNamesForType(StaticMessageSource.class);
+ assertEquals(1, beanNamesForType.length);
+ assertEquals("myMessageSource", beanNamesForType[0]);
+ beanNamesForType = ctx.getBeanNamesForType(StaticMessageSource.class, true, true);
+ assertEquals(1, beanNamesForType.length);
+ assertEquals("myMessageSource", beanNamesForType[0]);
+ beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(ctx, StaticMessageSource.class);
+ assertEquals(1, beanNamesForType.length);
+ assertEquals("myMessageSource", beanNamesForType[0]);
+ beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(ctx, StaticMessageSource.class, true, true);
+ assertEquals(1, beanNamesForType.length);
+ assertEquals("myMessageSource", beanNamesForType[0]);
+
+ Map beansOfType = ctx.getBeansOfType(StaticMessageSource.class);
+ assertEquals(1, beansOfType.size());
+ assertSame(myMessageSource, beansOfType.values().iterator().next());
+ beansOfType = ctx.getBeansOfType(StaticMessageSource.class, true, true);
+ assertEquals(1, beansOfType.size());
+ assertSame(myMessageSource, beansOfType.values().iterator().next());
+ beansOfType = BeanFactoryUtils.beansOfTypeIncludingAncestors(ctx, StaticMessageSource.class);
+ assertEquals(1, beansOfType.size());
+ assertSame(myMessageSource, beansOfType.values().iterator().next());
+ beansOfType = BeanFactoryUtils.beansOfTypeIncludingAncestors(ctx, StaticMessageSource.class, true, true);
+ assertEquals(1, beansOfType.size());
+ assertSame(myMessageSource, beansOfType.values().iterator().next());
+ }
+
+ public void testResourceAndInputStream() throws IOException {
+ ClassPathXmlApplicationContext ctx =
+ new ClassPathXmlApplicationContext("/org/springframework/beans/factory/xml/resource.xml") {
+ public Resource getResource(String location) {
+ if ("classpath:org/springframework/beans/factory/xml/test.properties".equals(location)) {
+ return new ClassPathResource("test.properties", ClassPathXmlApplicationContextTests.class);
+ }
+ return super.getResource(location);
+ }
+ };
+ ResourceTestBean resource1 = (ResourceTestBean) ctx.getBean("resource1");
+ ResourceTestBean resource2 = (ResourceTestBean) ctx.getBean("resource2");
+ assertTrue(resource1.getResource() instanceof ClassPathResource);
+ StringWriter writer = new StringWriter();
+ FileCopyUtils.copy(new InputStreamReader(resource1.getResource().getInputStream()), writer);
+ assertEquals("contexttest", writer.toString());
+ writer = new StringWriter();
+ FileCopyUtils.copy(new InputStreamReader(resource1.getInputStream()), writer);
+ assertEquals("contexttest", writer.toString());
+ writer = new StringWriter();
+ FileCopyUtils.copy(new InputStreamReader(resource2.getResource().getInputStream()), writer);
+ assertEquals("contexttest", writer.toString());
+ writer = new StringWriter();
+ FileCopyUtils.copy(new InputStreamReader(resource2.getInputStream()), writer);
+ assertEquals("contexttest", writer.toString());
+ ctx.close();
+ }
+
+ public void testGenericApplicationContextWithXmlBeanDefinitions() {
+ GenericApplicationContext ctx = new GenericApplicationContext();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(ctx);
+ reader.loadBeanDefinitions(new ClassPathResource("test/contextB.xml", getClass()));
+ reader.loadBeanDefinitions(new ClassPathResource("test/contextC.xml", getClass()));
+ reader.loadBeanDefinitions(new ClassPathResource("test/contextA.xml", getClass()));
+ ctx.refresh();
+ assertTrue(ctx.containsBean("service"));
+ assertTrue(ctx.containsBean("logicOne"));
+ assertTrue(ctx.containsBean("logicTwo"));
+ ctx.close();
+ }
+
+ public void testGenericApplicationContextWithXmlBeanDefinitionsAndClassLoaderNull() {
+ GenericApplicationContext ctx = new GenericApplicationContext();
+ ctx.setClassLoader(null);
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(ctx);
+ reader.loadBeanDefinitions(new ClassPathResource("test/contextB.xml", getClass()));
+ reader.loadBeanDefinitions(new ClassPathResource("test/contextC.xml", getClass()));
+ reader.loadBeanDefinitions(new ClassPathResource("test/contextA.xml", getClass()));
+ ctx.refresh();
+ assertEquals(ObjectUtils.identityToString(ctx), ctx.getId());
+ assertEquals(ObjectUtils.identityToString(ctx), ctx.getDisplayName());
+ assertTrue(ctx.containsBean("service"));
+ assertTrue(ctx.containsBean("logicOne"));
+ assertTrue(ctx.containsBean("logicTwo"));
+ ctx.close();
+ }
+
+ public void testGenericApplicationContextWithXmlBeanDefinitionsAndSpecifiedId() {
+ GenericApplicationContext ctx = new GenericApplicationContext();
+ ctx.setId("testContext");
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(ctx);
+ reader.loadBeanDefinitions(new ClassPathResource("test/contextB.xml", getClass()));
+ reader.loadBeanDefinitions(new ClassPathResource("test/contextC.xml", getClass()));
+ reader.loadBeanDefinitions(new ClassPathResource("test/contextA.xml", getClass()));
+ ctx.refresh();
+ assertEquals("testContext", ctx.getId());
+ assertEquals("testContext", ctx.getDisplayName());
+ assertTrue(ctx.containsBean("service"));
+ assertTrue(ctx.containsBean("logicOne"));
+ assertTrue(ctx.containsBean("logicTwo"));
+ ctx.close();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/FactoryBeanAndApplicationListener.java b/org.springframework.testsuite/src/test/java/org/springframework/context/support/FactoryBeanAndApplicationListener.java
new file mode 100644
index 00000000000..b0a90824d44
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/FactoryBeanAndApplicationListener.java
@@ -0,0 +1,28 @@
+package org.springframework.context.support;
+
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationListener;
+
+/**
+ * @author Juergen Hoeller
+ * @since 06.10.2004
+ */
+public class FactoryBeanAndApplicationListener implements FactoryBean, ApplicationListener {
+
+ public Object getObject() throws Exception {
+ return "";
+ }
+
+ public Class getObjectType() {
+ return String.class;
+ }
+
+ public boolean isSingleton() {
+ return true;
+ }
+
+ public void onApplicationEvent(ApplicationEvent event) {
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/LifecycleTestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/context/support/LifecycleTestBean.java
new file mode 100644
index 00000000000..8c220888378
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/LifecycleTestBean.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.context.support;
+
+import org.springframework.context.Lifecycle;
+
+/**
+ * @author Mark Fisher
+ */
+public class LifecycleTestBean implements Lifecycle {
+
+ private static int startCounter;
+
+ private static int stopCounter;
+
+
+ private int startOrder;
+
+ private int stopOrder;
+
+ private boolean running;
+
+
+ public int getStartOrder() {
+ return startOrder;
+ }
+
+ public int getStopOrder() {
+ return stopOrder;
+ }
+
+ public boolean isRunning() {
+ return this.running;
+ }
+
+ public void start() {
+ this.startOrder = ++startCounter;
+ this.running = true;
+ }
+
+ public void stop() {
+ this.stopOrder = ++stopCounter;
+ this.running = false;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/Logic.java b/org.springframework.testsuite/src/test/java/org/springframework/context/support/Logic.java
new file mode 100644
index 00000000000..ee1974670ce
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/Logic.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.context.support;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.BeanNameAware;
+
+
+public class Logic implements BeanNameAware {
+
+ private Log log = LogFactory.getLog(Logic.class);
+ private String name;
+ private Assembler a;
+
+ public void setAssembler(Assembler a) {
+ this.a = a;
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String)
+ */
+ public void setBeanName(String name) {
+ this.name = name;
+ }
+
+ public void output() {
+ System.out.println("Bean " + name);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/ResourceBundleMessageSourceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/context/support/ResourceBundleMessageSourceTests.java
new file mode 100644
index 00000000000..6379d9a791f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/ResourceBundleMessageSourceTests.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.context.support;
+
+import java.util.Locale;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.context.MessageSourceResolvable;
+import org.springframework.context.NoSuchMessageException;
+import org.springframework.context.i18n.LocaleContextHolder;
+import org.springframework.core.JdkVersion;
+
+/**
+ * @author Juergen Hoeller
+ * @since 03.02.2004
+ */
+public class ResourceBundleMessageSourceTests extends TestCase {
+
+ public void testMessageAccessWithDefaultMessageSource() {
+ doTestMessageAccess(false, true, false, false, false);
+ }
+
+ public void testMessageAccessWithDefaultMessageSourceAndMessageFormat() {
+ doTestMessageAccess(false, true, false, false, true);
+ }
+
+ public void testMessageAccessWithDefaultMessageSourceAndFallbackToGerman() {
+ doTestMessageAccess(false, true, true, true, false);
+ }
+
+ public void testMessageAccessWithReloadableMessageSource() {
+ doTestMessageAccess(true, true, false, false, false);
+ }
+
+ public void testMessageAccessWithReloadableMessageSourceAndMessageFormat() {
+ doTestMessageAccess(true, true, false, false, true);
+ }
+
+ public void testMessageAccessWithReloadableMessageSourceAndFallbackToGerman() {
+ doTestMessageAccess(true, true, true, true, false);
+ }
+
+ public void testMessageAccessWithReloadableMessageSourceAndFallbackTurnedOff() {
+ doTestMessageAccess(true, false, false, false, false);
+ }
+
+ public void testMessageAccessWithReloadableMessageSourceAndFallbackTurnedOffAndFallbackToGerman() {
+ doTestMessageAccess(true, false, true, true, false);
+ }
+
+ protected void doTestMessageAccess(
+ boolean reloadable, boolean fallbackToSystemLocale,
+ boolean expectGermanFallback, boolean useCodeAsDefaultMessage, boolean alwaysUseMessageFormat) {
+
+ StaticApplicationContext ac = new StaticApplicationContext();
+ if (reloadable) {
+ StaticApplicationContext parent = new StaticApplicationContext();
+ parent.refresh();
+ ac.setParent(parent);
+ }
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ String basepath = "org/springframework/context/support/";
+ String[] basenames = null;
+ if (reloadable) {
+ basenames = new String[] {
+ "classpath:" + basepath + "messages",
+ "classpath:" + basepath + "more-messages"};
+ }
+ else {
+ basenames = new String[] {
+ basepath + "messages",
+ basepath + "more-messages"};
+ }
+ pvs.addPropertyValue("basenames", basenames);
+ if (!fallbackToSystemLocale) {
+ pvs.addPropertyValue("fallbackToSystemLocale", Boolean.FALSE);
+ }
+ if (useCodeAsDefaultMessage) {
+ pvs.addPropertyValue("useCodeAsDefaultMessage", Boolean.TRUE);
+ }
+ if (alwaysUseMessageFormat) {
+ pvs.addPropertyValue("alwaysUseMessageFormat", Boolean.TRUE);
+ }
+ Class clazz = reloadable ?
+ (Class) ReloadableResourceBundleMessageSource.class : ResourceBundleMessageSource.class;
+ ac.registerSingleton("messageSource", clazz, pvs);
+ ac.refresh();
+
+ Locale.setDefault(expectGermanFallback ? Locale.GERMAN : Locale.CANADA);
+ assertEquals("message1", ac.getMessage("code1", null, Locale.ENGLISH));
+ assertEquals(fallbackToSystemLocale && expectGermanFallback ? "nachricht2" : "message2",
+ ac.getMessage("code2", null, Locale.ENGLISH));
+
+ assertEquals("nachricht2", ac.getMessage("code2", null, Locale.GERMAN));
+ assertEquals("nochricht2", ac.getMessage("code2", null, new Locale("DE", "at")));
+ assertEquals("noochricht2", ac.getMessage("code2", null, new Locale("DE", "at", "oo")));
+
+ if (reloadable && JdkVersion.getMajorJavaVersion() >= JdkVersion.JAVA_15) {
+ assertEquals("nachricht2xml", ac.getMessage("code2", null, Locale.GERMANY));
+ }
+
+ MessageSourceAccessor accessor = new MessageSourceAccessor(ac);
+ LocaleContextHolder.setLocale(new Locale("DE", "at"));
+ try {
+ assertEquals("nochricht2", accessor.getMessage("code2"));
+ }
+ finally {
+ LocaleContextHolder.setLocale(null);
+ }
+
+ assertEquals("message3", ac.getMessage("code3", null, Locale.ENGLISH));
+ MessageSourceResolvable resolvable = new DefaultMessageSourceResolvable("code3");
+ assertEquals("message3", ac.getMessage(resolvable, Locale.ENGLISH));
+ resolvable = new DefaultMessageSourceResolvable(new String[] {"code4", "code3"});
+ assertEquals("message3", ac.getMessage(resolvable, Locale.ENGLISH));
+
+ assertEquals("message3", ac.getMessage("code3", null, Locale.ENGLISH));
+ resolvable = new DefaultMessageSourceResolvable(new String[] {"code4", "code3"});
+ assertEquals("message3", ac.getMessage(resolvable, Locale.ENGLISH));
+
+ Object[] args = new Object[] {"Hello", new DefaultMessageSourceResolvable(new String[] {"code1"})};
+ assertEquals("Hello, message1", ac.getMessage("hello", args, Locale.ENGLISH));
+
+ // test default message without and with args
+ assertEquals("default", ac.getMessage(null, null, "default", Locale.ENGLISH));
+ assertEquals("default", ac.getMessage(null, args, "default", Locale.ENGLISH));
+ assertEquals("{0}, default", ac.getMessage(null, null, "{0}, default", Locale.ENGLISH));
+ assertEquals("Hello, default", ac.getMessage(null, args, "{0}, default", Locale.ENGLISH));
+
+ // test resolvable with default message, without and with args
+ resolvable = new DefaultMessageSourceResolvable(null, null, "default");
+ assertEquals("default", ac.getMessage(resolvable, Locale.ENGLISH));
+ resolvable = new DefaultMessageSourceResolvable(null, args, "default");
+ assertEquals("default", ac.getMessage(resolvable, Locale.ENGLISH));
+ resolvable = new DefaultMessageSourceResolvable(null, null, "{0}, default");
+ assertEquals("{0}, default", ac.getMessage(resolvable, Locale.ENGLISH));
+ resolvable = new DefaultMessageSourceResolvable(null, args, "{0}, default");
+ assertEquals("Hello, default", ac.getMessage(resolvable, Locale.ENGLISH));
+
+ // test message args
+ assertEquals("Arg1, Arg2", ac.getMessage("hello", new Object[] {"Arg1", "Arg2"}, Locale.ENGLISH));
+ assertEquals("{0}, {1}", ac.getMessage("hello", null, Locale.ENGLISH));
+
+ if (alwaysUseMessageFormat) {
+ assertEquals("I'm", ac.getMessage("escaped", null, Locale.ENGLISH));
+ }
+ else {
+ assertEquals("I''m", ac.getMessage("escaped", null, Locale.ENGLISH));
+ }
+ assertEquals("I'm", ac.getMessage("escaped", new Object[] {"some arg"}, Locale.ENGLISH));
+
+ try {
+ assertEquals("code4", ac.getMessage("code4", null, Locale.GERMAN));
+ if (!useCodeAsDefaultMessage) {
+ fail("Should have thrown NoSuchMessageException");
+ }
+ }
+ catch (NoSuchMessageException ex) {
+ if (useCodeAsDefaultMessage) {
+ fail("Should have returned code as default message");
+ }
+ }
+ }
+
+ public void testDefaultApplicationContextMessageSource() {
+ GenericApplicationContext ac = new GenericApplicationContext();
+ ac.refresh();
+ assertEquals("default", ac.getMessage("code1", null, "default", Locale.ENGLISH));
+ assertEquals("default value", ac.getMessage("code1", new Object[] {"value"}, "default {0}", Locale.ENGLISH));
+ }
+
+ public void testResourceBundleMessageSourceStandalone() {
+ ResourceBundleMessageSource ms = new ResourceBundleMessageSource();
+ ms.setBasename("org/springframework/context/support/messages");
+ assertEquals("message1", ms.getMessage("code1", null, Locale.ENGLISH));
+ assertEquals("nachricht2", ms.getMessage("code2", null, Locale.GERMAN));
+ }
+
+ public void testResourceBundleMessageSourceWithWhitespaceInBasename() {
+ ResourceBundleMessageSource ms = new ResourceBundleMessageSource();
+ ms.setBasename(" org/springframework/context/support/messages ");
+ assertEquals("message1", ms.getMessage("code1", null, Locale.ENGLISH));
+ assertEquals("nachricht2", ms.getMessage("code2", null, Locale.GERMAN));
+ }
+
+ public void testReloadableResourceBundleMessageSourceStandalone() {
+ ReloadableResourceBundleMessageSource ms = new ReloadableResourceBundleMessageSource();
+ ms.setBasename("org/springframework/context/support/messages");
+ assertEquals("message1", ms.getMessage("code1", null, Locale.ENGLISH));
+ assertEquals("nachricht2", ms.getMessage("code2", null, Locale.GERMAN));
+ }
+
+ public void testReloadableResourceBundleMessageSourceWithWhitespaceInBasename() {
+ ReloadableResourceBundleMessageSource ms = new ReloadableResourceBundleMessageSource();
+ ms.setBasename(" org/springframework/context/support/messages ");
+ assertEquals("message1", ms.getMessage("code1", null, Locale.ENGLISH));
+ assertEquals("nachricht2", ms.getMessage("code2", null, Locale.GERMAN));
+ }
+
+ public void testReloadableResourceBundleMessageSourceWithDefaultCharset() {
+ ReloadableResourceBundleMessageSource ms = new ReloadableResourceBundleMessageSource();
+ ms.setBasename("org/springframework/context/support/messages");
+ ms.setDefaultEncoding("ISO-8859-1");
+ assertEquals("message1", ms.getMessage("code1", null, Locale.ENGLISH));
+ assertEquals("nachricht2", ms.getMessage("code2", null, Locale.GERMAN));
+ }
+
+ public void testReloadableResourceBundleMessageSourceWithInappropriateDefaultCharset() {
+ ReloadableResourceBundleMessageSource ms = new ReloadableResourceBundleMessageSource();
+ ms.setBasename("org/springframework/context/support/messages");
+ ms.setDefaultEncoding("unicode");
+ Properties fileCharsets = new Properties();
+ fileCharsets.setProperty("org/springframework/context/support/messages_de", "unicode");
+ ms.setFileEncodings(fileCharsets);
+ ms.setFallbackToSystemLocale(false);
+ try {
+ ms.getMessage("code1", null, Locale.ENGLISH);
+ fail("Should have thrown NoSuchMessageException");
+ }
+ catch (NoSuchMessageException ex) {
+ // expected
+ }
+ }
+
+ public void testReloadableResourceBundleMessageSourceWithInappropriateEnglishCharset() {
+ ReloadableResourceBundleMessageSource ms = new ReloadableResourceBundleMessageSource();
+ ms.setBasename("org/springframework/context/support/messages");
+ ms.setFallbackToSystemLocale(false);
+ Properties fileCharsets = new Properties();
+ fileCharsets.setProperty("org/springframework/context/support/messages", "unicode");
+ ms.setFileEncodings(fileCharsets);
+ try {
+ ms.getMessage("code1", null, Locale.ENGLISH);
+ fail("Should have thrown NoSuchMessageException");
+ }
+ catch (NoSuchMessageException ex) {
+ // expected
+ }
+ }
+
+ public void testReloadableResourceBundleMessageSourceWithInappropriateGermanCharset() {
+ ReloadableResourceBundleMessageSource ms = new ReloadableResourceBundleMessageSource();
+ ms.setBasename("org/springframework/context/support/messages");
+ ms.setFallbackToSystemLocale(false);
+ Properties fileCharsets = new Properties();
+ fileCharsets.setProperty("org/springframework/context/support/messages_de", "unicode");
+ ms.setFileEncodings(fileCharsets);
+ assertEquals("message1", ms.getMessage("code1", null, Locale.ENGLISH));
+ assertEquals("message2", ms.getMessage("code2", null, Locale.GERMAN));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/ResourceMapFactoryBeanTests.java b/org.springframework.testsuite/src/test/java/org/springframework/context/support/ResourceMapFactoryBeanTests.java
new file mode 100644
index 00000000000..d45c2f7084d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/ResourceMapFactoryBeanTests.java
@@ -0,0 +1,75 @@
+package org.springframework.context.support;
+
+import java.util.Map;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+/**
+ * @author Juergen Hoeller
+ * @since 25.04.2004
+ */
+public class ResourceMapFactoryBeanTests extends TestCase {
+
+ public void testResourceMapFactoryBeanWithoutContext() {
+ DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
+ Properties props = new Properties();
+ props.setProperty("test1", "classpath:org/springframework/context/support/contextA.xml");
+ props.setProperty("test2", "classpath:org/springframework/context/support/contextB.xml");
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", props);
+ RootBeanDefinition bd = new RootBeanDefinition(ResourceMapFactoryBean.class, pvs);
+ beanFactory.registerBeanDefinition("resourceMap", bd);
+ Map result = (Map) beanFactory.getBean("resourceMap");
+ assertEquals(2, result.size());
+ assertTrue(result.get("test1") instanceof ClassPathResource);
+ assertTrue(((Resource) result.get("test1")).getDescription().indexOf("contextA.xml") != -1);
+ assertTrue(((Resource) result.get("test2")).getDescription().indexOf("contextB.xml") != -1);
+ }
+
+ public void testResourceMapFactoryBeanWithContext() {
+ StaticApplicationContext context = new StaticApplicationContext() {
+ public Resource getResource(String location) {
+ return super.getResource("classpath:org/springframework/context/support/context" + location);
+ }
+ };
+ DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
+ Properties props = new Properties();
+ props.setProperty("test1", "A.xml");
+ props.setProperty("test2", "B.xml");
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", props);
+ RootBeanDefinition bd = new RootBeanDefinition(ResourceMapFactoryBean.class, pvs);
+ beanFactory.registerBeanDefinition("resourceMap", bd);
+ context.refresh();
+ Map result = (Map) beanFactory.getBean("resourceMap");
+ assertEquals(2, result.size());
+ assertTrue(result.get("test1") instanceof ClassPathResource);
+ assertTrue(((Resource) result.get("test1")).getDescription().indexOf("contextA.xml") != -1);
+ assertTrue(((Resource) result.get("test2")).getDescription().indexOf("contextB.xml") != -1);
+ }
+
+ public void testResourceMapFactoryBeanWithResourceBasePath() {
+ DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
+ Properties props = new Properties();
+ props.setProperty("test1", "A.xml");
+ props.setProperty("test2", "B.xml");
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", props);
+ pvs.addPropertyValue("resourceBasePath", "classpath:org/springframework/context/support/context");
+ RootBeanDefinition bd = new RootBeanDefinition(ResourceMapFactoryBean.class, pvs);
+ beanFactory.registerBeanDefinition("resourceMap", bd);
+ Map result = (Map) beanFactory.getBean("resourceMap");
+ assertEquals(2, result.size());
+ assertTrue(result.get("test1") instanceof ClassPathResource);
+ assertTrue(((Resource) result.get("test1")).getDescription().indexOf("contextA.xml") != -1);
+ assertTrue(((Resource) result.get("test2")).getDescription().indexOf("contextB.xml") != -1);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/Service.java b/org.springframework.testsuite/src/test/java/org/springframework/context/support/Service.java
new file mode 100644
index 00000000000..8778978bd80
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/Service.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.context.support;
+
+import org.springframework.beans.factory.BeanCreationNotAllowedException;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.MessageSource;
+import org.springframework.context.MessageSourceAware;
+import org.springframework.core.io.Resource;
+import org.springframework.util.Assert;
+
+/**
+ * @author Alef Arendsen
+ * @author Juergen Hoeller
+ */
+public class Service implements ApplicationContextAware, MessageSourceAware, DisposableBean {
+
+ private ApplicationContext applicationContext;
+
+ private MessageSource messageSource;
+
+ private Resource[] resources;
+
+ private boolean properlyDestroyed = false;
+
+
+ public void setApplicationContext(ApplicationContext applicationContext) {
+ this.applicationContext = applicationContext;
+ }
+
+ public void setMessageSource(MessageSource messageSource) {
+ if (this.messageSource != null) {
+ throw new IllegalArgumentException("MessageSource should not be set twice");
+ }
+ this.messageSource = messageSource;
+ }
+
+ public MessageSource getMessageSource() {
+ return messageSource;
+ }
+
+ public void setResources(Resource[] resources) {
+ this.resources = resources;
+ }
+
+ public Resource[] getResources() {
+ return resources;
+ }
+
+
+ public void destroy() {
+ this.properlyDestroyed = true;
+ Thread thread = new Thread() {
+ public void run() {
+ Assert.isTrue(applicationContext.getBean("messageSource") instanceof StaticMessageSource);
+ try {
+ applicationContext.getBean("service2");
+ // Should have thrown BeanCreationNotAllowedException
+ properlyDestroyed = false;
+ }
+ catch (BeanCreationNotAllowedException ex) {
+ // expected
+ }
+ }
+ };
+ thread.start();
+ try {
+ thread.join();
+ }
+ catch (InterruptedException ex) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ public boolean isProperlyDestroyed() {
+ return properlyDestroyed;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/StaticApplicationContextMulticasterTests.java b/org.springframework.testsuite/src/test/java/org/springframework/context/support/StaticApplicationContextMulticasterTests.java
new file mode 100644
index 00000000000..9bfe88b2cc2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/StaticApplicationContextMulticasterTests.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.context.support;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.support.PropertiesBeanDefinitionReader;
+import org.springframework.context.ACATester;
+import org.springframework.context.AbstractApplicationContextTests;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.BeanThatListens;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.event.SimpleApplicationEventMulticaster;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.EncodedResource;
+
+/**
+ * Tests for static application context with custom application event multicaster.
+ *
+ * @author Juergen Hoeller
+ */
+public class StaticApplicationContextMulticasterTests extends AbstractApplicationContextTests {
+
+ protected StaticApplicationContext sac;
+
+ /** Run for each test */
+ protected ConfigurableApplicationContext createContext() throws Exception {
+ StaticApplicationContext parent = new StaticApplicationContext();
+ Map m = new HashMap();
+ m.put("name", "Roderick");
+ parent.registerPrototype("rod", TestBean.class, new MutablePropertyValues(m));
+ m.put("name", "Albert");
+ parent.registerPrototype("father", TestBean.class, new MutablePropertyValues(m));
+ parent.registerSingleton(StaticApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME,
+ TestApplicationEventMulticaster.class, null);
+ parent.refresh();
+ parent.addListener(parentListener) ;
+
+ parent.getStaticMessageSource().addMessage("code1", Locale.getDefault(), "message1");
+
+ this.sac = new StaticApplicationContext(parent);
+ sac.registerSingleton("beanThatListens", BeanThatListens.class, new MutablePropertyValues());
+ sac.registerSingleton("aca", ACATester.class, new MutablePropertyValues());
+ sac.registerPrototype("aca-prototype", ACATester.class, new MutablePropertyValues());
+ PropertiesBeanDefinitionReader reader = new PropertiesBeanDefinitionReader(sac.getDefaultListableBeanFactory());
+ Resource resource = new ClassPathResource("testBeans.properties", getClass());
+ reader.loadBeanDefinitions(new EncodedResource(resource, "ISO-8859-1"));
+ sac.refresh();
+ sac.addListener(listener);
+
+ sac.getStaticMessageSource().addMessage("code2", Locale.getDefault(), "message2");
+
+ return sac;
+ }
+
+ /** Overridden */
+ public void testCount() {
+ assertCount(15);
+ }
+
+ public void testEvents() throws Exception {
+ TestApplicationEventMulticaster.counter = 0;
+ super.testEvents();
+ assertEquals(1, TestApplicationEventMulticaster.counter);
+ }
+
+
+ public static class TestApplicationEventMulticaster extends SimpleApplicationEventMulticaster {
+
+ private static int counter = 0;
+
+ public void multicastEvent(ApplicationEvent event) {
+ super.multicastEvent(event);
+ counter++;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/StaticApplicationContextTests.java b/org.springframework.testsuite/src/test/java/org/springframework/context/support/StaticApplicationContextTests.java
new file mode 100644
index 00000000000..d98528b2306
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/StaticApplicationContextTests.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.context.support;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.support.PropertiesBeanDefinitionReader;
+import org.springframework.context.ACATester;
+import org.springframework.context.AbstractApplicationContextTests;
+import org.springframework.context.BeanThatListens;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * Tests for static application context.
+ *
+ * @author Rod Johnson
+ */
+public class StaticApplicationContextTests extends AbstractApplicationContextTests {
+
+ protected StaticApplicationContext sac;
+
+ /** Run for each test */
+ protected ConfigurableApplicationContext createContext() throws Exception {
+ StaticApplicationContext parent = new StaticApplicationContext();
+ Map m = new HashMap();
+ m.put("name", "Roderick");
+ parent.registerPrototype("rod", TestBean.class, new MutablePropertyValues(m));
+ m.put("name", "Albert");
+ parent.registerPrototype("father", TestBean.class, new MutablePropertyValues(m));
+ parent.refresh();
+ parent.addListener(parentListener) ;
+
+ parent.getStaticMessageSource().addMessage("code1", Locale.getDefault(), "message1");
+
+ this.sac = new StaticApplicationContext(parent);
+ sac.registerSingleton("beanThatListens", BeanThatListens.class, new MutablePropertyValues());
+ sac.registerSingleton("aca", ACATester.class, new MutablePropertyValues());
+ sac.registerPrototype("aca-prototype", ACATester.class, new MutablePropertyValues());
+ PropertiesBeanDefinitionReader reader = new PropertiesBeanDefinitionReader(sac.getDefaultListableBeanFactory());
+ reader.loadBeanDefinitions(new ClassPathResource("testBeans.properties", getClass()));
+ sac.refresh();
+ sac.addListener(listener);
+
+ sac.getStaticMessageSource().addMessage("code2", Locale.getDefault(), "message2");
+
+ return sac;
+ }
+
+ /** Overridden */
+ public void testCount() {
+ assertCount(15);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/StaticMessageSourceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/context/support/StaticMessageSourceTests.java
new file mode 100644
index 00000000000..47e72fb9116
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/StaticMessageSourceTests.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.context.support;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.factory.support.PropertiesBeanDefinitionReader;
+import org.springframework.context.ACATester;
+import org.springframework.context.AbstractApplicationContextTests;
+import org.springframework.context.BeanThatListens;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.MessageSourceResolvable;
+import org.springframework.context.NoSuchMessageException;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public class StaticMessageSourceTests extends AbstractApplicationContextTests {
+
+ protected static final String MSG_TXT1_US =
+ "At '{1,time}' on \"{1,date}\", there was \"{2}\" on planet {0,number,integer}.";
+ protected static final String MSG_TXT1_UK =
+ "At '{1,time}' on \"{1,date}\", there was \"{2}\" on station number {0,number,integer}.";
+ protected static final String MSG_TXT2_US =
+ "This is a test message in the message catalog with no args.";
+ protected static final String MSG_TXT3_US =
+ "This is another test message in the message catalog with no args.";
+
+ protected StaticApplicationContext sac;
+
+ /** Overridden */
+ public void testCount() {
+ // These are only checked for current Ctx (not parent ctx)
+ assertCount(15);
+ }
+
+ public void testMessageSource() throws NoSuchMessageException {
+ // Do nothing here since super is looking for errorCodes we
+ // do NOT have in the Context
+ }
+
+ public void testGetMessageWithDefaultPassedInAndFoundInMsgCatalog() {
+ // Try with Locale.US
+ assertTrue("valid msg from staticMsgSource with default msg passed in returned msg from msg catalog for Locale.US",
+ sac.getMessage("message.format.example2", null, "This is a default msg if not found in MessageSource.", Locale.US)
+ .equals("This is a test message in the message catalog with no args."));
+ }
+
+ public void testGetMessageWithDefaultPassedInAndNotFoundInMsgCatalog() {
+ // Try with Locale.US
+ assertTrue("bogus msg from staticMsgSource with default msg passed in returned default msg for Locale.US",
+ sac.getMessage("bogus.message", null, "This is a default msg if not found in MessageSource.", Locale.US)
+ .equals("This is a default msg if not found in MessageSource."));
+ }
+
+ /**
+ * We really are testing the AbstractMessageSource class here.
+ * The underlying implementation uses a hashMap to cache messageFormats
+ * once a message has been asked for. This test is an attempt to
+ * make sure the cache is being used properly.
+ * @see org.springframework.context.support.AbstractMessageSource for more details.
+ */
+ public void testGetMessageWithMessageAlreadyLookedFor() {
+ Object[] arguments = {
+ new Integer(7), new Date(System.currentTimeMillis()),
+ "a disturbance in the Force"
+ };
+
+ // The first time searching, we don't care about for this test
+ // Try with Locale.US
+ sac.getMessage("message.format.example1", arguments, Locale.US);
+
+ // Now msg better be as expected
+ assertTrue("2nd search within MsgFormat cache returned expected message for Locale.US",
+ sac.getMessage("message.format.example1", arguments, Locale.US).indexOf(
+ "there was \"a disturbance in the Force\" on planet 7.") != -1);
+
+ Object[] newArguments = {
+ new Integer(8), new Date(System.currentTimeMillis()),
+ "a disturbance in the Force"
+ };
+
+ // Now msg better be as expected even with different args
+ assertTrue("2nd search within MsgFormat cache with different args returned expected message for Locale.US",
+ sac.getMessage("message.format.example1", newArguments, Locale.US)
+ .indexOf("there was \"a disturbance in the Force\" on planet 8.") != -1);
+ }
+
+ /**
+ * Example taken from the javadocs for the java.text.MessageFormat class
+ */
+ public void testGetMessageWithNoDefaultPassedInAndFoundInMsgCatalog() {
+ Object[] arguments = {
+ new Integer(7), new Date(System.currentTimeMillis()),
+ "a disturbance in the Force"
+ };
+
+ /*
+ Try with Locale.US
+ Since the msg has a time value in it, we will use String.indexOf(...)
+ to just look for a substring without the time. This is because it is
+ possible that by the time we store a time variable in this method
+ and the time the ResourceBundleMessageSource resolves the msg the
+ minutes of the time might not be the same.
+ */
+ assertTrue("msg from staticMsgSource for Locale.US substituting args for placeholders is as expected",
+ sac.getMessage("message.format.example1", arguments, Locale.US)
+ .indexOf("there was \"a disturbance in the Force\" on planet 7.") != -1);
+
+ // Try with Locale.UK
+ assertTrue("msg from staticMsgSource for Locale.UK substituting args for placeholders is as expected",
+ sac.getMessage("message.format.example1", arguments, Locale.UK)
+ .indexOf("there was \"a disturbance in the Force\" on station number 7.") != -1);
+
+ // Try with Locale.US - Use a different test msg that requires no args
+ assertTrue("msg from staticMsgSource for Locale.US that requires no args is as expected",
+ sac.getMessage("message.format.example2", null, Locale.US)
+ .equals("This is a test message in the message catalog with no args."));
+ }
+
+ public void testGetMessageWithNoDefaultPassedInAndNotFoundInMsgCatalog() {
+ // Expecting an exception
+ try {
+ // Try with Locale.US
+ sac.getMessage("bogus.message", null, Locale.US);
+
+ fail("bogus msg from staticMsgSource for Locale.US without default msg should have thrown exception");
+ }
+ catch (NoSuchMessageException tExcept) {
+ assertTrue("bogus msg from staticMsgSource for Locale.US without default msg threw expected exception", true);
+ }
+ }
+
+ public void testMessageSourceResolvable() {
+ // first code valid
+ String[] codes1 = new String[] {"message.format.example3", "message.format.example2"};
+ MessageSourceResolvable resolvable1 = new DefaultMessageSourceResolvable(codes1, null, "default");
+ try {
+ assertTrue("correct message retrieved", MSG_TXT3_US.equals(sac.getMessage(resolvable1, Locale.US)));
+ }
+ catch (NoSuchMessageException ex) {
+ fail("Should not throw NoSuchMessageException");
+ }
+
+ // only second code valid
+ String[] codes2 = new String[] {"message.format.example99", "message.format.example2"};
+ MessageSourceResolvable resolvable2 = new DefaultMessageSourceResolvable(codes2, null, "default");
+ try {
+ assertTrue("correct message retrieved", MSG_TXT2_US.equals(sac.getMessage(resolvable2, Locale.US)));
+ }
+ catch (NoSuchMessageException ex) {
+ fail("Should not throw NoSuchMessageException");
+ }
+
+ // no code valid, but default given
+ String[] codes3 = new String[] {"message.format.example99", "message.format.example98"};
+ MessageSourceResolvable resolvable3 = new DefaultMessageSourceResolvable(codes3, null, "default");
+ try {
+ assertTrue("correct message retrieved", "default".equals(sac.getMessage(resolvable3, Locale.US)));
+ }
+ catch (NoSuchMessageException ex) {
+ fail("Should not throw NoSuchMessageException");
+ }
+
+ // no code valid, no default
+ String[] codes4 = new String[] {"message.format.example99", "message.format.example98"};
+ MessageSourceResolvable resolvable4 = new DefaultMessageSourceResolvable(codes4);
+ try {
+ sac.getMessage(resolvable4, Locale.US);
+ fail("Should have thrown NoSuchMessageException");
+ }
+ catch (NoSuchMessageException ex) {
+ // expected
+ }
+ }
+
+ /** Run for each test */
+ protected ConfigurableApplicationContext createContext() throws Exception {
+ StaticApplicationContext parent = new StaticApplicationContext();
+
+ Map m = new HashMap();
+ m.put("name", "Roderick");
+ parent.registerPrototype("rod", org.springframework.beans.TestBean.class, new MutablePropertyValues(m));
+ m.put("name", "Albert");
+ parent.registerPrototype("father", org.springframework.beans.TestBean.class, new MutablePropertyValues(m));
+
+ parent.refresh();
+ parent.addListener(parentListener);
+
+ this.sac = new StaticApplicationContext(parent);
+
+ sac.registerSingleton("beanThatListens", BeanThatListens.class, new MutablePropertyValues());
+
+ sac.registerSingleton("aca", ACATester.class, new MutablePropertyValues());
+
+ sac.registerPrototype("aca-prototype", ACATester.class, new MutablePropertyValues());
+
+ PropertiesBeanDefinitionReader reader = new PropertiesBeanDefinitionReader(sac.getDefaultListableBeanFactory());
+ reader.loadBeanDefinitions(new ClassPathResource("testBeans.properties", getClass()));
+ sac.refresh();
+ sac.addListener(listener);
+
+ StaticMessageSource messageSource = sac.getStaticMessageSource();
+ Map usMessages = new HashMap(3);
+ usMessages.put("message.format.example1", MSG_TXT1_US);
+ usMessages.put("message.format.example2", MSG_TXT2_US);
+ usMessages.put("message.format.example3", MSG_TXT3_US);
+ messageSource.addMessages(usMessages, Locale.US);
+ messageSource.addMessage("message.format.example1", Locale.UK, MSG_TXT1_UK);
+
+ return sac;
+ }
+
+ public void testNestedMessageSourceWithParamInChild() {
+ StaticMessageSource source = new StaticMessageSource();
+ StaticMessageSource parent = new StaticMessageSource();
+ source.setParentMessageSource(parent);
+
+ source.addMessage("param", Locale.ENGLISH, "value");
+ parent.addMessage("with.param", Locale.ENGLISH, "put {0} here");
+
+ MessageSourceResolvable resolvable = new DefaultMessageSourceResolvable(
+ new String[] {"with.param"}, new Object[] {new DefaultMessageSourceResolvable("param")});
+
+ assertEquals("put value here", source.getMessage(resolvable, Locale.ENGLISH));
+ }
+
+ public void testNestedMessageSourceWithParamInParent() {
+ StaticMessageSource source = new StaticMessageSource();
+ StaticMessageSource parent = new StaticMessageSource();
+ source.setParentMessageSource(parent);
+
+ parent.addMessage("param", Locale.ENGLISH, "value");
+ source.addMessage("with.param", Locale.ENGLISH, "put {0} here");
+
+ MessageSourceResolvable resolvable = new DefaultMessageSourceResolvable(
+ new String[] {"with.param"}, new Object[] {new DefaultMessageSourceResolvable("param")});
+
+ assertEquals("put value here", source.getMessage(resolvable, Locale.ENGLISH));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/TestIF.java b/org.springframework.testsuite/src/test/java/org/springframework/context/support/TestIF.java
new file mode 100644
index 00000000000..d458965dc3d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/TestIF.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.context.support;
+
+public interface TestIF {
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/aliasForParent.xml b/org.springframework.testsuite/src/test/java/org/springframework/context/support/aliasForParent.xml
new file mode 100644
index 00000000000..3f66e034998
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/aliasForParent.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/aliasThatOverridesParent.xml b/org.springframework.testsuite/src/test/java/org/springframework/context/support/aliasThatOverridesParent.xml
new file mode 100644
index 00000000000..8ab5e584a42
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/aliasThatOverridesParent.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/childWithProxy.xml b/org.springframework.testsuite/src/test/java/org/springframework/context/support/childWithProxy.xml
new file mode 100644
index 00000000000..ec31bf6e574
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/childWithProxy.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+ true
+
+
+ PROPAGATION_REQUIRED
+
+
+
+
+
+
+
+ true
+
+
+ PROPAGATION_REQUIRED
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/classWithPlaceholder.xml b/org.springframework.testsuite/src/test/java/org/springframework/context/support/classWithPlaceholder.xml
new file mode 100644
index 00000000000..e2dcc3fff10
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/classWithPlaceholder.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+ StaticMessageSource
+ singleton
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/invalidClass.xml b/org.springframework.testsuite/src/test/java/org/springframework/context/support/invalidClass.xml
new file mode 100644
index 00000000000..3e7509aec74
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/invalidClass.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/invalidValueType.xml b/org.springframework.testsuite/src/test/java/org/springframework/context/support/invalidValueType.xml
new file mode 100644
index 00000000000..6a07f13fbab
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/invalidValueType.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/lifecycleTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/context/support/lifecycleTests.xml
new file mode 100644
index 00000000000..f38a0d3d747
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/lifecycleTests.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/messages.properties b/org.springframework.testsuite/src/test/java/org/springframework/context/support/messages.properties
new file mode 100644
index 00000000000..90fb2bb9b22
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/messages.properties
@@ -0,0 +1,5 @@
+ code1 = mess\
+ age1
+code2=message2
+hello={0}, {1}
+escaped=I''m
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/messages_de.properties b/org.springframework.testsuite/src/test/java/org/springframework/context/support/messages_de.properties
new file mode 100644
index 00000000000..a9a00b17a0d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/messages_de.properties
@@ -0,0 +1 @@
+code2=nachricht2
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/messages_de_AT.properties b/org.springframework.testsuite/src/test/java/org/springframework/context/support/messages_de_AT.properties
new file mode 100644
index 00000000000..1f363cc4732
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/messages_de_AT.properties
@@ -0,0 +1 @@
+code2=nochricht2
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/messages_de_AT_oo.properties b/org.springframework.testsuite/src/test/java/org/springframework/context/support/messages_de_AT_oo.properties
new file mode 100644
index 00000000000..b0a94283a08
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/messages_de_AT_oo.properties
@@ -0,0 +1 @@
+code2=noochricht2
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/messages_de_DE.xml b/org.springframework.testsuite/src/test/java/org/springframework/context/support/messages_de_DE.xml
new file mode 100644
index 00000000000..fe84234b5f1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/messages_de_DE.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+ nachricht2xml
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/more-messages.properties b/org.springframework.testsuite/src/test/java/org/springframework/context/support/more-messages.properties
new file mode 100644
index 00000000000..1a76f24fc98
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/more-messages.properties
@@ -0,0 +1 @@
+code3=message3
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/override.properties b/org.springframework.testsuite/src/test/java/org/springframework/context/support/override.properties
new file mode 100644
index 00000000000..37e7f13ad0a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/override.properties
@@ -0,0 +1,2 @@
+wrappedAssemblerOne.proxyTargetClass=true
+wrappedAssemblerTwo.proxyTargetClass=true
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/placeholder.properties b/org.springframework.testsuite/src/test/java/org/springframework/context/support/placeholder.properties
new file mode 100644
index 00000000000..6c9d0976218
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/placeholder.properties
@@ -0,0 +1,3 @@
+targetName=wrappedAssemblerOne
+logicName=logicTwo
+realLogicName=realLogic
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/simpleContext.xml b/org.springframework.testsuite/src/test/java/org/springframework/context/support/simpleContext.xml
new file mode 100644
index 00000000000..c32ed74147c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/simpleContext.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/test.properties b/org.springframework.testsuite/src/test/java/org/springframework/context/support/test.properties
new file mode 100644
index 00000000000..6cfa0eae111
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/test.properties
@@ -0,0 +1 @@
+contexttest
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/test/aliased-contextC.xml b/org.springframework.testsuite/src/test/java/org/springframework/context/support/test/aliased-contextC.xml
new file mode 100644
index 00000000000..3c46c30820f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/test/aliased-contextC.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/test/contextA.xml b/org.springframework.testsuite/src/test/java/org/springframework/context/support/test/contextA.xml
new file mode 100644
index 00000000000..55f9cdfd699
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/test/contextA.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PROPAGATION_REQUIRED
+
+
+
+
+
+
+
+
+
+
+ PROPAGATION_REQUIRED
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/test/contextB.xml b/org.springframework.testsuite/src/test/java/org/springframework/context/support/test/contextB.xml
new file mode 100644
index 00000000000..261ce0698b6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/test/contextB.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/test/contextC.xml b/org.springframework.testsuite/src/test/java/org/springframework/context/support/test/contextC.xml
new file mode 100644
index 00000000000..c1abb93e2a3
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/test/contextC.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/test/import1.xml b/org.springframework.testsuite/src/test/java/org/springframework/context/support/test/import1.xml
new file mode 100644
index 00000000000..f49285b811f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/test/import1.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/test/subtest/import2.xml b/org.springframework.testsuite/src/test/java/org/springframework/context/support/test/subtest/import2.xml
new file mode 100644
index 00000000000..74b2f73fd27
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/test/subtest/import2.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/context/support/testBeans.properties b/org.springframework.testsuite/src/test/java/org/springframework/context/support/testBeans.properties
new file mode 100644
index 00000000000..1eab846bc5e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/context/support/testBeans.properties
@@ -0,0 +1,42 @@
+# this must only be used for ApplicationContexts, some classes are only appropriate for application contexts
+
+rod.(class)=org.springframework.beans.TestBean
+rod.name=Rod
+rod.age=31
+
+roderick.(parent)=rod
+roderick.name=Roderick
+
+kerry.(class)=org.springframework.beans.TestBean
+kerry.name=Kerry
+kerry.age=34
+kerry.spouse(ref)=rod
+
+kathy.(class)=org.springframework.beans.TestBean
+kathy.(singleton)=false
+
+typeMismatch.(class)=org.springframework.beans.TestBean
+typeMismatch.name=typeMismatch
+typeMismatch.age=34x
+typeMismatch.spouse(ref)=rod
+typeMismatch.(singleton)=false
+
+validEmpty.(class)=org.springframework.beans.TestBean
+
+listenerVeto.(class)=org.springframework.beans.TestBean
+
+typeMismatch.name=typeMismatch
+typeMismatch.age=34x
+typeMismatch.spouse(ref)=rod
+
+singletonFactory.(class)=org.springframework.beans.factory.DummyFactory
+singletonFactory.singleton=true
+
+prototypeFactory.(class)=org.springframework.beans.factory.DummyFactory
+prototypeFactory.singleton=false
+
+mustBeInitialized.(class)=org.springframework.beans.factory.MustBeInitialized
+
+lifecycle.(class)=org.springframework.context.LifecycleContextBean
+
+lifecyclePostProcessor.(class)=org.springframework.beans.factory.LifecycleBean$PostProcessor
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/core/AbstractControlFlowTests.java b/org.springframework.testsuite/src/test/java/org/springframework/core/AbstractControlFlowTests.java
new file mode 100644
index 00000000000..2136a269d9f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/core/AbstractControlFlowTests.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.core;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rod Johnson
+ */
+public abstract class AbstractControlFlowTests extends TestCase {
+
+ protected abstract ControlFlow createControlFlow();
+
+ /*
+ * Class to test for boolean under(Class)
+ */
+ public void testUnderClassAndMethod() {
+ new One().test();
+ new Two().testing();
+ new Three().test();
+ }
+
+ /*
+ public void testUnderPackage() {
+ ControlFlow cflow = new ControlFlow();
+ assertFalse(cflow.underPackage("org.springframework.aop"));
+ assertTrue(cflow.underPackage("org.springframework.aop.support"));
+ assertFalse(cflow.underPackage("com.interface21"));
+ }
+ */
+
+
+ public class One {
+
+ public void test() {
+ ControlFlow cflow = createControlFlow();
+ assertTrue(cflow.under(One.class));
+ assertTrue(cflow.under(AbstractControlFlowTests.class));
+ assertFalse(cflow.under(Two.class));
+ assertTrue(cflow.under(One.class, "test"));
+ assertFalse(cflow.under(One.class, "hashCode"));
+ }
+
+ }
+
+
+ public class Two {
+
+ public void testing() {
+ ControlFlow cflow = createControlFlow();
+ assertTrue(cflow.under(Two.class));
+ assertTrue(cflow.under(AbstractControlFlowTests.class));
+ assertFalse(cflow.under(One.class));
+ assertFalse(cflow.under(Two.class, "test"));
+ assertTrue(cflow.under(Two.class, "testing"));
+ }
+ }
+
+
+ public class Three {
+
+ public void test() {
+ testing();
+ }
+
+ private void testing() {
+ ControlFlow cflow = createControlFlow();
+ assertTrue(cflow.under(Three.class));
+ assertTrue(cflow.under(AbstractControlFlowTests.class));
+ assertFalse(cflow.under(One.class));
+ assertTrue(cflow.under(Three.class, "test"));
+ assertTrue(cflow.under(Three.class, "testing"));
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/core/AttributeAccessorSupportTests.java b/org.springframework.testsuite/src/test/java/org/springframework/core/AttributeAccessorSupportTests.java
new file mode 100644
index 00000000000..d35b1b34fd9
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/core/AttributeAccessorSupportTests.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.core;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+
+/**
+ * @author Rob Harrop
+ * @since 2.0
+ */
+public class AttributeAccessorSupportTests extends TestCase {
+
+ private static final String NAME = "foo";
+
+ private static final String VALUE = "bar";
+
+ private AttributeAccessor attributeAccessor;
+
+ protected void setUp() throws Exception {
+ this.attributeAccessor = new AttributeAccessorSupport() {
+ };
+ }
+
+ public void testSetAndGet() throws Exception {
+ this.attributeAccessor.setAttribute(NAME, VALUE);
+ assertEquals(VALUE, this.attributeAccessor.getAttribute(NAME));
+ }
+
+ public void testSetAndHas() throws Exception {
+ assertFalse(this.attributeAccessor.hasAttribute(NAME));
+ this.attributeAccessor.setAttribute(NAME, VALUE);
+ assertTrue(this.attributeAccessor.hasAttribute(NAME));
+ }
+
+ public void testRemove() throws Exception {
+ assertFalse(this.attributeAccessor.hasAttribute(NAME));
+ this.attributeAccessor.setAttribute(NAME, VALUE);
+ assertEquals(VALUE, this.attributeAccessor.removeAttribute(NAME));
+ assertFalse(this.attributeAccessor.hasAttribute(NAME));
+ }
+
+ public void testAttributeNames() throws Exception {
+ this.attributeAccessor.setAttribute(NAME, VALUE);
+ this.attributeAccessor.setAttribute("abc", "123");
+ String[] attributeNames = this.attributeAccessor.attributeNames();
+ Arrays.sort(attributeNames);
+ assertTrue(Arrays.binarySearch(attributeNames, NAME) > -1);
+ assertTrue(Arrays.binarySearch(attributeNames, "abc") > -1);
+ }
+ protected void tearDown() throws Exception {
+ this.attributeAccessor.removeAttribute(NAME);
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/core/CollectionFactoryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/core/CollectionFactoryTests.java
new file mode 100644
index 00000000000..2bdd6df41a0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/core/CollectionFactoryTests.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.core;
+
+import java.util.IdentityHashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Darren Davison
+ * @author Juergen Hoeller
+ */
+public class CollectionFactoryTests extends TestCase {
+
+ public void testLinkedSet() {
+ Set set = CollectionFactory.createLinkedSetIfPossible(16);
+ assertTrue(set instanceof LinkedHashSet);
+ }
+
+ public void testLinkedMap() {
+ Map map = CollectionFactory.createLinkedMapIfPossible(16);
+ assertTrue(map instanceof LinkedHashMap);
+ }
+
+ public void testIdentityMap() {
+ Map map = CollectionFactory.createIdentityMapIfPossible(16);
+ assertTrue(map instanceof IdentityHashMap);
+ }
+
+ public void testConcurrentMap() {
+ Map map = CollectionFactory.createConcurrentMapIfPossible(16);
+ assertTrue(map.getClass().getName().endsWith("ConcurrentHashMap"));
+ }
+
+ public void testConcurrentMapWithExplicitInterface() {
+ ConcurrentMap map = CollectionFactory.createConcurrentMap(16);
+ assertTrue(map.getClass().getSuperclass().getName().endsWith("ConcurrentHashMap"));
+ map.putIfAbsent("key", "value1");
+ map.putIfAbsent("key", "value2");
+ assertEquals("value1", map.get("key"));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/core/ConstantsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/core/ConstantsTests.java
new file mode 100644
index 00000000000..ee7b7187eb1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/core/ConstantsTests.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.core;
+
+import java.util.Locale;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ * @since 28.04.2003
+ */
+public class ConstantsTests extends TestCase {
+
+ public void testConstants() {
+ Constants c = new Constants(A.class);
+ assertEquals(A.class.getName(), c.getClassName());
+ assertEquals(9, c.getSize());
+
+ assertEquals(c.asNumber("DOG").intValue(), A.DOG);
+ assertEquals(c.asNumber("dog").intValue(), A.DOG);
+ assertEquals(c.asNumber("cat").intValue(), A.CAT);
+
+ try {
+ c.asNumber("bogus");
+ fail("Can't get bogus field");
+ }
+ catch (ConstantException expected) {
+ }
+
+ assertTrue(c.asString("S1").equals(A.S1));
+ try {
+ c.asNumber("S1");
+ fail("Wrong type");
+ }
+ catch (ConstantException expected) {
+ }
+ }
+
+ public void testGetNames() {
+ Constants c = new Constants(A.class);
+
+ Set names = c.getNames("");
+ assertEquals(c.getSize(), names.size());
+ assertTrue(names.contains("DOG"));
+ assertTrue(names.contains("CAT"));
+ assertTrue(names.contains("S1"));
+
+ names = c.getNames("D");
+ assertEquals(1, names.size());
+ assertTrue(names.contains("DOG"));
+
+ names = c.getNames("d");
+ assertEquals(1, names.size());
+ assertTrue(names.contains("DOG"));
+ }
+
+ public void testGetValues() {
+ Constants c = new Constants(A.class);
+
+ Set values = c.getValues("");
+ assertEquals(7, values.size());
+ assertTrue(values.contains(new Integer(0)));
+ assertTrue(values.contains(new Integer(66)));
+ assertTrue(values.contains(""));
+
+ values = c.getValues("D");
+ assertEquals(1, values.size());
+ assertTrue(values.contains(new Integer(0)));
+
+ values = c.getValues("prefix");
+ assertEquals(2, values.size());
+ assertTrue(values.contains(new Integer(1)));
+ assertTrue(values.contains(new Integer(2)));
+
+ values = c.getValuesForProperty("myProperty");
+ assertEquals(2, values.size());
+ assertTrue(values.contains(new Integer(1)));
+ assertTrue(values.contains(new Integer(2)));
+ }
+
+ public void testGetValuesInTurkey() {
+ Locale oldLocale = Locale.getDefault();
+ Locale.setDefault(new Locale("tr", ""));
+ try {
+ Constants c = new Constants(A.class);
+
+ Set values = c.getValues("");
+ assertEquals(7, values.size());
+ assertTrue(values.contains(new Integer(0)));
+ assertTrue(values.contains(new Integer(66)));
+ assertTrue(values.contains(""));
+
+ values = c.getValues("D");
+ assertEquals(1, values.size());
+ assertTrue(values.contains(new Integer(0)));
+
+ values = c.getValues("prefix");
+ assertEquals(2, values.size());
+ assertTrue(values.contains(new Integer(1)));
+ assertTrue(values.contains(new Integer(2)));
+
+ values = c.getValuesForProperty("myProperty");
+ assertEquals(2, values.size());
+ assertTrue(values.contains(new Integer(1)));
+ assertTrue(values.contains(new Integer(2)));
+ }
+ finally {
+ Locale.setDefault(oldLocale);
+ }
+ }
+
+ public void testSuffixAccess() {
+ Constants c = new Constants(A.class);
+
+ Set names = c.getNamesForSuffix("_PROPERTY");
+ assertEquals(2, names.size());
+ assertTrue(names.contains("NO_PROPERTY"));
+ assertTrue(names.contains("YES_PROPERTY"));
+
+ Set values = c.getValuesForSuffix("_PROPERTY");
+ assertEquals(2, values.size());
+ assertTrue(values.contains(new Integer(3)));
+ assertTrue(values.contains(new Integer(4)));
+ }
+
+ public void testToCode() {
+ Constants c = new Constants(A.class);
+
+ assertEquals(c.toCode(new Integer(0), ""), "DOG");
+ assertEquals(c.toCode(new Integer(0), "D"), "DOG");
+ assertEquals(c.toCode(new Integer(0), "DO"), "DOG");
+ assertEquals(c.toCode(new Integer(0), "DoG"), "DOG");
+ assertEquals(c.toCode(new Integer(66), ""), "CAT");
+ assertEquals(c.toCode(new Integer(66), "C"), "CAT");
+ assertEquals(c.toCode(new Integer(66), "ca"), "CAT");
+ assertEquals(c.toCode(new Integer(66), "cAt"), "CAT");
+ assertEquals(c.toCode("", ""), "S1");
+ assertEquals(c.toCode("", "s"), "S1");
+ assertEquals(c.toCode("", "s1"), "S1");
+ try {
+ c.toCode("bogus", "bogus");
+ fail("Should have thrown ConstantException");
+ }
+ catch (ConstantException expected) {
+ }
+
+ assertEquals(c.toCodeForProperty(new Integer(1), "myProperty"), "MY_PROPERTY_NO");
+ assertEquals(c.toCodeForProperty(new Integer(2), "myProperty"), "MY_PROPERTY_YES");
+ try {
+ c.toCodeForProperty("bogus", "bogus");
+ fail("Should have thrown ConstantException");
+ }
+ catch (ConstantException expected) {
+ }
+
+ assertEquals(c.toCodeForSuffix(new Integer(0), ""), "DOG");
+ assertEquals(c.toCodeForSuffix(new Integer(0), "G"), "DOG");
+ assertEquals(c.toCodeForSuffix(new Integer(0), "OG"), "DOG");
+ assertEquals(c.toCodeForSuffix(new Integer(0), "DoG"), "DOG");
+ assertEquals(c.toCodeForSuffix(new Integer(66), ""), "CAT");
+ assertEquals(c.toCodeForSuffix(new Integer(66), "T"), "CAT");
+ assertEquals(c.toCodeForSuffix(new Integer(66), "at"), "CAT");
+ assertEquals(c.toCodeForSuffix(new Integer(66), "cAt"), "CAT");
+ assertEquals(c.toCodeForSuffix("", ""), "S1");
+ assertEquals(c.toCodeForSuffix("", "1"), "S1");
+ assertEquals(c.toCodeForSuffix("", "s1"), "S1");
+ try {
+ c.toCodeForSuffix("bogus", "bogus");
+ fail("Should have thrown ConstantException");
+ }
+ catch (ConstantException expected) {
+ }
+ }
+
+ public void testGetValuesWithNullPrefix() throws Exception {
+ Constants c = new Constants(A.class);
+ Set values = c.getValues(null);
+ assertEquals("Must have returned *all* public static final values", 7, values.size());
+ }
+
+ public void testGetValuesWithEmptyStringPrefix() throws Exception {
+ Constants c = new Constants(A.class);
+ Set values = c.getValues("");
+ assertEquals("Must have returned *all* public static final values", 7, values.size());
+ }
+
+ public void testGetValuesWithWhitespacedStringPrefix() throws Exception {
+ Constants c = new Constants(A.class);
+ Set values = c.getValues(" ");
+ assertEquals("Must have returned *all* public static final values", 7, values.size());
+ }
+
+ public void testWithClassThatExposesNoConstants() throws Exception {
+ Constants c = new Constants(NoConstants.class);
+ assertEquals(0, c.getSize());
+ final Set values = c.getValues("");
+ assertNotNull(values);
+ assertEquals(0, values.size());
+ }
+
+ public void testCtorWithNullClass() throws Exception {
+ try {
+ new Constants(null);
+ fail("Must have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {}
+ }
+
+
+ private static final class NoConstants {
+ }
+
+
+ private static final class A {
+
+ public static final int DOG = 0;
+ public static final int CAT = 66;
+ public static final String S1 = "";
+
+ public static final int PREFIX_NO = 1;
+ public static final int PREFIX_YES = 2;
+
+ public static final int MY_PROPERTY_NO = 1;
+ public static final int MY_PROPERTY_YES = 2;
+
+ public static final int NO_PROPERTY = 3;
+ public static final int YES_PROPERTY = 4;
+
+ /** ignore these */
+ protected static final int P = -1;
+ protected boolean f;
+ static final Object o = new Object();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/core/ConventionsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/core/ConventionsTests.java
new file mode 100644
index 00000000000..ce42c75d7c2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/core/ConventionsTests.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.core;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+
+/**
+ * @author Rob Harrop
+ */
+public class ConventionsTests extends TestCase {
+
+ public void testSimpleObject() {
+ TestBean testBean = new TestBean();
+ assertEquals("Incorrect singular variable name", "testBean", Conventions.getVariableName(testBean));
+ }
+
+ public void testArray() {
+ TestBean[] testBeans = new TestBean[0];
+ assertEquals("Incorrect plural array form", "testBeanList", Conventions.getVariableName(testBeans));
+ }
+
+ public void testCollections() {
+ List list = new ArrayList();
+ list.add(new TestBean());
+ assertEquals("Incorrect plural List form", "testBeanList", Conventions.getVariableName(list));
+
+ Set set = new HashSet();
+ set.add(new TestBean());
+ assertEquals("Incorrect plural Set form", "testBeanList", Conventions.getVariableName(set));
+
+ List emptyList = new ArrayList();
+ try {
+ Conventions.getVariableName(emptyList);
+ fail("Should not be able to generate name for empty collection");
+ }
+ catch(IllegalArgumentException ex) {
+ // success
+ }
+ }
+
+ public void testAttributeNameToPropertyName() throws Exception {
+ assertEquals("transactionManager", Conventions.attributeNameToPropertyName("transaction-manager"));
+ assertEquals("pointcutRef", Conventions.attributeNameToPropertyName("pointcut-ref"));
+ assertEquals("lookupOnStartup", Conventions.attributeNameToPropertyName("lookup-on-startup"));
+ }
+
+ public void testGetQualifiedAttributeName() throws Exception {
+ String baseName = "foo";
+ Class cls = String.class;
+ String desiredResult = "java.lang.String.foo";
+ assertEquals(desiredResult, Conventions.getQualifiedAttributeName(cls, baseName));
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/core/DefaultControlFlowTests.java b/org.springframework.testsuite/src/test/java/org/springframework/core/DefaultControlFlowTests.java
new file mode 100644
index 00000000000..d527f769eac
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/core/DefaultControlFlowTests.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.core;
+
+/**
+ * Tests with ControlFlowFactory return.
+ *
+ * @author Rod Johnson
+ */
+public class DefaultControlFlowTests extends AbstractControlFlowTests {
+
+ /**
+ * Necessary only because Eclipse won't run test suite unless
+ * it declares some methods as well as inherited methods.
+ */
+ public void testThisClassPlease() {
+ }
+
+ protected ControlFlow createControlFlow() {
+ return ControlFlowFactory.createControlFlow();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/core/Jdk14ControlFlowTests.java b/org.springframework.testsuite/src/test/java/org/springframework/core/Jdk14ControlFlowTests.java
new file mode 100644
index 00000000000..040a6fcf20b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/core/Jdk14ControlFlowTests.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.core;
+
+/**
+ * Tests with ControlFlowFactory return.
+ *
+ * @author Rod Johnson
+ */
+public class Jdk14ControlFlowTests extends AbstractControlFlowTests {
+
+ /**
+ * Necessary only because Eclipse won't run test suite unless it declares
+ * some methods as well as inherited methods
+ */
+ public void testThisClassPlease() {
+ }
+
+ protected ControlFlow createControlFlow() {
+ return ControlFlowFactory.createControlFlow();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/core/LocalVariableTableParameterNameDiscovererTests.java b/org.springframework.testsuite/src/test/java/org/springframework/core/LocalVariableTableParameterNameDiscovererTests.java
new file mode 100644
index 00000000000..f12d96f1303
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/core/LocalVariableTableParameterNameDiscovererTests.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.core;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+
+/**
+ * @author Adrian Colyer
+ */
+public class LocalVariableTableParameterNameDiscovererTests extends TestCase {
+
+ private LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
+
+
+ public void testMethodParameterNameDiscoveryNoArgs() throws NoSuchMethodException {
+ Method getName = TestBean.class.getMethod("getName", new Class[0]);
+ String[] names = discoverer.getParameterNames(getName);
+ assertNotNull("should find method info", names);
+ assertEquals("no argument names", 0, names.length);
+ }
+
+ public void testMethodParameterNameDiscoveryWithArgs() throws NoSuchMethodException {
+ Method setName = TestBean.class.getMethod("setName", new Class[]{String.class});
+ String[] names = discoverer.getParameterNames(setName);
+ assertNotNull("should find method info", names);
+ assertEquals("one argument", 1, names.length);
+ assertEquals("name", names[0]);
+ }
+
+ public void testConsParameterNameDiscoveryNoArgs() throws NoSuchMethodException {
+ Constructor noArgsCons = TestBean.class.getConstructor(new Class[0]);
+ String[] names = discoverer.getParameterNames(noArgsCons);
+ assertNotNull("should find cons info", names);
+ assertEquals("no argument names", 0, names.length);
+ }
+
+ public void testConsParameterNameDiscoveryArgs() throws NoSuchMethodException {
+ Constructor twoArgCons = TestBean.class.getConstructor(new Class[]{String.class, int.class});
+ String[] names = discoverer.getParameterNames(twoArgCons);
+ assertNotNull("should find cons info", names);
+ assertEquals("one argument", 2, names.length);
+ assertEquals("name", names[0]);
+ assertEquals("age", names[1]);
+ }
+
+ public void testStaticMethodParameterNameDiscoveryNoArgs() throws NoSuchMethodException {
+ Method m = getClass().getMethod("staticMethodNoLocalVars", new Class[0]);
+ String[] names = discoverer.getParameterNames(m);
+ assertNotNull("should find method info", names);
+ assertEquals("no argument names", 0, names.length);
+ }
+
+ public void testOverloadedStaticMethod() throws Exception {
+ Class clazz = this.getClass();
+
+ Method m1 = clazz.getMethod("staticMethod", new Class[]{Long.TYPE, Long.TYPE});
+ String[] names = discoverer.getParameterNames(m1);
+ assertNotNull("should find method info", names);
+ assertEquals("two arguments", 2, names.length);
+ assertEquals("x", names[0]);
+ assertEquals("y", names[1]);
+
+ Method m2 = clazz.getMethod("staticMethod", new Class[]{Long.TYPE, Long.TYPE, Long.TYPE});
+ names = discoverer.getParameterNames(m2);
+ assertNotNull("should find method info", names);
+ assertEquals("three arguments", 3, names.length);
+ assertEquals("x", names[0]);
+ assertEquals("y", names[1]);
+ assertEquals("z", names[2]);
+ }
+
+ public void testOverloadedStaticMethodInInnerClass() throws Exception {
+ Class clazz = InnerClass.class;
+
+ Method m1 = clazz.getMethod("staticMethod", new Class[]{Long.TYPE});
+ String[] names = discoverer.getParameterNames(m1);
+ assertNotNull("should find method info", names);
+ assertEquals("one argument", 1, names.length);
+ assertEquals("x", names[0]);
+
+ Method m2 = clazz.getMethod("staticMethod", new Class[]{Long.TYPE, Long.TYPE});
+ names = discoverer.getParameterNames(m2);
+ assertNotNull("should find method info", names);
+ assertEquals("two arguments", 2, names.length);
+ assertEquals("x", names[0]);
+ assertEquals("y", names[1]);
+ }
+
+ public void testOverloadedMethod() throws Exception {
+ Class clazz = this.getClass();
+
+ Method m1 = clazz.getMethod("instanceMethod", new Class[]{Double.TYPE, Double.TYPE});
+ String[] names = discoverer.getParameterNames(m1);
+ assertNotNull("should find method info", names);
+ assertEquals("two arguments", 2, names.length);
+ assertEquals("x", names[0]);
+ assertEquals("y", names[1]);
+
+ Method m2 = clazz.getMethod("instanceMethod", new Class[]{Double.TYPE, Double.TYPE, Double.TYPE});
+ names = discoverer.getParameterNames(m2);
+ assertNotNull("should find method info", names);
+ assertEquals("three arguments", 3, names.length);
+ assertEquals("x", names[0]);
+ assertEquals("y", names[1]);
+ assertEquals("z", names[2]);
+ }
+
+ public void testOverloadedMethodInInnerClass() throws Exception {
+ Class clazz = InnerClass.class;
+
+ Method m1 = clazz.getMethod("instanceMethod", new Class[]{String.class});
+ String[] names = discoverer.getParameterNames(m1);
+ assertNotNull("should find method info", names);
+ assertEquals("one argument", 1, names.length);
+ assertEquals("aa", names[0]);
+
+ Method m2 = clazz.getMethod("instanceMethod", new Class[]{String.class, String.class});
+ names = discoverer.getParameterNames(m2);
+ assertNotNull("should find method info", names);
+ assertEquals("two arguments", 2, names.length);
+ assertEquals("aa", names[0]);
+ assertEquals("bb", names[1]);
+ }
+
+
+ public static void staticMethodNoLocalVars() {
+ }
+
+ public static long staticMethod(long x, long y) {
+ long u = x * y;
+ return u;
+ }
+
+ public static long staticMethod(long x, long y, long z) {
+ long u = x * y * z;
+ return u;
+ }
+
+ public double instanceMethod(double x, double y) {
+ double u = x * y;
+ return u;
+ }
+
+ public double instanceMethod(double x, double y, double z) {
+ double u = x * y * z;
+ return u;
+ }
+
+
+ public static class InnerClass {
+
+ public int waz = 0;
+
+ public InnerClass() {
+ }
+
+ public InnerClass(String firstArg, long secondArg, Object thirdArg) {
+ long foo = 0;
+ short bar = 10;
+ this.waz = (int) (foo + bar);
+ }
+
+ public String instanceMethod(String aa) {
+ return aa;
+ }
+
+ public String instanceMethod(String aa, String bb) {
+ return aa + bb;
+ }
+
+ public static long staticMethod(long x) {
+ long u = x;
+ return u;
+ }
+
+ public static long staticMethod(long x, long y) {
+ long u = x * y;
+ return u;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/core/NestedExceptionTests.java b/org.springframework.testsuite/src/test/java/org/springframework/core/NestedExceptionTests.java
new file mode 100644
index 00000000000..ddc7056802b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/core/NestedExceptionTests.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.core;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletException;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public class NestedExceptionTests extends TestCase {
+
+ public void testNestedRuntimeExceptionWithNoRootCause() {
+ String mesg = "mesg of mine";
+ // Making a class abstract doesn't _really_ prevent instantiation :-)
+ NestedRuntimeException nex = new NestedRuntimeException(mesg) {};
+ assertNull(nex.getCause());
+ assertEquals(nex.getMessage(), mesg);
+
+ // Check printStackTrace
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintWriter pw = new PrintWriter(baos);
+ nex.printStackTrace(pw);
+ pw.flush();
+ String stackTrace = new String(baos.toByteArray());
+ assertFalse(stackTrace.indexOf(mesg) == -1);
+ }
+
+ public void testNestedRuntimeExceptionWithRootCause() {
+ String myMessage = "mesg for this exception";
+ String rootCauseMesg = "this is the obscure message of the root cause";
+ ServletException rootCause = new ServletException(rootCauseMesg);
+ // Making a class abstract doesn't _really_ prevent instantiation :-)
+ NestedRuntimeException nex = new NestedRuntimeException(myMessage, rootCause) {};
+ assertEquals(nex.getCause(), rootCause);
+ assertTrue(nex.getMessage().indexOf(myMessage) != -1);
+ assertTrue(nex.getMessage().indexOf(rootCauseMesg) != -1);
+
+ // check PrintStackTrace
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintWriter pw = new PrintWriter(baos);
+ nex.printStackTrace(pw);
+ pw.flush();
+ String stackTrace = new String(baos.toByteArray());
+ assertFalse(stackTrace.indexOf(rootCause.getClass().getName()) == -1);
+ assertFalse(stackTrace.indexOf(rootCauseMesg) == -1);
+ }
+
+ public void testNestedCheckedExceptionWithNoRootCause() {
+ String mesg = "mesg of mine";
+ // Making a class abstract doesn't _really_ prevent instantiation :-)
+ NestedCheckedException nex = new NestedCheckedException(mesg) {};
+ assertNull(nex.getCause());
+ assertEquals(nex.getMessage(), mesg);
+
+ // Check printStackTrace
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintWriter pw = new PrintWriter(baos);
+ nex.printStackTrace(pw);
+ pw.flush();
+ String stackTrace = new String(baos.toByteArray());
+ assertFalse(stackTrace.indexOf(mesg) == -1);
+ }
+
+ public void testNestedCheckedExceptionWithRootCause() {
+ String myMessage = "mesg for this exception";
+ String rootCauseMesg = "this is the obscure message of the root cause";
+ ServletException rootCause = new ServletException(rootCauseMesg);
+ // Making a class abstract doesn't _really_ prevent instantiation :-)
+ NestedCheckedException nex = new NestedCheckedException(myMessage, rootCause) {};
+ assertEquals(nex.getCause(), rootCause);
+ assertTrue(nex.getMessage().indexOf(myMessage) != -1);
+ assertTrue(nex.getMessage().indexOf(rootCauseMesg) != -1);
+
+ // check PrintStackTrace
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintWriter pw = new PrintWriter(baos);
+ nex.printStackTrace(pw);
+ pw.flush();
+ String stackTrace = new String(baos.toByteArray());
+ assertFalse(stackTrace.indexOf(rootCause.getClass().getName()) == -1);
+ assertFalse(stackTrace.indexOf(rootCauseMesg) == -1);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/core/OrderComparatorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/core/OrderComparatorTests.java
new file mode 100644
index 00000000000..9c9d515bab6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/core/OrderComparatorTests.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.core;
+
+import junit.framework.TestCase;
+
+import java.util.Comparator;
+
+/**
+ * Unit tests for the {@link OrderComparator} class.
+ *
+ * @author Rick Evans
+ */
+public final class OrderComparatorTests extends TestCase {
+
+ private Comparator comparator;
+
+
+ protected void setUp() throws Exception {
+ this.comparator = new OrderComparator();
+ }
+
+
+ public void testCompareOrderedInstancesBefore() throws Exception {
+ assertEquals(-1, this.comparator.compare(
+ new StubOrdered(100), new StubOrdered(2000)));
+ }
+
+ public void testCompareOrderedInstancesSame() throws Exception {
+ assertEquals(0, this.comparator.compare(
+ new StubOrdered(100), new StubOrdered(100)));
+ }
+
+ public void testCompareOrderedInstancesAfter() throws Exception {
+ assertEquals(1, this.comparator.compare(
+ new StubOrdered(982300), new StubOrdered(100)));
+ }
+
+ public void testCompareTwoNonOrderedInstancesEndsUpAsSame() throws Exception {
+ assertEquals(0, this.comparator.compare(new Object(), new Object()));
+ }
+
+
+ private static final class StubOrdered implements Ordered {
+
+ private final int order;
+
+
+ public StubOrdered(int order) {
+ this.order = order;
+ }
+
+ public int getOrder() {
+ return this.order;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/core/PrioritizedParameterNameDiscovererTests.java b/org.springframework.testsuite/src/test/java/org/springframework/core/PrioritizedParameterNameDiscovererTests.java
new file mode 100644
index 00000000000..c51d8c1dbfa
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/core/PrioritizedParameterNameDiscovererTests.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.core;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+
+public class PrioritizedParameterNameDiscovererTests extends TestCase {
+
+ private static final String[] FOO_BAR = new String[] { "foo", "bar" };
+
+ private static final String[] SOMETHING_ELSE = new String[] { "something", "else" };
+
+ ParameterNameDiscoverer returnsFooBar = new ParameterNameDiscoverer() {
+ public String[] getParameterNames(Method m) {
+ return FOO_BAR;
+ }
+ public String[] getParameterNames(Constructor ctor) {
+ return FOO_BAR;
+ }
+ };
+
+ ParameterNameDiscoverer returnsSomethingElse = new ParameterNameDiscoverer() {
+ public String[] getParameterNames(Method m) {
+ return SOMETHING_ELSE;
+ }
+ public String[] getParameterNames(Constructor ctor) {
+ return SOMETHING_ELSE;
+ }
+ };
+
+ private final Method anyMethod;
+ private final Class anyClass = Object.class;
+
+ public PrioritizedParameterNameDiscovererTests() throws SecurityException, NoSuchMethodException {
+ anyMethod = TestBean.class.getMethod("getAge", (Class[]) null);
+ }
+
+ public void testNoParametersDiscoverers() {
+ ParameterNameDiscoverer pnd = new PrioritizedParameterNameDiscoverer();
+ assertNull(pnd.getParameterNames(anyMethod));
+ assertNull(pnd.getParameterNames((Constructor) null));
+ }
+
+ public void testOrderedParameterDiscoverers1() {
+ PrioritizedParameterNameDiscoverer pnd = new PrioritizedParameterNameDiscoverer();
+ pnd.addDiscoverer(returnsFooBar);
+ assertTrue(Arrays.equals(FOO_BAR, pnd.getParameterNames(anyMethod)));
+ assertTrue(Arrays.equals(FOO_BAR, pnd.getParameterNames((Constructor) null)));
+ pnd.addDiscoverer(returnsSomethingElse);
+ assertTrue(Arrays.equals(FOO_BAR, pnd.getParameterNames(anyMethod)));
+ assertTrue(Arrays.equals(FOO_BAR, pnd.getParameterNames((Constructor) null)));
+ }
+
+ public void testOrderedParameterDiscoverers2() {
+ PrioritizedParameterNameDiscoverer pnd = new PrioritizedParameterNameDiscoverer();
+ pnd.addDiscoverer(returnsSomethingElse);
+ assertTrue(Arrays.equals(SOMETHING_ELSE, pnd.getParameterNames(anyMethod)));
+ assertTrue(Arrays.equals(SOMETHING_ELSE, pnd.getParameterNames((Constructor) null)));
+ pnd.addDiscoverer(returnsFooBar);
+ assertTrue(Arrays.equals(SOMETHING_ELSE, pnd.getParameterNames(anyMethod)));
+ assertTrue(Arrays.equals(SOMETHING_ELSE, pnd.getParameterNames((Constructor) null)));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/core/enums/LabeledEnumTests.java b/org.springframework.testsuite/src/test/java/org/springframework/core/enums/LabeledEnumTests.java
new file mode 100644
index 00000000000..0e57814ac56
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/core/enums/LabeledEnumTests.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.core.enums;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Keith Donald
+ * @author Juergen Hoeller
+ * @author Sam Brannen
+ */
+public class LabeledEnumTests extends TestCase {
+
+ private byte[] serializeObject(final Object obj) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(obj);
+ oos.close();
+ return baos.toByteArray();
+ }
+
+ private Object deserializeObject(final byte[] serializedBytes) throws IOException, ClassNotFoundException {
+ ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(serializedBytes));
+ Object obj = ois.readObject();
+ ois.close();
+ return obj;
+ }
+
+ private Object serializeAndDeserializeObject(Object obj) throws IOException, ClassNotFoundException {
+ return deserializeObject(serializeObject(obj));
+ }
+
+ public void testCodeFound() {
+ Dog golden = (Dog) StaticLabeledEnumResolver.instance().getLabeledEnumByCode(Dog.class, new Short((short) 11));
+ Dog borderCollie = (Dog) StaticLabeledEnumResolver.instance().getLabeledEnumByCode(Dog.class,
+ new Short((short) 13));
+ assertSame(golden, Dog.GOLDEN_RETRIEVER);
+ assertSame(borderCollie, Dog.BORDER_COLLIE);
+ }
+
+ public void testCodeFoundForAbstractEnums() {
+ ValuedEnum one = (ValuedEnum) StaticLabeledEnumResolver.instance().getLabeledEnumByCode(ValuedEnum.class,
+ new Short((short) 1));
+ ValuedEnum two = (ValuedEnum) StaticLabeledEnumResolver.instance().getLabeledEnumByCode(ValuedEnum.class,
+ new Short((short) 2));
+ assertSame(one, ValuedEnum.ONE);
+ assertSame(two, ValuedEnum.TWO);
+ }
+
+ public void testDeserializationOfInnerClassEnums() throws Exception {
+ assertSame(serializeAndDeserializeObject(Other.THING1), Other.THING1);
+ }
+
+ public void testDeserializationOfStandAloneEnums() throws Exception {
+ assertSame(serializeAndDeserializeObject(StandAloneStaticLabeledEnum.ENUM1),
+ StandAloneStaticLabeledEnum.ENUM1);
+ }
+
+ public void testLabelFound() {
+ Dog golden = (Dog) StaticLabeledEnumResolver.instance().getLabeledEnumByLabel(Dog.class, "Golden Retriever");
+ Dog borderCollie = (Dog) StaticLabeledEnumResolver.instance().getLabeledEnumByLabel(Dog.class, "Border Collie");
+ assertSame(golden, Dog.GOLDEN_RETRIEVER);
+ assertSame(borderCollie, Dog.BORDER_COLLIE);
+ }
+
+ public void testLabelFoundForStandAloneEnum() {
+ StandAloneStaticLabeledEnum enum1 = (StandAloneStaticLabeledEnum)
+ StaticLabeledEnumResolver.instance().getLabeledEnumByLabel(StandAloneStaticLabeledEnum.class, "Enum1");
+ StandAloneStaticLabeledEnum enum2 = (StandAloneStaticLabeledEnum)
+ StaticLabeledEnumResolver.instance().getLabeledEnumByLabel(StandAloneStaticLabeledEnum.class, "Enum2");
+ assertSame(enum1, StandAloneStaticLabeledEnum.ENUM1);
+ assertSame(enum2, StandAloneStaticLabeledEnum.ENUM2);
+ }
+
+ public void testLabelFoundForAbstractEnums() {
+ ValuedEnum one = (ValuedEnum)
+ StaticLabeledEnumResolver.instance().getLabeledEnumByLabel(ValuedEnum.class, "one");
+ ValuedEnum two = (ValuedEnum)
+ StaticLabeledEnumResolver.instance().getLabeledEnumByLabel(ValuedEnum.class, "two");
+ assertSame(one, ValuedEnum.ONE);
+ assertSame(two, ValuedEnum.TWO);
+ }
+
+ public void testDoesNotMatchWrongClass() {
+ try {
+ LabeledEnum none = StaticLabeledEnumResolver.instance().getLabeledEnumByCode(Dog.class,
+ new Short((short) 1));
+ fail("Should have failed");
+ }
+ catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testEquals() {
+ assertEquals("Code equality means equals", Dog.GOLDEN_RETRIEVER, new Dog(11, "Golden Retriever"));
+ assertFalse("Code inequality means notEquals", Dog.GOLDEN_RETRIEVER.equals(new Dog(12, "Golden Retriever")));
+ }
+
+
+ private static class Other extends StaticLabeledEnum {
+
+ public static final Other THING1 = new Other(1, "Thing1");
+ public static final Other THING2 = new Other(2, "Thing2");
+
+
+ private Other(int code, String name) {
+ super(code, name);
+ }
+ }
+
+
+ private static class Dog extends StaticLabeledEnum {
+
+ public static final Dog GOLDEN_RETRIEVER = new Dog(11, null) {
+
+ public String getLabel() {
+ return "Golden Retriever";
+ }
+
+ // Overriding getType() is no longer necessary as of Spring 2.5;
+ // however, this is left here to provide valid testing for
+ // backwards compatibility.
+ public Class getType() {
+ return Dog.class;
+ }
+ };
+
+ public static final Dog BORDER_COLLIE = new Dog(13, "Border Collie");
+ public static final Dog WHIPPET = new Dog(14, "Whippet");
+
+ // Ignore this
+ public static final Other THING1 = Other.THING1;
+
+
+ private Dog(int code, String name) {
+ super(code, name);
+ }
+ }
+
+
+ private static abstract class ValuedEnum extends StaticLabeledEnum {
+
+ public static final ValuedEnum ONE = new ValuedEnum(1, "one") {
+ public int getValue() {
+ return 1;
+ }
+ };
+
+ public static final ValuedEnum TWO = new ValuedEnum(2, "two") {
+ public int getValue() {
+ return 2;
+ }
+ };
+
+ private ValuedEnum(int code, String name) {
+ super(code, name);
+ }
+
+ public abstract int getValue();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/core/enums/StandAloneStaticLabeledEnum.java b/org.springframework.testsuite/src/test/java/org/springframework/core/enums/StandAloneStaticLabeledEnum.java
new file mode 100644
index 00000000000..078f39864c5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/core/enums/StandAloneStaticLabeledEnum.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.core.enums;
+
+/**
+ * Stand-alone static enum for use in {@link LabeledEnumTests}.
+ *
+ * @author Sam Brannen
+ * @since 2.5
+ */
+public class StandAloneStaticLabeledEnum extends StaticLabeledEnum {
+
+ private static final long serialVersionUID = 1L;
+
+ public static final StandAloneStaticLabeledEnum ENUM1 = new StandAloneStaticLabeledEnum(1, "Enum1");
+ public static final StandAloneStaticLabeledEnum ENUM2 = new StandAloneStaticLabeledEnum(2, "Enum2");
+
+
+ private StandAloneStaticLabeledEnum(int code, String name) {
+ super(code, name);
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/core/io/ResourceEditorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/core/io/ResourceEditorTests.java
new file mode 100644
index 00000000000..c9a4797c3a9
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/core/io/ResourceEditorTests.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.core.io;
+
+import junit.framework.TestCase;
+import org.springframework.test.AssertThrows;
+
+import java.beans.PropertyEditor;
+
+/**
+ * Unit tests for the {@link ResourceEditor} class.
+ *
+ * @author Rick Evans
+ */
+public final class ResourceEditorTests extends TestCase {
+
+ public void testSunnyDay() throws Exception {
+ PropertyEditor editor = new ResourceEditor();
+ editor.setAsText("classpath:org/springframework/core/io/ResourceEditorTests.class");
+ Resource resource = (Resource) editor.getValue();
+ assertNotNull(resource);
+ assertTrue(resource.exists());
+ }
+
+ public void testCtorWithNullResourceLoader() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new ResourceEditor(null);
+ }
+ }.runTest();
+ }
+
+ public void testSetAndGetAsTextWithNull() throws Exception {
+ PropertyEditor editor = new ResourceEditor();
+ editor.setAsText(null);
+ assertEquals("", editor.getAsText());
+ }
+
+ public void testSetAndGetAsTextWithWhitespaceResource() throws Exception {
+ PropertyEditor editor = new ResourceEditor();
+ editor.setAsText(" ");
+ assertEquals("", editor.getAsText());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/core/io/ResourceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/core/io/ResourceTests.java
new file mode 100644
index 00000000000..8b01a3be688
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/core/io/ResourceTests.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.core.io;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.HashSet;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.util.FileCopyUtils;
+import org.springframework.web.context.support.ServletContextResource;
+
+/**
+ * @author Juergen Hoeller
+ * @since 09.09.2004
+ */
+public class ResourceTests extends TestCase {
+
+ public void testByteArrayResource() throws IOException {
+ Resource resource = new ByteArrayResource("testString".getBytes());
+ assertTrue(resource.exists());
+ assertFalse(resource.isOpen());
+ String content = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream()));
+ assertEquals("testString", content);
+ assertEquals(resource, new ByteArrayResource("testString".getBytes()));
+ }
+
+ public void testByteArrayResourceWithDescription() throws IOException {
+ Resource resource = new ByteArrayResource("testString".getBytes(), "my description");
+ assertTrue(resource.exists());
+ assertFalse(resource.isOpen());
+ String content = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream()));
+ assertEquals("testString", content);
+ assertEquals("my description", resource.getDescription());
+ assertEquals(resource, new ByteArrayResource("testString".getBytes()));
+ }
+
+ public void testInputStreamResource() throws IOException {
+ InputStream is = new ByteArrayInputStream("testString".getBytes());
+ Resource resource = new InputStreamResource(is);
+ assertTrue(resource.exists());
+ assertTrue(resource.isOpen());
+ String content = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream()));
+ assertEquals("testString", content);
+ assertEquals(resource, new InputStreamResource(is));
+ }
+
+ public void testInputStreamResourceWithDescription() throws IOException {
+ InputStream is = new ByteArrayInputStream("testString".getBytes());
+ Resource resource = new InputStreamResource(is, "my description");
+ assertTrue(resource.exists());
+ assertTrue(resource.isOpen());
+ String content = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream()));
+ assertEquals("testString", content);
+ assertEquals("my description", resource.getDescription());
+ assertEquals(resource, new InputStreamResource(is));
+ }
+
+ public void testClassPathResource() throws IOException {
+ Resource resource = new ClassPathResource("org/springframework/core/io/Resource.class");
+ doTestResource(resource);
+ Resource resource2 = new ClassPathResource("org/springframework/core/../core/io/./Resource.class");
+ assertEquals(resource, resource2);
+ Resource resource3 = new ClassPathResource("org/springframework/core/").createRelative("../core/io/./Resource.class");
+ assertEquals(resource, resource3);
+
+ // Check whether equal/hashCode works in a HashSet.
+ HashSet resources = new HashSet();
+ resources.add(resource);
+ resources.add(resource2);
+ assertEquals(1, resources.size());
+ }
+
+ public void testClassPathResourceWithClassLoader() throws IOException {
+ Resource resource =
+ new ClassPathResource("org/springframework/core/io/Resource.class", getClass().getClassLoader());
+ doTestResource(resource);
+ assertEquals(resource,
+ new ClassPathResource("org/springframework/core/../core/io/./Resource.class", getClass().getClassLoader()));
+ }
+
+ public void testClassPathResourceWithClass() throws IOException {
+ Resource resource = new ClassPathResource("Resource.class", getClass());
+ doTestResource(resource);
+ assertEquals(resource, new ClassPathResource("Resource.class", getClass()));
+ }
+
+ public void testFileSystemResource() throws IOException {
+ Resource resource = new FileSystemResource(getClass().getResource("Resource.class").getFile());
+ doTestResource(resource);
+ assertEquals(new FileSystemResource(getClass().getResource("Resource.class").getFile()), resource);
+ Resource resource2 = new FileSystemResource("core/io/Resource.class");
+ assertEquals(resource2, new FileSystemResource("core/../core/io/./Resource.class"));
+ }
+
+ public void testUrlResource() throws IOException {
+ Resource resource = new UrlResource(getClass().getResource("Resource.class"));
+ doTestResource(resource);
+ assertEquals(new UrlResource(getClass().getResource("Resource.class")), resource);
+ Resource resource2 = new UrlResource("file:core/io/Resource.class");
+ assertEquals(resource2, new UrlResource("file:core/../core/io/./Resource.class"));
+ }
+
+ public void testServletContextResource() throws IOException {
+ MockServletContext sc = new MockServletContext();
+ Resource resource = new ServletContextResource(sc, "org/springframework/core/io/Resource.class");
+ doTestResource(resource);
+ assertEquals(resource, new ServletContextResource(sc, "org/springframework/core/../core/io/./Resource.class"));
+ }
+
+ private void doTestResource(Resource resource) throws IOException {
+ assertEquals("Resource.class", resource.getFilename());
+ assertTrue(resource.getURL().getFile().endsWith("Resource.class"));
+
+ Resource relative1 = resource.createRelative("ClassPathResource.class");
+ assertEquals("ClassPathResource.class", relative1.getFilename());
+ assertTrue(relative1.getURL().getFile().endsWith("ClassPathResource.class"));
+ assertTrue(relative1.exists());
+
+ Resource relative2 = resource.createRelative("support/ResourcePatternResolver.class");
+ assertEquals("ResourcePatternResolver.class", relative2.getFilename());
+ assertTrue(relative2.getURL().getFile().endsWith("ResourcePatternResolver.class"));
+ assertTrue(relative2.exists());
+
+ Resource relative3 = resource.createRelative("../SpringVersion.class");
+ assertEquals("SpringVersion.class", relative3.getFilename());
+ assertTrue(relative3.getURL().getFile().endsWith("SpringVersion.class"));
+ assertTrue(relative3.exists());
+ }
+
+ public void testClassPathResourceWithRelativePath() throws IOException {
+ Resource resource = new ClassPathResource("dir/");
+ Resource relative = resource.createRelative("subdir");
+ assertEquals(new ClassPathResource("dir/subdir"), relative);
+ }
+
+ public void testFileSystemResourceWithRelativePath() throws IOException {
+ Resource resource = new FileSystemResource("dir/");
+ Resource relative = resource.createRelative("subdir");
+ assertEquals(new FileSystemResource("dir/subdir"), relative);
+ }
+
+ public void testUrlResourceWithRelativePath() throws IOException {
+ Resource resource = new UrlResource("file:dir/");
+ Resource relative = resource.createRelative("subdir");
+ assertEquals(new UrlResource("file:dir/subdir"), relative);
+ }
+
+ public void testServletContextResourceWithRelativePath() throws IOException {
+ MockServletContext sc = new MockServletContext();
+ Resource resource = new ServletContextResource(sc, "dir/");
+ Resource relative = resource.createRelative("subdir");
+ assertEquals(new ServletContextResource(sc, "dir/subdir"), relative);
+ }
+
+ /*
+ public void testNonFileResourceExists() throws Exception {
+ Resource resource = new UrlResource("http://www.springframework.org");
+ assertTrue(resource.exists());
+ }
+ */
+
+ public void testAbstractResourceExceptions() throws Exception {
+ final String name = "test-resource";
+
+ Resource resource = new AbstractResource() {
+ public String getDescription() {
+ return name;
+ }
+ public InputStream getInputStream() {
+ return null;
+ }
+ };
+
+ try {
+ resource.getURL();
+ fail("FileNotFoundException should have been thrown");
+ }
+ catch (FileNotFoundException ex) {
+ assertTrue(ex.getMessage().indexOf(name) != -1);
+ }
+ try {
+ resource.getFile();
+ fail("FileNotFoundException should have been thrown");
+ }
+ catch (FileNotFoundException ex) {
+ assertTrue(ex.getMessage().indexOf(name) != -1);
+ }
+ try {
+ resource.createRelative("/testing");
+ fail("FileNotFoundException should have been thrown");
+ }
+ catch (FileNotFoundException ex) {
+ assertTrue(ex.getMessage().indexOf(name) != -1);
+ }
+ try {
+ resource.getFilename();
+ fail("IllegalStateException should have been thrown");
+ }
+ catch (IllegalStateException ex) {
+ assertTrue(ex.getMessage().indexOf(name) != -1);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/core/io/support/PathMatchingResourcePatternResolverTests.java b/org.springframework.testsuite/src/test/java/org/springframework/core/io/support/PathMatchingResourcePatternResolverTests.java
new file mode 100644
index 00000000000..52253d8e8e0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/core/io/support/PathMatchingResourcePatternResolverTests.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.core.io.support;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.springframework.core.io.Resource;
+
+/**
+ * If this test case fails, uncomment diagnostics in
+ * assertProtocolAndFilenames method.
+ *
+ * @author Oliver Hutchison
+ * @author Juergen Hoeller
+ * @since 17.11.2004
+ */
+public class PathMatchingResourcePatternResolverTests extends TestCase {
+
+ private static final String[] CLASSES_IN_CORE_IO_SUPPORT =
+ new String[] {"EncodedResource.class", "LocalizedResourceHelper.class",
+ "PathMatchingResourcePatternResolver.class",
+ "PropertiesLoaderSupport.class", "PropertiesLoaderUtils.class",
+ "ResourceArrayPropertyEditor.class",
+ "ResourcePatternResolver.class", "ResourcePatternUtils.class"};
+
+ private static final String[] TEST_CLASSES_IN_CORE_IO_SUPPORT =
+ new String[] {"PathMatchingResourcePatternResolverTests.class"};
+
+ private static final String[] CLASSES_IN_AOPALLIANCE =
+ new String[] {"Advice.class", "AspectException.class", "ConstructorInterceptor.class",
+ "ConstructorInvocation.class", "Interceptor.class", "Invocation.class",
+ "Joinpoint.class", "MethodInterceptor.class", "MethodInvocation.class"};
+
+ private PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
+
+
+ public void testInvalidPrefixWithPatternElementInIt() throws IOException {
+ try {
+ resolver.getResources("xx**:**/*.xy");
+ fail("Should have thrown FileNotFoundException");
+ }
+ catch (FileNotFoundException ex) {
+ // expected
+ }
+ }
+
+ public void testSingleResourceOnFileSystem() throws IOException {
+ Resource[] resources =
+ resolver.getResources("org/springframework/core/io/support/PathMatchingResourcePatternResolverTests.class");
+ assertEquals(1, resources.length);
+ assertProtocolAndFilename(resources[0], "file", "PathMatchingResourcePatternResolverTests.class");
+ }
+
+ public void testSingleResourceInJar() throws IOException {
+ Resource[] resources = resolver.getResources("java/net/URL.class");
+ assertEquals(1, resources.length);
+ assertProtocolAndFilename(resources[0], "jar", "URL.class");
+ }
+
+ public void testClasspathStarWithPatternOnFileSystem() throws IOException {
+ Resource[] resources = resolver.getResources("classpath*:org/springframework/core/io/sup*/*.class");
+ // Have to exclude Clover-generated class files here,
+ // as we might be running as part of a Clover test run.
+ List noCloverResources = new ArrayList();
+ for (int i = 0; i < resources.length; i++) {
+ if (resources[i].getFilename().indexOf("$__CLOVER_") == -1) {
+ noCloverResources.add(resources[i]);
+ }
+ }
+ resources = (Resource[]) noCloverResources.toArray(new Resource[noCloverResources.size()]);
+ assertProtocolAndFilenames(resources, "file", CLASSES_IN_CORE_IO_SUPPORT, TEST_CLASSES_IN_CORE_IO_SUPPORT);
+ }
+
+ public void testClasspathWithPatternInJar() throws IOException {
+ Resource[] resources = resolver.getResources("classpath:org/aopalliance/**/*.class");
+ assertProtocolAndFilenames(resources, "jar", CLASSES_IN_AOPALLIANCE);
+ }
+
+ public void testClasspathStartWithPatternInJar() throws IOException {
+ Resource[] resources = resolver.getResources("classpath*:org/aopalliance/**/*.class");
+ assertProtocolAndFilenames(resources, "jar", CLASSES_IN_AOPALLIANCE);
+ }
+
+ private void assertProtocolAndFilename(Resource resource, String urlProtocol, String fileName) throws IOException {
+ assertProtocolAndFilenames(new Resource[] {resource}, urlProtocol, new String[] {fileName});
+ }
+
+ private void assertProtocolAndFilenames(
+ Resource[] resources, String urlProtocol, String[] fileNames1, String[] fileNames2) throws IOException {
+ List fileNames = new ArrayList(Arrays.asList(fileNames1));
+ fileNames.addAll(Arrays.asList(fileNames2));
+ assertProtocolAndFilenames(resources, urlProtocol, (String[]) fileNames.toArray(new String[fileNames.size()]));
+ }
+
+ private void assertProtocolAndFilenames(Resource[] resources, String urlProtocol, String[] fileNames)
+ throws IOException {
+
+ // Uncomment the following if you encounter problems with matching against the file system
+ // It shows file locations.
+// String[] actualNames = new String[resources.length];
+// for (int i = 0; i < resources.length; i++) {
+// actualNames[i] = resources[i].getFilename();
+// }
+// List sortedActualNames = new LinkedList(Arrays.asList(actualNames));
+// List expectedNames = new LinkedList(Arrays.asList(fileNames));
+// Collections.sort(sortedActualNames);
+// Collections.sort(expectedNames);
+//
+// System.out.println("-----------");
+// System.out.println("Expected: " + StringUtils.collectionToCommaDelimitedString(expectedNames));
+// System.out.println("Actual: " + StringUtils.collectionToCommaDelimitedString(sortedActualNames));
+// for (int i = 0; i < resources.length; i++) {
+// System.out.println(resources[i]);
+// }
+
+ assertEquals("Correct number of files found", fileNames.length, resources.length);
+ for (int i = 0; i < resources.length; i++) {
+ Resource resource = resources[i];
+ assertEquals(urlProtocol, resource.getURL().getProtocol());
+ assertFilenameIn(resource, fileNames);
+ }
+ }
+
+ private void assertFilenameIn(Resource resource, String[] fileNames) {
+ for (int i = 0; i < fileNames.length; i++) {
+ if (resource.getFilename().endsWith(fileNames[i])) {
+ return;
+ }
+ }
+ fail("resource [" + resource + "] does not have a filename that matches and of the names in 'fileNames'");
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/core/style/ToStringCreatorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/core/style/ToStringCreatorTests.java
new file mode 100644
index 00000000000..928486b3962
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/core/style/ToStringCreatorTests.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.core.style;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.springframework.core.CollectionFactory;
+import org.springframework.util.ObjectUtils;
+
+/**
+ * @author Keith Donald
+ */
+public class ToStringCreatorTests extends TestCase {
+
+ private SomeObject s1, s2, s3;
+
+ protected void setUp() throws Exception {
+ s1 = new SomeObject() {
+ public String toString() {
+ return "A";
+ }
+ };
+ s2 = new SomeObject() {
+ public String toString() {
+ return "B";
+ }
+ };
+ s3 = new SomeObject() {
+ public String toString() {
+ return "C";
+ }
+ };
+ }
+
+ public void testDefaultStyleMap() {
+ final Map map = getMap();
+ Object stringy = new Object() {
+ public String toString() {
+ return new ToStringCreator(this).append("familyFavoriteSport", map).toString();
+ }
+ };
+ assertEquals("[ToStringCreatorTests.4@" + ObjectUtils.getIdentityHexString(stringy)
+ + " familyFavoriteSport = map['Keri' -> 'Softball', 'Scot' -> 'Fishing', 'Keith' -> 'Flag Football']]",
+ stringy.toString());
+ }
+
+ private Map getMap() {
+ Map map = CollectionFactory.createLinkedMapIfPossible(3);
+ map.put("Keri", "Softball");
+ map.put("Scot", "Fishing");
+ map.put("Keith", "Flag Football");
+ return map;
+ }
+
+ public void testDefaultStyleArray() {
+ SomeObject[] array = new SomeObject[] { s1, s2, s3 };
+ String str = new ToStringCreator(array).toString();
+ assertEquals("[@" + ObjectUtils.getIdentityHexString(array)
+ + " array[A, B, C]]", str);
+ }
+
+ public void testPrimitiveArrays() {
+ int[] integers = new int[] { 0, 1, 2, 3, 4 };
+ String str = new ToStringCreator(integers).toString();
+ assertEquals("[@" + ObjectUtils.getIdentityHexString(integers) + " array[0, 1, 2, 3, 4]]", str);
+ }
+
+ public void testList() {
+ List list = new ArrayList();
+ list.add(s1);
+ list.add(s2);
+ list.add(s3);
+ String str = new ToStringCreator(this).append("myLetters", list).toString();
+ assertEquals("[ToStringCreatorTests@" + ObjectUtils.getIdentityHexString(this) + " myLetters = list[A, B, C]]",
+ str);
+ }
+
+ public void testSet() {
+ Set set = CollectionFactory.createLinkedSetIfPossible(3);
+ set.add(s1);
+ set.add(s2);
+ set.add(s3);
+ String str = new ToStringCreator(this).append("myLetters", set).toString();
+ assertEquals("[ToStringCreatorTests@" + ObjectUtils.getIdentityHexString(this) + " myLetters = set[A, B, C]]",
+ str);
+ }
+
+ public void testClass() {
+ String str = new ToStringCreator(this).append("myClass", this.getClass()).toString();
+ assertEquals("[ToStringCreatorTests@" + ObjectUtils.getIdentityHexString(this)
+ + " myClass = ToStringCreatorTests]", str);
+ }
+
+ public void testMethod() throws Exception {
+ String str = new ToStringCreator(this).append("myMethod", this.getClass().getMethod("testMethod", null))
+ .toString();
+ assertEquals("[ToStringCreatorTests@" + ObjectUtils.getIdentityHexString(this)
+ + " myMethod = testMethod@ToStringCreatorTests]", str);
+ }
+
+
+ public static class SomeObject {
+
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/core/task/MockRunnable.java b/org.springframework.testsuite/src/test/java/org/springframework/core/task/MockRunnable.java
new file mode 100644
index 00000000000..8aa2d639546
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/core/task/MockRunnable.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.core.task;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class MockRunnable implements Runnable {
+
+ private boolean executed = false;
+
+ public void run() {
+ this.executed = true;
+ }
+
+ public boolean wasExecuted() {
+ return this.executed;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/core/task/NoOpRunnable.java b/org.springframework.testsuite/src/test/java/org/springframework/core/task/NoOpRunnable.java
new file mode 100644
index 00000000000..88ce25e7450
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/core/task/NoOpRunnable.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.core.task;
+
+/**
+ * A no-op Runnable implementation.
+ *
+ * @author Rick Evans
+ */
+public class NoOpRunnable implements Runnable {
+
+ public void run() {
+ // explicit no-op
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/core/task/SimpleAsyncTaskExecutorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/core/task/SimpleAsyncTaskExecutorTests.java
new file mode 100644
index 00000000000..6dc78ff80df
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/core/task/SimpleAsyncTaskExecutorTests.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.core.task;
+
+import junit.framework.TestCase;
+
+import org.springframework.util.ClassUtils;
+import org.springframework.util.ConcurrencyThrottleSupport;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public final class SimpleAsyncTaskExecutorTests extends TestCase {
+
+ public void testCannotExecuteWhenConcurrencyIsSwitchedOff() throws Exception {
+ SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor();
+ executor.setConcurrencyLimit(ConcurrencyThrottleSupport.NO_CONCURRENCY);
+ assertFalse(executor.isThrottleActive());
+ try {
+ executor.execute(new NoOpRunnable());
+ }
+ catch (IllegalStateException expected) {
+ }
+ }
+
+ public void testThrottleIsNotActiveByDefault() throws Exception {
+ SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor();
+ assertFalse("Concurrency throttle must not default to being active (on)", executor.isThrottleActive());
+ }
+
+ public void testThreadNameGetsSetCorrectly() throws Exception {
+ final String customPrefix = "chankPop#";
+ final Object monitor = new Object();
+ SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor(customPrefix);
+ ThreadNameHarvester task = new ThreadNameHarvester(monitor);
+ executeAndWait(executor, task, monitor);
+ assertTrue(task.getThreadName().startsWith(customPrefix));
+ }
+
+ public void testThreadNameRevertsToDefaultIfSetToNull() throws Exception {
+ final Object monitor = new Object();
+ SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor(null);
+ ThreadNameHarvester task = new ThreadNameHarvester(monitor);
+ executeAndWait(executor, task, monitor);
+ assertTrue(task.getThreadName().startsWith(ClassUtils.getShortName(SimpleAsyncTaskExecutor.class) + "-"));
+ }
+
+ public void testThrowsExceptionWhenSuppliedWithNullRunnable() throws Exception {
+ try {
+ new SimpleAsyncTaskExecutor().execute(null);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ private void executeAndWait(SimpleAsyncTaskExecutor executor, Runnable task, Object monitor) {
+ synchronized (monitor) {
+ executor.execute(task);
+ try {
+ monitor.wait();
+ }
+ catch (InterruptedException ignored) {
+ }
+ }
+ }
+
+
+ private static final class NoOpRunnable implements Runnable {
+
+ public void run() {
+ // no-op
+ }
+ }
+
+
+ private static abstract class AbstractNotifyingRunnable implements Runnable {
+
+ private final Object monitor;
+
+ protected AbstractNotifyingRunnable(Object monitor) {
+ this.monitor = monitor;
+ }
+
+ public final void run() {
+ synchronized (this.monitor) {
+ try {
+ doRun();
+ }
+ finally {
+ this.monitor.notifyAll();
+ }
+ }
+ }
+
+ protected abstract void doRun();
+ }
+
+
+ private static final class ThreadNameHarvester extends AbstractNotifyingRunnable {
+
+ private String threadName;
+
+ protected ThreadNameHarvester(Object monitor) {
+ super(monitor);
+ }
+
+ public String getThreadName() {
+ return this.threadName;
+ }
+
+ protected void doRun() {
+ this.threadName = Thread.currentThread().getName();
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/core/task/StubTaskExecutor.java b/org.springframework.testsuite/src/test/java/org/springframework/core/task/StubTaskExecutor.java
new file mode 100644
index 00000000000..5270aff4d36
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/core/task/StubTaskExecutor.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.core.task;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class StubTaskExecutor implements TaskExecutor {
+
+ public void execute(Runnable task) {
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/dao/support/ChainedPersistenceExceptionTranslatorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/dao/support/ChainedPersistenceExceptionTranslatorTests.java
new file mode 100644
index 00000000000..010da75e8f5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/dao/support/ChainedPersistenceExceptionTranslatorTests.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.dao.support;
+
+import junit.framework.TestCase;
+
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+import org.springframework.dao.OptimisticLockingFailureException;
+import org.springframework.dao.support.DataAccessUtilsTests.MapPersistenceExceptionTranslator;
+
+/**
+ * @author Rod Johnson
+ * @since 2.0
+ */
+public class ChainedPersistenceExceptionTranslatorTests extends TestCase {
+
+ public void testEmpty() {
+ ChainedPersistenceExceptionTranslator pet = new ChainedPersistenceExceptionTranslator();
+ //MapPersistenceExceptionTranslator mpet = new MapPersistenceExceptionTranslator();
+ RuntimeException in = new RuntimeException("in");
+ assertSame(in, DataAccessUtils.translateIfNecessary(in, pet));
+ }
+
+ public void testExceptionTranslationWithTranslation() {
+ MapPersistenceExceptionTranslator mpet1 = new MapPersistenceExceptionTranslator();
+ RuntimeException in1 = new RuntimeException("in");
+ InvalidDataAccessApiUsageException out1 = new InvalidDataAccessApiUsageException("out");
+ InvalidDataAccessApiUsageException out2 = new InvalidDataAccessApiUsageException("out");
+ mpet1.addTranslation(in1, out1);
+
+ ChainedPersistenceExceptionTranslator chainedPet1 = new ChainedPersistenceExceptionTranslator();
+ assertSame("Should not translate yet", in1, DataAccessUtils.translateIfNecessary(in1, chainedPet1));
+ chainedPet1.addDelegate(mpet1);
+ assertSame("Should now translate", out1, DataAccessUtils.translateIfNecessary(in1, chainedPet1));
+
+ // Now add a new translator and verify it wins
+ MapPersistenceExceptionTranslator mpet2 = new MapPersistenceExceptionTranslator();
+ mpet2.addTranslation(in1, out2);
+ chainedPet1.addDelegate(mpet2);
+ assertSame("Should still translate the same due to ordering",
+ out1, DataAccessUtils.translateIfNecessary(in1, chainedPet1));
+
+ ChainedPersistenceExceptionTranslator chainedPet2 = new ChainedPersistenceExceptionTranslator();
+ chainedPet2.addDelegate(mpet2);
+ chainedPet2.addDelegate(mpet1);
+ assertSame("Should translate differently due to ordering",
+ out2, DataAccessUtils.translateIfNecessary(in1, chainedPet2));
+
+ RuntimeException in2 = new RuntimeException("in2");
+ OptimisticLockingFailureException out3 = new OptimisticLockingFailureException("out2");
+ assertNull(chainedPet2.translateExceptionIfPossible(in2));
+ MapPersistenceExceptionTranslator mpet3 = new MapPersistenceExceptionTranslator();
+ mpet3.addTranslation(in2, out3);
+ chainedPet2.addDelegate(mpet3);
+ assertSame(out3, chainedPet2.translateExceptionIfPossible(in2));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/dao/support/DataAccessUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/dao/support/DataAccessUtilsTests.java
new file mode 100644
index 00000000000..e0a4523bfb2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/dao/support/DataAccessUtilsTests.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.dao.support;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.IncorrectResultSizeDataAccessException;
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+import org.springframework.dao.TypeMismatchDataAccessException;
+
+/**
+ * @author Juergen Hoeller
+ * @since 20.10.2004
+ */
+public class DataAccessUtilsTests extends TestCase {
+
+ public void testWithEmptyCollection() {
+ Collection col = new HashSet();
+
+ assertNull(DataAccessUtils.uniqueResult(col));
+
+ try {
+ DataAccessUtils.requiredUniqueResult(col);
+ fail("Should have thrown IncorrectResultSizeDataAccessException");
+ }
+ catch (IncorrectResultSizeDataAccessException ex) {
+ // expected
+ assertEquals(1, ex.getExpectedSize());
+ assertEquals(0, ex.getActualSize());
+ }
+
+ try {
+ DataAccessUtils.objectResult(col, String.class);
+ fail("Should have thrown IncorrectResultSizeDataAccessException");
+ }
+ catch (IncorrectResultSizeDataAccessException ex) {
+ // expected
+ assertEquals(1, ex.getExpectedSize());
+ assertEquals(0, ex.getActualSize());
+ }
+
+ try {
+ DataAccessUtils.intResult(col);
+ fail("Should have thrown IncorrectResultSizeDataAccessException");
+ }
+ catch (IncorrectResultSizeDataAccessException ex) {
+ // expected
+ assertEquals(1, ex.getExpectedSize());
+ assertEquals(0, ex.getActualSize());
+ }
+
+ try {
+ DataAccessUtils.longResult(col);
+ fail("Should have thrown IncorrectResultSizeDataAccessException");
+ }
+ catch (IncorrectResultSizeDataAccessException ex) {
+ // expected
+ assertEquals(1, ex.getExpectedSize());
+ assertEquals(0, ex.getActualSize());
+ }
+ }
+
+ public void testWithTooLargeCollection() {
+ Collection col = new HashSet();
+ col.add("test1");
+ col.add("test2");
+
+ try {
+ DataAccessUtils.uniqueResult(col);
+ fail("Should have thrown IncorrectResultSizeDataAccessException");
+ }
+ catch (IncorrectResultSizeDataAccessException ex) {
+ // expected
+ assertEquals(1, ex.getExpectedSize());
+ assertEquals(2, ex.getActualSize());
+ }
+
+ try {
+ DataAccessUtils.requiredUniqueResult(col);
+ fail("Should have thrown IncorrectResultSizeDataAccessException");
+ }
+ catch (IncorrectResultSizeDataAccessException ex) {
+ // expected
+ assertEquals(1, ex.getExpectedSize());
+ assertEquals(2, ex.getActualSize());
+ }
+
+ try {
+ DataAccessUtils.objectResult(col, String.class);
+ fail("Should have thrown IncorrectResultSizeDataAccessException");
+ }
+ catch (IncorrectResultSizeDataAccessException ex) {
+ // expected
+ assertEquals(1, ex.getExpectedSize());
+ assertEquals(2, ex.getActualSize());
+ }
+
+ try {
+ DataAccessUtils.intResult(col);
+ fail("Should have thrown IncorrectResultSizeDataAccessException");
+ }
+ catch (IncorrectResultSizeDataAccessException ex) {
+ // expected
+ assertEquals(1, ex.getExpectedSize());
+ assertEquals(2, ex.getActualSize());
+ }
+
+ try {
+ DataAccessUtils.longResult(col);
+ fail("Should have thrown IncorrectResultSizeDataAccessException");
+ }
+ catch (IncorrectResultSizeDataAccessException ex) {
+ // expected
+ assertEquals(1, ex.getExpectedSize());
+ assertEquals(2, ex.getActualSize());
+ }
+ }
+
+ public void testWithInteger() {
+ Collection col = new HashSet();
+ col.add(new Integer(5));
+
+ assertEquals(new Integer(5), DataAccessUtils.uniqueResult(col));
+ assertEquals(new Integer(5), DataAccessUtils.requiredUniqueResult(col));
+ assertEquals(new Integer(5), DataAccessUtils.objectResult(col, Integer.class));
+ assertEquals("5", DataAccessUtils.objectResult(col, String.class));
+ assertEquals(5, DataAccessUtils.intResult(col));
+ assertEquals(5, DataAccessUtils.longResult(col));
+ }
+
+ public void testWithSameIntegerInstanceTwice() {
+ Integer i = new Integer(5);
+ Collection col = new ArrayList();
+ col.add(i);
+ col.add(i);
+
+ assertEquals(new Integer(5), DataAccessUtils.uniqueResult(col));
+ assertEquals(new Integer(5), DataAccessUtils.requiredUniqueResult(col));
+ assertEquals(new Integer(5), DataAccessUtils.objectResult(col, Integer.class));
+ assertEquals("5", DataAccessUtils.objectResult(col, String.class));
+ assertEquals(5, DataAccessUtils.intResult(col));
+ assertEquals(5, DataAccessUtils.longResult(col));
+ }
+
+ public void testWithEquivalentIntegerInstanceTwice() {
+ Collection col = new ArrayList();
+ col.add(new Integer(5));
+ col.add(new Integer(5));
+
+ try {
+ DataAccessUtils.uniqueResult(col);
+ fail("Should have thrown IncorrectResultSizeDataAccessException");
+ }
+ catch (IncorrectResultSizeDataAccessException ex) {
+ // expected
+ assertEquals(1, ex.getExpectedSize());
+ assertEquals(2, ex.getActualSize());
+ }
+ }
+
+ public void testWithLong() {
+ Collection col = new HashSet();
+ col.add(new Long(5));
+
+ assertEquals(new Long(5), DataAccessUtils.uniqueResult(col));
+ assertEquals(new Long(5), DataAccessUtils.requiredUniqueResult(col));
+ assertEquals(new Long(5), DataAccessUtils.objectResult(col, Long.class));
+ assertEquals("5", DataAccessUtils.objectResult(col, String.class));
+ assertEquals(5, DataAccessUtils.intResult(col));
+ assertEquals(5, DataAccessUtils.longResult(col));
+ }
+
+ public void testWithString() {
+ Collection col = new HashSet();
+ col.add("test1");
+
+ assertEquals("test1", DataAccessUtils.uniqueResult(col));
+ assertEquals("test1", DataAccessUtils.requiredUniqueResult(col));
+ assertEquals("test1", DataAccessUtils.objectResult(col, String.class));
+
+ try {
+ DataAccessUtils.intResult(col);
+ fail("Should have thrown TypeMismatchDataAccessException");
+ }
+ catch (TypeMismatchDataAccessException ex) {
+ // expected
+ }
+
+ try {
+ DataAccessUtils.longResult(col);
+ fail("Should have thrown TypeMismatchDataAccessException");
+ }
+ catch (TypeMismatchDataAccessException ex) {
+ // expected
+ }
+ }
+
+ public void testWithDate() {
+ Date date = new Date();
+ Collection col = new HashSet();
+ col.add(date);
+
+ assertEquals(date, DataAccessUtils.uniqueResult(col));
+ assertEquals(date, DataAccessUtils.requiredUniqueResult(col));
+ assertEquals(date, DataAccessUtils.objectResult(col, Date.class));
+ assertEquals(date.toString(), DataAccessUtils.objectResult(col, String.class));
+
+ try {
+ DataAccessUtils.intResult(col);
+ fail("Should have thrown TypeMismatchDataAccessException");
+ }
+ catch (TypeMismatchDataAccessException ex) {
+ // expected
+ }
+
+ try {
+ DataAccessUtils.longResult(col);
+ fail("Should have thrown TypeMismatchDataAccessException");
+ }
+ catch (TypeMismatchDataAccessException ex) {
+ // expected
+ }
+ }
+
+ public void testExceptionTranslationWithNoTranslation() {
+ MapPersistenceExceptionTranslator mpet = new MapPersistenceExceptionTranslator();
+ RuntimeException in = new RuntimeException();
+ assertSame(in, DataAccessUtils.translateIfNecessary(in, mpet));
+ }
+
+ public void testExceptionTranslationWithTranslation() {
+ MapPersistenceExceptionTranslator mpet = new MapPersistenceExceptionTranslator();
+ RuntimeException in = new RuntimeException("in");
+ InvalidDataAccessApiUsageException out = new InvalidDataAccessApiUsageException("out");
+ mpet.addTranslation(in, out);
+ assertSame(out, DataAccessUtils.translateIfNecessary(in, mpet));
+ }
+
+
+ public static class MapPersistenceExceptionTranslator implements PersistenceExceptionTranslator {
+
+ /**
+ * Map: in to out
+ */
+ private Map translations = new HashMap();
+
+ public void addTranslation(RuntimeException in, RuntimeException out) {
+ this.translations.put(in, out);
+ }
+
+ public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
+ return (DataAccessException) translations.get(ex);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jca/StubActivationSpec.java b/org.springframework.testsuite/src/test/java/org/springframework/jca/StubActivationSpec.java
new file mode 100644
index 00000000000..9f38822a4e7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jca/StubActivationSpec.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jca;
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ActivationSpec;
+import javax.resource.spi.InvalidPropertyException;
+import javax.resource.spi.ResourceAdapter;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class StubActivationSpec implements ActivationSpec {
+
+ public void validate() throws InvalidPropertyException {
+ }
+
+ public ResourceAdapter getResourceAdapter() {
+ return null;
+ }
+
+ public void setResourceAdapter(ResourceAdapter resourceAdapter) throws ResourceException {
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jca/StubResourceAdapter.java b/org.springframework.testsuite/src/test/java/org/springframework/jca/StubResourceAdapter.java
new file mode 100644
index 00000000000..65dcd8b0172
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jca/StubResourceAdapter.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jca;
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ActivationSpec;
+import javax.resource.spi.BootstrapContext;
+import javax.resource.spi.ResourceAdapter;
+import javax.resource.spi.ResourceAdapterInternalException;
+import javax.resource.spi.endpoint.MessageEndpointFactory;
+import javax.transaction.xa.XAResource;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class StubResourceAdapter implements ResourceAdapter {
+
+ public void start(BootstrapContext bootstrapContext) throws ResourceAdapterInternalException {
+ }
+
+ public void stop() {
+ }
+
+ public void endpointActivation(MessageEndpointFactory messageEndpointFactory, ActivationSpec activationSpec) throws ResourceException {
+ }
+
+ public void endpointDeactivation(MessageEndpointFactory messageEndpointFactory, ActivationSpec activationSpec) {
+ }
+
+ public XAResource[] getXAResources(ActivationSpec[] activationSpecs) throws ResourceException {
+ return null;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jca/cci/CciLocalTransactionTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jca/cci/CciLocalTransactionTests.java
new file mode 100644
index 00000000000..3d29787774d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jca/cci/CciLocalTransactionTests.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jca.cci;
+
+import javax.resource.ResourceException;
+import javax.resource.cci.Connection;
+import javax.resource.cci.ConnectionFactory;
+import javax.resource.cci.Interaction;
+import javax.resource.cci.InteractionSpec;
+import javax.resource.cci.LocalTransaction;
+import javax.resource.cci.Record;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.dao.DataRetrievalFailureException;
+import org.springframework.jca.cci.core.CciTemplate;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.support.TransactionCallback;
+import org.springframework.transaction.support.TransactionCallbackWithoutResult;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+import org.springframework.transaction.support.TransactionTemplate;
+
+/**
+ * @author Thierry TEMPLIER
+ */
+public class CciLocalTransactionTests extends TestCase {
+
+ /**
+ * Test if a transaction ( begin / commit ) is executed on the
+ * LocalTransaction when CciLocalTransactionManager is specified as
+ * transaction manager.
+ */
+ public void testLocalTransactionCommit() throws ResourceException {
+ MockControl connectionFactoryControl = MockControl.createControl(ConnectionFactory.class);
+ final ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+ MockControl localTransactionControl = MockControl.createControl(LocalTransaction.class);
+ LocalTransaction localTransaction = (LocalTransaction) localTransactionControl.getMock();
+ MockControl recordControl = MockControl.createControl(Record.class);
+ final Record record = (Record) recordControl.getMock();
+
+ MockControl interactionSpecControl = MockControl.createControl(InteractionSpec.class);
+ final InteractionSpec interactionSpec = (InteractionSpec) interactionSpecControl.getMock();
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection, 1);
+
+ connection.getLocalTransaction();
+ connectionControl.setReturnValue(localTransaction, 1);
+
+ localTransaction.begin();
+ localTransactionControl.setVoidCallable(1);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction);
+
+ interaction.execute(interactionSpec, record, record);
+ interactionControl.setReturnValue(true, 1);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.getLocalTransaction();
+ connectionControl.setReturnValue(localTransaction);
+
+ localTransaction.commit();
+ localTransactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ localTransactionControl.replay();
+ interactionControl.replay();
+
+ org.springframework.jca.cci.connection.CciLocalTransactionManager tm = new org.springframework.jca.cci.connection.CciLocalTransactionManager();
+ tm.setConnectionFactory(connectionFactory);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(connectionFactory));
+ CciTemplate ct = new CciTemplate(connectionFactory);
+ ct.execute(interactionSpec, record, record);
+ }
+ });
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ localTransactionControl.verify();
+ }
+
+ /**
+ * Test if a transaction ( begin / rollback ) is executed on the
+ * LocalTransaction when CciLocalTransactionManager is specified as
+ * transaction manager and a non-checked exception is thrown.
+ */
+ public void testLocalTransactionRollback() throws ResourceException {
+ MockControl connectionFactoryControl = MockControl.createControl(ConnectionFactory.class);
+ final ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+ MockControl localTransactionControl = MockControl.createControl(LocalTransaction.class);
+ LocalTransaction localTransaction = (LocalTransaction) localTransactionControl.getMock();
+ MockControl recordControl = MockControl.createControl(Record.class);
+ final Record record = (Record) recordControl.getMock();
+
+ MockControl interactionSpecControl = MockControl.createControl(InteractionSpec.class);
+ final InteractionSpec interactionSpec = (InteractionSpec) interactionSpecControl.getMock();
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection);
+
+ connection.getLocalTransaction();
+ connectionControl.setReturnValue(localTransaction);
+
+ localTransaction.begin();
+ localTransactionControl.setVoidCallable(1);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction);
+
+ interaction.execute(interactionSpec, record, record);
+ interactionControl.setReturnValue(true, 1);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.getLocalTransaction();
+ connectionControl.setReturnValue(localTransaction);
+
+ localTransaction.rollback();
+ localTransactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ localTransactionControl.replay();
+ interactionControl.replay();
+
+ org.springframework.jca.cci.connection.CciLocalTransactionManager tm = new org.springframework.jca.cci.connection.CciLocalTransactionManager();
+ tm.setConnectionFactory(connectionFactory);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+
+ try {
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(connectionFactory));
+ CciTemplate ct = new CciTemplate(connectionFactory);
+ ct.execute(interactionSpec, record, record);
+ throw new DataRetrievalFailureException("error");
+ }
+ });
+ }
+ catch (Exception ex) {
+ }
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ localTransactionControl.verify();
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jca/cci/CciTemplateTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jca/cci/CciTemplateTests.java
new file mode 100644
index 00000000000..2c421091589
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jca/cci/CciTemplateTests.java
@@ -0,0 +1,987 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jca.cci;
+
+import java.sql.SQLException;
+
+import javax.resource.NotSupportedException;
+import javax.resource.ResourceException;
+import javax.resource.cci.Connection;
+import javax.resource.cci.ConnectionFactory;
+import javax.resource.cci.ConnectionSpec;
+import javax.resource.cci.IndexedRecord;
+import javax.resource.cci.Interaction;
+import javax.resource.cci.InteractionSpec;
+import javax.resource.cci.MappedRecord;
+import javax.resource.cci.Record;
+import javax.resource.cci.RecordFactory;
+import javax.resource.cci.ResultSet;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.jca.cci.connection.ConnectionSpecConnectionFactoryAdapter;
+import org.springframework.jca.cci.connection.NotSupportedRecordFactory;
+import org.springframework.jca.cci.core.CciTemplate;
+import org.springframework.jca.cci.core.ConnectionCallback;
+import org.springframework.jca.cci.core.InteractionCallback;
+import org.springframework.jca.cci.core.RecordCreator;
+import org.springframework.jca.cci.core.RecordExtractor;
+
+/**
+ * @author Thierry Templier
+ * @author Juergen Hoeller
+ */
+public class CciTemplateTests extends TestCase {
+
+ public void testCreateIndexedRecord() throws ResourceException {
+ MockControl connectionFactoryControl = MockControl.createStrictControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl recordFactoryControl = MockControl.createStrictControl(RecordFactory.class);
+ RecordFactory recordFactory = (RecordFactory) recordFactoryControl.getMock();
+ MockControl indexedRecordControl = MockControl.createStrictControl(IndexedRecord.class);
+ IndexedRecord indexedRecord = (IndexedRecord) indexedRecordControl.getMock();
+
+ connectionFactory.getRecordFactory();
+ connectionFactoryControl.setReturnValue(recordFactory, 1);
+
+ recordFactory.createIndexedRecord("name");
+ recordFactoryControl.setReturnValue(indexedRecord, 1);
+
+ connectionFactoryControl.replay();
+ recordFactoryControl.replay();
+
+ CciTemplate ct = new CciTemplate(connectionFactory);
+ ct.createIndexedRecord("name");
+
+ connectionFactoryControl.verify();
+ recordFactoryControl.verify();
+ }
+
+ public void testCreateMappedRecord() throws ResourceException {
+ MockControl connectionFactoryControl = MockControl.createStrictControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl recordFactoryControl = MockControl.createStrictControl(RecordFactory.class);
+ RecordFactory recordFactory = (RecordFactory) recordFactoryControl.getMock();
+ MockControl mappedRecordControl = MockControl.createStrictControl(MappedRecord.class);
+ MappedRecord mappedRecord = (MappedRecord) mappedRecordControl.getMock();
+
+ connectionFactory.getRecordFactory();
+ connectionFactoryControl.setReturnValue(recordFactory, 1);
+
+ recordFactory.createMappedRecord("name");
+ recordFactoryControl.setReturnValue(mappedRecord, 1);
+
+ connectionFactoryControl.replay();
+ recordFactoryControl.replay();
+
+ CciTemplate ct = new CciTemplate(connectionFactory);
+ ct.createMappedRecord("name");
+
+ connectionFactoryControl.verify();
+ recordFactoryControl.verify();
+ }
+
+ public void testTemplateExecuteInputOutput() throws ResourceException {
+ MockControl connectionFactoryControl = MockControl.createStrictControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createStrictControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createStrictControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+
+ MockControl inputRecordControl = MockControl.createStrictControl(Record.class);
+ Record inputRecord = (Record) inputRecordControl.getMock();
+ MockControl outputRecordControl = MockControl.createStrictControl(Record.class);
+ Record outputRecord = (Record) outputRecordControl.getMock();
+
+ MockControl interactionSpecControl = MockControl.createStrictControl(InteractionSpec.class);
+ InteractionSpec interactionSpec = (InteractionSpec) interactionSpecControl.getMock();
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection, 1);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction, 1);
+
+ interaction.execute(interactionSpec, inputRecord, outputRecord);
+ interactionControl.setReturnValue(true, 1);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ interactionControl.replay();
+
+ CciTemplate ct = new CciTemplate(connectionFactory);
+ ct.execute(interactionSpec, inputRecord, outputRecord);
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ }
+
+ public void testTemplateExecuteWithCreatorAndRecordFactoryNotSupported() throws ResourceException {
+ MockControl connectionFactoryControl = MockControl.createStrictControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createStrictControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createStrictControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+
+ MockControl inputRecordControl = MockControl.createStrictControl(Record.class);
+ Record inputRecord = (Record) inputRecordControl.getMock();
+ MockControl outputRecordControl = MockControl.createStrictControl(Record.class);
+ final Record outputRecord = (Record) outputRecordControl.getMock();
+
+ MockControl interactionSpecControl = MockControl.createStrictControl(InteractionSpec.class);
+ InteractionSpec interactionSpec = (InteractionSpec) interactionSpecControl.getMock();
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection);
+
+ connectionFactory.getRecordFactory();
+ connectionFactoryControl.setThrowable(new NotSupportedException("not supported"), 1);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction);
+
+ interaction.execute(interactionSpec, inputRecord, outputRecord);
+ interactionControl.setReturnValue(true, 1);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ interactionControl.replay();
+
+ CciTemplate ct = new CciTemplate(connectionFactory);
+ ct.setOutputRecordCreator(new RecordCreator() {
+ public Record createRecord(RecordFactory recordFactory) {
+ assertTrue(recordFactory instanceof NotSupportedRecordFactory);
+ return outputRecord;
+ }
+ });
+ ct.execute(interactionSpec, inputRecord);
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ }
+
+ public void testTemplateExecuteInputTrueWithCreator() throws ResourceException {
+ MockControl connectionFactoryControl = MockControl.createStrictControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl recordFactoryControl = MockControl.createStrictControl(RecordFactory.class);
+ RecordFactory recordFactory = (RecordFactory) recordFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createStrictControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createStrictControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+ MockControl creatorControl = MockControl.createStrictControl(RecordCreator.class);
+ RecordCreator creator = (RecordCreator) creatorControl.getMock();
+
+ MockControl inputRecordControl = MockControl.createStrictControl(Record.class);
+ Record inputRecord = (Record) inputRecordControl.getMock();
+ MockControl outputRecordControl = MockControl.createStrictControl(Record.class);
+ Record outputRecord = (Record) outputRecordControl.getMock();
+
+ MockControl interactionSpecControl = MockControl.createStrictControl(InteractionSpec.class);
+ InteractionSpec interactionSpec = (InteractionSpec) interactionSpecControl.getMock();
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection);
+
+ connectionFactory.getRecordFactory();
+ connectionFactoryControl.setReturnValue(recordFactory, 1);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction);
+
+ creator.createRecord(recordFactory);
+ creatorControl.setReturnValue(outputRecord);
+
+ interaction.execute(interactionSpec, inputRecord, outputRecord);
+ interactionControl.setReturnValue(true, 1);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ interactionControl.replay();
+ creatorControl.replay();
+
+ CciTemplate ct = new CciTemplate(connectionFactory);
+ ct.setOutputRecordCreator(creator);
+ ct.execute(interactionSpec, inputRecord);
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ creatorControl.verify();
+ }
+
+ public void testTemplateExecuteInputFalse() throws ResourceException {
+ MockControl connectionFactoryControl = MockControl.createStrictControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createStrictControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createStrictControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+
+ MockControl inputRecordControl = MockControl.createStrictControl(Record.class);
+ Record inputRecord = (Record) inputRecordControl.getMock();
+ MockControl outputRecordControl = MockControl.createStrictControl(Record.class);
+ Record outputRecord = (Record) outputRecordControl.getMock();
+
+ MockControl interactionSpecControl = MockControl.createStrictControl(InteractionSpec.class);
+ InteractionSpec interactionSpec = (InteractionSpec) interactionSpecControl.getMock();
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction);
+
+ interaction.execute(interactionSpec, inputRecord);
+ interactionControl.setReturnValue(outputRecord, 1);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ interactionControl.replay();
+
+ CciTemplate ct = new CciTemplate(connectionFactory);
+ ct.execute(interactionSpec, inputRecord);
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ }
+
+ public void testTemplateExecuteInputExtractorTrueWithCreator() throws ResourceException, SQLException {
+ MockControl connectionFactoryControl = MockControl.createStrictControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl recordFactoryControl = MockControl.createStrictControl(RecordFactory.class);
+ RecordFactory recordFactory = (RecordFactory) recordFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createStrictControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createStrictControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+ MockControl extractorControl = MockControl.createStrictControl(RecordExtractor.class);
+ RecordExtractor extractor = (RecordExtractor) extractorControl.getMock();
+ MockControl creatorControl = MockControl.createStrictControl(RecordCreator.class);
+ RecordCreator creator = (RecordCreator) creatorControl.getMock();
+
+ MockControl inputRecordControl = MockControl.createStrictControl(Record.class);
+ Record inputRecord = (Record) inputRecordControl.getMock();
+ MockControl outputRecordControl = MockControl.createStrictControl(Record.class);
+ Record outputRecord = (Record) outputRecordControl.getMock();
+
+ MockControl interactionSpecControl = MockControl.createStrictControl(InteractionSpec.class);
+ InteractionSpec interactionSpec = (InteractionSpec) interactionSpecControl.getMock();
+
+ Object obj = new Object();
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction);
+
+ connectionFactory.getRecordFactory();
+ connectionFactoryControl.setReturnValue(recordFactory, 1);
+
+ creator.createRecord(recordFactory);
+ creatorControl.setReturnValue(outputRecord);
+
+ interaction.execute(interactionSpec, inputRecord, outputRecord);
+ interactionControl.setReturnValue(true, 1);
+
+ extractor.extractData(outputRecord);
+ extractorControl.setReturnValue(obj);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ interactionControl.replay();
+ extractorControl.replay();
+ creatorControl.replay();
+
+ CciTemplate ct = new CciTemplate(connectionFactory);
+ ct.setOutputRecordCreator(creator);
+ ct.execute(interactionSpec, inputRecord, extractor);
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ extractorControl.verify();
+ creatorControl.verify();
+ }
+
+ public void testTemplateExecuteInputExtractorFalse() throws ResourceException, SQLException {
+ MockControl connectionFactoryControl = MockControl.createStrictControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createStrictControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createStrictControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+ MockControl extractorControl = MockControl.createStrictControl(RecordExtractor.class);
+ RecordExtractor extractor = (RecordExtractor) extractorControl.getMock();
+
+ MockControl inputRecordControl = MockControl.createStrictControl(Record.class);
+ Record inputRecord = (Record) inputRecordControl.getMock();
+ MockControl outputRecordControl = MockControl.createStrictControl(Record.class);
+ Record outputRecord = (Record) outputRecordControl.getMock();
+
+ MockControl interactionSpecControl = MockControl.createStrictControl(InteractionSpec.class);
+ InteractionSpec interactionSpec = (InteractionSpec) interactionSpecControl.getMock();
+
+ Object obj = new Object();
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction);
+
+ interaction.execute(interactionSpec, inputRecord);
+ interactionControl.setReturnValue(outputRecord, 1);
+
+ extractor.extractData(outputRecord);
+ extractorControl.setReturnValue(obj);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ interactionControl.replay();
+ extractorControl.replay();
+
+ CciTemplate ct = new CciTemplate(connectionFactory);
+ ct.execute(interactionSpec, inputRecord, extractor);
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ extractorControl.verify();
+ }
+
+ public void testTemplateExecuteInputGeneratorTrueWithCreator() throws ResourceException {
+ MockControl connectionFactoryControl = MockControl.createStrictControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl recordFactoryControl = MockControl.createStrictControl(RecordFactory.class);
+ RecordFactory recordFactory = (RecordFactory) recordFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createStrictControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createStrictControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+ MockControl generatorControl = MockControl.createStrictControl(RecordCreator.class);
+ RecordCreator generator = (RecordCreator) generatorControl.getMock();
+ MockControl creatorControl = MockControl.createStrictControl(RecordCreator.class);
+ RecordCreator creator = (RecordCreator) creatorControl.getMock();
+
+ MockControl inputRecordControl = MockControl.createStrictControl(Record.class);
+ Record inputRecord = (Record) inputRecordControl.getMock();
+ MockControl outputRecordControl = MockControl.createStrictControl(Record.class);
+ Record outputRecord = (Record) outputRecordControl.getMock();
+
+ MockControl interactionSpecControl = MockControl.createStrictControl(InteractionSpec.class);
+ InteractionSpec interactionSpec = (InteractionSpec) interactionSpecControl.getMock();
+
+ connectionFactory.getRecordFactory();
+ connectionFactoryControl.setReturnValue(recordFactory, 1);
+
+ generator.createRecord(recordFactory);
+ generatorControl.setReturnValue(inputRecord);
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction);
+
+ creator.createRecord(recordFactory);
+ creatorControl.setReturnValue(outputRecord);
+
+ connectionFactory.getRecordFactory();
+ connectionFactoryControl.setReturnValue(recordFactory, 1);
+
+ interaction.execute(interactionSpec, inputRecord, outputRecord);
+ interactionControl.setReturnValue(true, 1);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ interactionControl.replay();
+ generatorControl.replay();
+ creatorControl.replay();
+
+ CciTemplate ct = new CciTemplate(connectionFactory);
+ ct.setOutputRecordCreator(creator);
+ ct.execute(interactionSpec, generator);
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ generatorControl.verify();
+ creatorControl.verify();
+ }
+
+ public void testTemplateExecuteInputGeneratorFalse() throws ResourceException {
+ MockControl connectionFactoryControl = MockControl.createStrictControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl recordFactoryControl = MockControl.createStrictControl(RecordFactory.class);
+ RecordFactory recordFactory = (RecordFactory) recordFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createStrictControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createStrictControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+ MockControl generatorControl = MockControl.createStrictControl(RecordCreator.class);
+ RecordCreator generator = (RecordCreator) generatorControl.getMock();
+
+ MockControl inputRecordControl = MockControl.createStrictControl(Record.class);
+ Record inputRecord = (Record) inputRecordControl.getMock();
+ MockControl outputRecordControl = MockControl.createStrictControl(Record.class);
+ Record outputRecord = (Record) outputRecordControl.getMock();
+
+ MockControl interactionSpecControl = MockControl.createStrictControl(InteractionSpec.class);
+ InteractionSpec interactionSpec = (InteractionSpec) interactionSpecControl.getMock();
+
+ connectionFactory.getRecordFactory();
+ connectionFactoryControl.setReturnValue(recordFactory, 1);
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction);
+
+ generator.createRecord(recordFactory);
+ generatorControl.setReturnValue(inputRecord);
+
+ interaction.execute(interactionSpec, inputRecord);
+ interactionControl.setReturnValue(outputRecord, 1);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ interactionControl.replay();
+ generatorControl.replay();
+
+ CciTemplate ct = new CciTemplate(connectionFactory);
+ ct.execute(interactionSpec, generator);
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ generatorControl.verify();
+ }
+
+ public void testTemplateExecuteInputGeneratorExtractorTrueWithCreator() throws ResourceException, SQLException {
+ MockControl connectionFactoryControl = MockControl.createStrictControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl recordFactoryControl = MockControl.createStrictControl(RecordFactory.class);
+ RecordFactory recordFactory = (RecordFactory) recordFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createStrictControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createStrictControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+ MockControl generatorControl = MockControl.createStrictControl(RecordCreator.class);
+ RecordCreator generator = (RecordCreator) generatorControl.getMock();
+ MockControl extractorControl = MockControl.createStrictControl(RecordExtractor.class);
+ RecordExtractor extractor = (RecordExtractor) extractorControl.getMock();
+ MockControl creatorControl = MockControl.createStrictControl(RecordCreator.class);
+ RecordCreator creator = (RecordCreator) creatorControl.getMock();
+
+ MockControl inputRecordControl = MockControl.createStrictControl(Record.class);
+ Record inputRecord = (Record) inputRecordControl.getMock();
+ MockControl outputRecordControl = MockControl.createStrictControl(Record.class);
+ Record outputRecord = (Record) outputRecordControl.getMock();
+
+ MockControl interactionSpecControl = MockControl.createStrictControl(InteractionSpec.class);
+ InteractionSpec interactionSpec = (InteractionSpec) interactionSpecControl.getMock();
+
+ Object obj = new Object();
+
+ connectionFactory.getRecordFactory();
+ connectionFactoryControl.setReturnValue(recordFactory, 1);
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction);
+
+ creator.createRecord(recordFactory);
+ creatorControl.setReturnValue(outputRecord);
+
+ connectionFactory.getRecordFactory();
+ connectionFactoryControl.setReturnValue(recordFactory, 1);
+
+ generator.createRecord(recordFactory);
+ generatorControl.setReturnValue(inputRecord);
+
+ interaction.execute(interactionSpec, inputRecord, outputRecord);
+ interactionControl.setReturnValue(true, 1);
+
+ extractor.extractData(outputRecord);
+ extractorControl.setReturnValue(obj);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ interactionControl.replay();
+ generatorControl.replay();
+ extractorControl.replay();
+ creatorControl.replay();
+
+ CciTemplate ct = new CciTemplate(connectionFactory);
+ ct.setOutputRecordCreator(creator);
+ assertEquals(obj, ct.execute(interactionSpec, generator, extractor));
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ generatorControl.verify();
+ extractorControl.verify();
+ creatorControl.verify();
+ }
+
+ public void testTemplateExecuteInputGeneratorExtractorFalse() throws ResourceException, SQLException {
+ MockControl connectionFactoryControl = MockControl.createStrictControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl recordFactoryControl = MockControl.createStrictControl(RecordFactory.class);
+ RecordFactory recordFactory = (RecordFactory) recordFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createStrictControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createStrictControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+ MockControl generatorControl = MockControl.createStrictControl(RecordCreator.class);
+ RecordCreator generator = (RecordCreator) generatorControl.getMock();
+ MockControl extractorControl = MockControl.createStrictControl(RecordExtractor.class);
+ RecordExtractor extractor = (RecordExtractor) extractorControl.getMock();
+
+ MockControl inputRecordControl = MockControl.createStrictControl(Record.class);
+ Record inputRecord = (Record) inputRecordControl.getMock();
+ MockControl outputRecordControl = MockControl.createStrictControl(Record.class);
+ Record outputRecord = (Record) outputRecordControl.getMock();
+
+ MockControl interactionSpecControl = MockControl.createStrictControl(InteractionSpec.class);
+ InteractionSpec interactionSpec = (InteractionSpec) interactionSpecControl.getMock();
+
+ Object obj = new Object();
+
+ connectionFactory.getRecordFactory();
+ connectionFactoryControl.setReturnValue(recordFactory, 1);
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction);
+
+ generator.createRecord(recordFactory);
+ generatorControl.setReturnValue(inputRecord);
+
+ interaction.execute(interactionSpec, inputRecord);
+ interactionControl.setReturnValue(outputRecord, 1);
+
+ extractor.extractData(outputRecord);
+ extractorControl.setReturnValue(obj);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ interactionControl.replay();
+ generatorControl.replay();
+ extractorControl.replay();
+
+ CciTemplate ct = new CciTemplate(connectionFactory);
+ ct.execute(interactionSpec, generator, extractor);
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ generatorControl.verify();
+ extractorControl.verify();
+ }
+
+ public void testTemplateExecuteInputOutputConnectionSpec() throws ResourceException {
+ MockControl connectionFactoryControl = MockControl.createStrictControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createStrictControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createStrictControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+
+ MockControl inputRecordControl = MockControl.createStrictControl(Record.class);
+ Record inputRecord = (Record) inputRecordControl.getMock();
+ MockControl outputRecordControl = MockControl.createStrictControl(Record.class);
+ Record outputRecord = (Record) outputRecordControl.getMock();
+
+ MockControl connectionSpecControl = MockControl.createStrictControl(ConnectionSpec.class);
+ ConnectionSpec connectionSpec = (ConnectionSpec) connectionSpecControl.getMock();
+ MockControl interactionSpecControl = MockControl.createStrictControl(InteractionSpec.class);
+ InteractionSpec interactionSpec = (InteractionSpec) interactionSpecControl.getMock();
+
+ connectionFactory.getConnection(connectionSpec);
+ connectionFactoryControl.setReturnValue(connection, 1);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction, 1);
+
+ interaction.execute(interactionSpec, inputRecord, outputRecord);
+ interactionControl.setReturnValue(true, 1);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ interactionControl.replay();
+
+ ConnectionSpecConnectionFactoryAdapter adapter = new ConnectionSpecConnectionFactoryAdapter();
+ adapter.setTargetConnectionFactory(connectionFactory);
+ adapter.setConnectionSpec(connectionSpec);
+ CciTemplate ct = new CciTemplate(adapter);
+ ct.execute(interactionSpec, inputRecord, outputRecord);
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ }
+
+ public void testTemplateExecuteInputOutputResultsSetFalse() throws ResourceException, SQLException {
+ MockControl connectionFactoryControl = MockControl.createStrictControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl recordFactoryControl = MockControl.createStrictControl(RecordFactory.class);
+ RecordFactory recordFactory = (RecordFactory) recordFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createStrictControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createStrictControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+ MockControl recordControl = MockControl.createStrictControl(Record.class);
+ Record record = (Record) recordControl.getMock();
+ MockControl resultsetControl = MockControl.createStrictControl(ResultSet.class);
+ ResultSet resultset = (ResultSet) resultsetControl.getMock();
+ MockControl generatorControl = MockControl.createStrictControl(RecordCreator.class);
+ RecordCreator generator = (RecordCreator) generatorControl.getMock();
+ MockControl extractorControl = MockControl.createStrictControl(RecordExtractor.class);
+ RecordExtractor extractor = (RecordExtractor) extractorControl.getMock();
+
+ MockControl interactionSpecControl = MockControl.createStrictControl(InteractionSpec.class);
+ InteractionSpec interactionSpec = (InteractionSpec) interactionSpecControl.getMock();
+
+ Object obj = new Object();
+
+ connectionFactory.getRecordFactory();
+ connectionFactoryControl.setReturnValue(recordFactory, 1);
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction);
+
+ generator.createRecord(recordFactory);
+ generatorControl.setReturnValue(record);
+
+ interaction.execute(interactionSpec, record);
+ interactionControl.setReturnValue(resultset, 1);
+
+ extractor.extractData(resultset);
+ extractorControl.setReturnValue(obj);
+
+ resultset.close();
+ resultsetControl.setVoidCallable(1);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ interactionControl.replay();
+ generatorControl.replay();
+ extractorControl.replay();
+ resultsetControl.replay();
+
+ CciTemplate ct = new CciTemplate(connectionFactory);
+ ct.execute(interactionSpec, generator, extractor);
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ generatorControl.verify();
+ extractorControl.verify();
+ resultsetControl.verify();
+ }
+
+ public void testTemplateExecuteConnectionCallback() throws ResourceException, SQLException {
+ MockControl connectionFactoryControl = MockControl.createStrictControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createStrictControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl connectionCallbackControl = MockControl.createStrictControl(ConnectionCallback.class);
+ ConnectionCallback connectionCallback = (ConnectionCallback) connectionCallbackControl.getMock();
+
+ Object obj = new Object();
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection);
+
+ connectionCallback.doInConnection(connection, connectionFactory);
+ connectionCallbackControl.setReturnValue(obj);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ connectionCallbackControl.replay();
+
+ CciTemplate ct = new CciTemplate(connectionFactory);
+ ct.execute(connectionCallback);
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ connectionCallbackControl.verify();
+ }
+
+ public void testTemplateExecuteInteractionCallback() throws ResourceException, SQLException {
+ MockControl connectionFactoryControl = MockControl.createStrictControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createStrictControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createStrictControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+ MockControl interactionCallbackControl = MockControl.createStrictControl(InteractionCallback.class);
+ InteractionCallback interactionCallback = (InteractionCallback) interactionCallbackControl.getMock();
+
+ Object obj = new Object();
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction);
+
+ interactionCallback.doInInteraction(interaction, connectionFactory);
+ interactionCallbackControl.setReturnValue(obj);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ interactionControl.replay();
+ interactionCallbackControl.replay();
+
+ CciTemplate ct = new CciTemplate(connectionFactory);
+ ct.execute(interactionCallback);
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ interactionCallbackControl.verify();
+ }
+
+ public void testTemplateExecuteInputTrueTrueWithCreator() throws ResourceException {
+ MockControl connectionFactoryControl = MockControl.createStrictControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createStrictControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createStrictControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+ MockControl creatorControl = MockControl.createStrictControl(RecordCreator.class);
+ RecordCreator creator = (RecordCreator) creatorControl.getMock();
+
+ MockControl inputOutputRecordControl = MockControl.createStrictControl(Record.class);
+ Record inputOutputRecord = (Record) inputOutputRecordControl.getMock();
+
+ MockControl interactionSpecControl = MockControl.createStrictControl(InteractionSpec.class);
+ InteractionSpec interactionSpec = (InteractionSpec) interactionSpecControl.getMock();
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction);
+
+ interaction.execute(interactionSpec, inputOutputRecord, inputOutputRecord);
+ interactionControl.setReturnValue(true, 1);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ interactionControl.replay();
+ creatorControl.replay();
+
+ CciTemplate ct = new CciTemplate(connectionFactory);
+ ct.setOutputRecordCreator(creator);
+ ct.execute(interactionSpec, inputOutputRecord, inputOutputRecord);
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ creatorControl.verify();
+ }
+
+ public void testTemplateExecuteInputTrueTrue() throws ResourceException {
+ MockControl connectionFactoryControl = MockControl.createStrictControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createStrictControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createStrictControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+
+ MockControl inputOutputRecordControl = MockControl.createStrictControl(Record.class);
+ Record inputOutputRecord = (Record) inputOutputRecordControl.getMock();
+
+ MockControl interactionSpecControl = MockControl.createStrictControl(InteractionSpec.class);
+ InteractionSpec interactionSpec = (InteractionSpec) interactionSpecControl.getMock();
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction);
+
+ interaction.execute(interactionSpec, inputOutputRecord, inputOutputRecord);
+ interactionControl.setReturnValue(true, 1);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ interactionControl.replay();
+
+ CciTemplate ct = new CciTemplate(connectionFactory);
+ ct.execute(interactionSpec, inputOutputRecord, inputOutputRecord);
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ }
+
+ public void testTemplateExecuteInputFalseTrue() throws ResourceException {
+ MockControl connectionFactoryControl = MockControl.createStrictControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createStrictControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createStrictControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+
+ MockControl inputOutputRecordControl = MockControl.createStrictControl(Record.class);
+ Record inputOutputRecord = (Record) inputOutputRecordControl.getMock();
+
+ MockControl interactionSpecControl = MockControl.createStrictControl(InteractionSpec.class);
+ InteractionSpec interactionSpec = (InteractionSpec) interactionSpecControl.getMock();
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction);
+
+ interaction.execute(interactionSpec, inputOutputRecord);
+ interactionControl.setReturnValue(null, 1);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ interactionControl.replay();
+
+ CciTemplate ct = new CciTemplate(connectionFactory);
+ Record tmpOutputRecord = (Record) ct.execute(interactionSpec, inputOutputRecord);
+ assertNull(tmpOutputRecord);
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jca/cci/EisOperationTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jca/cci/EisOperationTests.java
new file mode 100644
index 00000000000..57386ce786c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jca/cci/EisOperationTests.java
@@ -0,0 +1,338 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jca.cci;
+
+import javax.resource.ResourceException;
+import javax.resource.cci.Connection;
+import javax.resource.cci.ConnectionFactory;
+import javax.resource.cci.Interaction;
+import javax.resource.cci.InteractionSpec;
+import javax.resource.cci.Record;
+import javax.resource.cci.RecordFactory;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.jca.cci.core.RecordCreator;
+import org.springframework.jca.cci.object.MappingRecordOperation;
+import org.springframework.jca.cci.object.SimpleRecordOperation;
+
+/**
+ * @author Thierry TEMPLIER
+ */
+public class EisOperationTests extends TestCase {
+
+ public void testSimpleRecordOperation() throws ResourceException {
+ MockControl connectionFactoryControl = MockControl.createControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+
+ MockControl inputRecordControl = MockControl.createControl(Record.class);
+ Record inputRecord = (Record) inputRecordControl.getMock();
+ MockControl outputRecordControl = MockControl.createControl(Record.class);
+ Record outputRecord = (Record) outputRecordControl.getMock();
+
+ MockControl interactionSpecControl = MockControl.createControl(InteractionSpec.class);
+ InteractionSpec interactionSpec = (InteractionSpec) interactionSpecControl.getMock();
+
+ SimpleRecordOperation query = new SimpleRecordOperation(connectionFactory, interactionSpec);
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction);
+
+ interaction.execute(interactionSpec, inputRecord);
+ interactionControl.setReturnValue(outputRecord, 1);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ interactionControl.replay();
+
+ query.execute(inputRecord);
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ }
+
+ public void testSimpleRecordOperationWithExplicitOutputRecord() throws ResourceException {
+ MockControl connectionFactoryControl = MockControl.createControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+
+ MockControl inputRecordControl = MockControl.createControl(Record.class);
+ Record inputRecord = (Record) inputRecordControl.getMock();
+ MockControl outputRecordControl = MockControl.createControl(Record.class);
+ Record outputRecord = (Record) outputRecordControl.getMock();
+
+ MockControl interactionSpecControl = MockControl.createControl(InteractionSpec.class);
+ InteractionSpec interactionSpec = (InteractionSpec) interactionSpecControl.getMock();
+
+ SimpleRecordOperation operation = new SimpleRecordOperation(connectionFactory, interactionSpec);
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection, 1);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction, 1);
+
+ interaction.execute(interactionSpec, inputRecord, outputRecord);
+ interactionControl.setReturnValue(true, 1);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ interactionControl.replay();
+
+ operation.execute(inputRecord, outputRecord);
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ }
+
+ public void testSimpleRecordOperationWithInputOutputRecord() throws ResourceException {
+ MockControl connectionFactoryControl = MockControl.createControl(ConnectionFactory.class);
+ final ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+
+ MockControl inputOutputRecordControl = MockControl.createControl(Record.class);
+ Record inputOutputRecord = (Record) inputOutputRecordControl.getMock();
+
+ MockControl interactionSpecControl = MockControl.createControl(InteractionSpec.class);
+ InteractionSpec interactionSpec = (InteractionSpec) interactionSpecControl.getMock();
+
+ SimpleRecordOperation query = new SimpleRecordOperation(connectionFactory, interactionSpec);
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction);
+
+ interaction.execute(interactionSpec, inputOutputRecord, inputOutputRecord);
+ interactionControl.setReturnValue(true, 1);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ interactionControl.replay();
+
+ query.execute(inputOutputRecord, inputOutputRecord);
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ }
+
+ public void testMappingRecordOperation() throws ResourceException {
+ MockControl connectionFactoryControl = MockControl.createControl(ConnectionFactory.class);
+ final ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl recordFactoryControl = MockControl.createStrictControl(RecordFactory.class);
+ RecordFactory recordFactory = (RecordFactory) recordFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+
+ MockControl inputRecordControl = MockControl.createControl(Record.class);
+ Record inputRecord = (Record) inputRecordControl.getMock();
+ MockControl outputRecordControl = MockControl.createControl(Record.class);
+ Record outputRecord = (Record) outputRecordControl.getMock();
+
+ MockControl interactionSpecControl = MockControl.createControl(InteractionSpec.class);
+ InteractionSpec interactionSpec = (InteractionSpec) interactionSpecControl.getMock();
+
+ MockControl callDetectorControl = MockControl.createControl(QueryCallDetector.class);
+ QueryCallDetector callDetector = (QueryCallDetector) callDetectorControl.getMock();
+
+ MappingRecordOperationImpl query = new MappingRecordOperationImpl(connectionFactory, interactionSpec);
+ query.setCallDetector(callDetector);
+
+ Object inObj = new Object();
+ Object outObj = new Object();
+
+ connectionFactory.getRecordFactory();
+ connectionFactoryControl.setReturnValue(recordFactory, 1);
+
+ callDetector.callCreateInputRecord(recordFactory, inObj);
+ callDetectorControl.setReturnValue(inputRecord, 1);
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection, 1);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction, 1);
+
+ interaction.execute(interactionSpec, inputRecord);
+ interactionControl.setReturnValue(outputRecord, 1);
+
+ callDetector.callExtractOutputData(outputRecord);
+ callDetectorControl.setReturnValue(outObj, 1);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ interactionControl.replay();
+ callDetectorControl.replay();
+
+ assertSame(outObj, query.execute(inObj));
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ callDetectorControl.verify();
+ }
+
+ public void testMappingRecordOperationWithOutputRecordCreator() throws ResourceException {
+ MockControl connectionFactoryControl = MockControl.createControl(ConnectionFactory.class);
+ final ConnectionFactory connectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ MockControl recordFactoryControl = MockControl.createStrictControl(RecordFactory.class);
+ RecordFactory recordFactory = (RecordFactory) recordFactoryControl.getMock();
+ MockControl connectionControl = MockControl.createControl(Connection.class);
+ Connection connection = (Connection) connectionControl.getMock();
+ MockControl interactionControl = MockControl.createControl(Interaction.class);
+ Interaction interaction = (Interaction) interactionControl.getMock();
+
+ MockControl inputRecordControl = MockControl.createControl(Record.class);
+ Record inputRecord = (Record) inputRecordControl.getMock();
+ MockControl outputRecordControl = MockControl.createControl(Record.class);
+ Record outputRecord = (Record) outputRecordControl.getMock();
+ MockControl outputCreatorControl = MockControl.createControl(RecordCreator.class);
+ RecordCreator outputCreator = (RecordCreator) outputCreatorControl.getMock();
+
+ MockControl interactionSpecControl = MockControl.createControl(InteractionSpec.class);
+ InteractionSpec interactionSpec = (InteractionSpec) interactionSpecControl.getMock();
+
+ MockControl callDetectorControl = MockControl.createControl(QueryCallDetector.class);
+ QueryCallDetector callDetector = (QueryCallDetector) callDetectorControl.getMock();
+
+ MappingRecordOperationImpl query = new MappingRecordOperationImpl(connectionFactory, interactionSpec);
+ query.setOutputRecordCreator(outputCreator);
+ query.setCallDetector(callDetector);
+
+ Object inObj = new Object();
+ Object outObj = new Object();
+
+ connectionFactory.getRecordFactory();
+ connectionFactoryControl.setReturnValue(recordFactory, 1);
+
+ callDetector.callCreateInputRecord(recordFactory, inObj);
+ callDetectorControl.setReturnValue(inputRecord, 1);
+
+ connectionFactory.getConnection();
+ connectionFactoryControl.setReturnValue(connection, 1);
+
+ connection.createInteraction();
+ connectionControl.setReturnValue(interaction, 1);
+
+ connectionFactory.getRecordFactory();
+ connectionFactoryControl.setReturnValue(recordFactory, 1);
+
+ outputCreator.createRecord(recordFactory);
+ outputCreatorControl.setReturnValue(outputRecord, 1);
+
+ interaction.execute(interactionSpec, inputRecord, outputRecord);
+ interactionControl.setReturnValue(true, 1);
+
+ callDetector.callExtractOutputData(outputRecord);
+ callDetectorControl.setReturnValue(outObj, 1);
+
+ interaction.close();
+ interactionControl.setVoidCallable(1);
+
+ connection.close();
+ connectionControl.setVoidCallable(1);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ interactionControl.replay();
+ outputCreatorControl.replay();
+ callDetectorControl.replay();
+
+ assertSame(outObj, query.execute(inObj));
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ interactionControl.verify();
+ outputCreatorControl.verify();
+ callDetectorControl.verify();
+ }
+
+
+ private class MappingRecordOperationImpl extends MappingRecordOperation {
+
+ private QueryCallDetector callDetector;
+
+ public MappingRecordOperationImpl(ConnectionFactory connectionFactory, InteractionSpec interactionSpec) {
+ super(connectionFactory, interactionSpec);
+ }
+
+ public void setCallDetector(QueryCallDetector callDetector) {
+ this.callDetector = callDetector;
+ }
+
+ protected Record createInputRecord(RecordFactory recordFactory, Object inputObject) {
+ return this.callDetector.callCreateInputRecord(recordFactory, inputObject);
+ }
+
+ protected Object extractOutputData(Record outputRecord) throws ResourceException {
+ return this.callDetector.callExtractOutputData(outputRecord);
+ }
+ }
+
+
+ private interface QueryCallDetector {
+
+ Record callCreateInputRecord(RecordFactory recordFactory, Object inputObject);
+
+ Object callExtractOutputData(Record outputRecord);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jca/support/LocalConnectionFactoryBeanTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jca/support/LocalConnectionFactoryBeanTests.java
new file mode 100644
index 00000000000..b988bed10f5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jca/support/LocalConnectionFactoryBeanTests.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jca.support;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+import org.springframework.test.AssertThrows;
+
+import javax.resource.spi.ConnectionManager;
+import javax.resource.spi.ManagedConnectionFactory;
+
+/**
+ * Unit tests for the {@link LocalConnectionFactoryBean} class.
+ *
+ * @author Rick Evans
+ */
+public final class LocalConnectionFactoryBeanTests extends TestCase {
+
+ public void testManagedConnectionFactoryIsRequired() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new LocalConnectionFactoryBean().afterPropertiesSet();
+ }
+ }.runTest();
+ }
+
+ public void testIsSingleton() throws Exception {
+ LocalConnectionFactoryBean factory = new LocalConnectionFactoryBean();
+ assertTrue(factory.isSingleton());
+ }
+
+ public void testGetObjectTypeIsNullIfConnectionFactoryHasNotBeenConfigured() throws Exception {
+ LocalConnectionFactoryBean factory = new LocalConnectionFactoryBean();
+ assertNull(factory.getObjectType());
+ }
+
+ public void testCreatesVanillaConnectionFactoryIfNoConnectionManagerHasBeenConfigured() throws Exception {
+
+ final Object CONNECTION_FACTORY = new Object();
+
+ MockControl mockManagedConnectionFactory = MockControl.createControl(ManagedConnectionFactory.class);
+ ManagedConnectionFactory managedConnectionFactory = (ManagedConnectionFactory) mockManagedConnectionFactory.getMock();
+
+ managedConnectionFactory.createConnectionFactory();
+ mockManagedConnectionFactory.setReturnValue(CONNECTION_FACTORY);
+ mockManagedConnectionFactory.replay();
+
+ LocalConnectionFactoryBean factory = new LocalConnectionFactoryBean();
+ factory.setManagedConnectionFactory(managedConnectionFactory);
+ factory.afterPropertiesSet();
+ assertEquals(CONNECTION_FACTORY, factory.getObject());
+
+ mockManagedConnectionFactory.verify();
+ }
+
+ public void testCreatesManagedConnectionFactoryIfAConnectionManagerHasBeenConfigured() throws Exception {
+ MockControl mockManagedConnectionFactory = MockControl.createControl(ManagedConnectionFactory.class);
+ ManagedConnectionFactory managedConnectionFactory = (ManagedConnectionFactory) mockManagedConnectionFactory.getMock();
+
+ MockControl mockConnectionManager = MockControl.createControl(ConnectionManager.class);
+ ConnectionManager connectionManager = (ConnectionManager) mockConnectionManager.getMock();
+
+ managedConnectionFactory.createConnectionFactory(connectionManager);
+ mockManagedConnectionFactory.setReturnValue(null);
+
+ mockConnectionManager.replay();
+ mockManagedConnectionFactory.replay();
+
+ LocalConnectionFactoryBean factory = new LocalConnectionFactoryBean();
+ factory.setManagedConnectionFactory(managedConnectionFactory);
+ factory.setConnectionManager(connectionManager);
+ factory.afterPropertiesSet();
+
+ mockManagedConnectionFactory.verify();
+ mockConnectionManager.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/AbstractJdbcTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/AbstractJdbcTests.java
new file mode 100644
index 00000000000..c8fecfdf969
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/AbstractJdbcTests.java
@@ -0,0 +1,85 @@
+/*
+ * AbstractJdbcTests.java
+ *
+ * Copyright (C) 2002 by Interprise Software. All rights reserved.
+ */
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jdbc;
+
+import java.sql.Connection;
+
+import javax.sql.DataSource;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+/**
+ * @author Trevor D. Cook
+ */
+public abstract class AbstractJdbcTests extends TestCase {
+
+ protected MockControl ctrlDataSource;
+ protected DataSource mockDataSource;
+ protected MockControl ctrlConnection;
+ protected Connection mockConnection;
+
+ /**
+ * Set to true if the user wants verification, indicated
+ * by a call to replay(). We need to make this optional,
+ * otherwise we setUp() will always result in verification failures
+ */
+ private boolean shouldVerify;
+
+ protected void setUp() throws Exception {
+ this.shouldVerify = false;
+ super.setUp();
+
+ ctrlConnection = MockControl.createControl(Connection.class);
+ mockConnection = (Connection) ctrlConnection.getMock();
+ mockConnection.getMetaData();
+ ctrlConnection.setDefaultReturnValue(null);
+ mockConnection.close();
+ ctrlConnection.setDefaultVoidCallable();
+
+ ctrlDataSource = MockControl.createControl(DataSource.class);
+ mockDataSource = (DataSource) ctrlDataSource.getMock();
+ mockDataSource.getConnection();
+ ctrlDataSource.setDefaultReturnValue(mockConnection);
+ }
+
+ protected void replay() {
+ ctrlDataSource.replay();
+ ctrlConnection.replay();
+ this.shouldVerify = true;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ // we shouldn't verify unless the user called replay()
+ if (shouldVerify()) {
+ ctrlDataSource.verify();
+ //ctrlConnection.verify();
+ }
+ }
+
+ protected boolean shouldVerify() {
+ return this.shouldVerify;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/Customer.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/Customer.java
new file mode 100644
index 00000000000..7c804be1d82
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/Customer.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jdbc;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class Customer {
+
+ private int id;
+
+ private String forename;
+
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getForename() {
+ return forename;
+ }
+
+ public void setForename(String forename) {
+ this.forename = forename;
+ }
+
+
+ public String toString() {
+ return "Customer: id=" + id + "; forename=" + forename;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/AbstractRowMapperTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/AbstractRowMapperTests.java
new file mode 100644
index 00000000000..271fadee7c7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/AbstractRowMapperTests.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.core;
+
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Timestamp;
+import java.sql.Types;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.jdbc.core.test.ConcretePerson;
+import org.springframework.jdbc.core.test.Person;
+import org.springframework.jdbc.datasource.SingleConnectionDataSource;
+import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
+
+/**
+ * Mock object based abstract class for RowMapper tests.
+ * Initializes mock objects and verifies results.
+ *
+ * @author Thomas Risberg
+ */
+public abstract class AbstractRowMapperTests extends TestCase {
+
+ private final boolean debugEnabled = LogFactory.getLog(JdbcTemplate.class).isDebugEnabled();
+
+ protected MockControl conControl;
+ protected Connection con;
+ protected MockControl rsmdControl;
+ protected ResultSetMetaData rsmd;
+ protected MockControl rsControl;
+ protected ResultSet rs;
+ protected MockControl stmtControl;
+ protected Statement stmt;
+ protected JdbcTemplate jdbcTemplate;
+
+ protected void setUp() throws SQLException {
+ conControl = MockControl.createControl(Connection.class);
+ con = (Connection) conControl.getMock();
+ con.isClosed();
+ conControl.setDefaultReturnValue(false);
+
+ rsmdControl = MockControl.createControl(ResultSetMetaData.class);
+ rsmd = (ResultSetMetaData)rsmdControl.getMock();
+ rsmd.getColumnCount();
+ rsmdControl.setReturnValue(4, 1);
+ rsmd.getColumnLabel(1);
+ rsmdControl.setReturnValue("name", 1);
+ rsmd.getColumnLabel(2);
+ rsmdControl.setReturnValue("age", 1);
+ rsmd.getColumnLabel(3);
+ rsmdControl.setReturnValue("birth_date", 1);
+ rsmd.getColumnLabel(4);
+ rsmdControl.setReturnValue("balance", 1);
+ rsmdControl.replay();
+
+ rsControl = MockControl.createControl(ResultSet.class);
+ rs = (ResultSet) rsControl.getMock();
+ rs.getMetaData();
+ rsControl.setReturnValue(rsmd, 1);
+ rs.next();
+ rsControl.setReturnValue(true, 1);
+ rs.getString(1);
+ rsControl.setReturnValue("Bubba", 1);
+ rs.wasNull();
+ rsControl.setReturnValue(false, 1);
+ rs.getLong(2);
+ rsControl.setReturnValue(22, 1);
+ rs.getTimestamp(3);
+ rsControl.setReturnValue(new Timestamp(1221222L), 1);
+ rs.getBigDecimal(4);
+ rsControl.setReturnValue(new BigDecimal("1234.56"), 1);
+ rs.next();
+ rsControl.setReturnValue(false, 1);
+ rs.close();
+ rsControl.setVoidCallable(1);
+ rsControl.replay();
+
+ stmtControl = MockControl.createControl(Statement.class);
+ stmt = (Statement) stmtControl.getMock();
+
+ con.createStatement();
+ conControl.setReturnValue(stmt, 1);
+ stmt.executeQuery("select name, age, birth_date, balance from people");
+ stmtControl.setReturnValue(rs, 1);
+ if (debugEnabled) {
+ stmt.getWarnings();
+ stmtControl.setReturnValue(null, 1);
+ }
+ stmt.close();
+ stmtControl.setVoidCallable(1);
+
+ conControl.replay();
+ stmtControl.replay();
+
+ jdbcTemplate = new JdbcTemplate();
+ jdbcTemplate.setDataSource(new SingleConnectionDataSource(con, false));
+ jdbcTemplate.setExceptionTranslator(new SQLStateSQLExceptionTranslator());
+ jdbcTemplate.afterPropertiesSet();
+ }
+
+ protected void verifyPerson(Person bean) {
+ verify();
+ assertEquals("Bubba", bean.getName());
+ assertEquals(22L, bean.getAge());
+ assertEquals(new java.util.Date(1221222L), bean.getBirth_date());
+ assertEquals(new BigDecimal("1234.56"), bean.getBalance());
+ }
+
+ protected void verifyConcretePerson(ConcretePerson bean) {
+ verify();
+ assertEquals("Bubba", bean.getName());
+ assertEquals(22L, bean.getAge());
+ assertEquals(new java.util.Date(1221222L), bean.getBirth_date());
+ assertEquals(new BigDecimal("1234.56"), bean.getBalance());
+ }
+
+ private void verify() {
+ conControl.verify();
+ rsControl.verify();
+ rsmdControl.verify();
+ stmtControl.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/BeanPropertyRowMapperTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/BeanPropertyRowMapperTests.java
new file mode 100644
index 00000000000..e877542898b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/BeanPropertyRowMapperTests.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.core;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+import org.springframework.jdbc.core.test.ConcretePerson;
+import org.springframework.jdbc.core.test.ExtendedPerson;
+import org.springframework.jdbc.core.test.Person;
+
+/**
+ * @author Thomas Risberg
+ * @author Juergen Hoeller
+ */
+public class BeanPropertyRowMapperTests extends AbstractRowMapperTests {
+
+ public void testOverridingClassDefinedForMapping() {
+ BeanPropertyRowMapper mapper = new BeanPropertyRowMapper(Person.class);
+ try {
+ mapper.setMappedClass(Long.class);
+ fail("Setting new class should have thrown InvalidDataAccessApiUsageException");
+ }
+ catch (InvalidDataAccessApiUsageException ex) {
+ }
+ try {
+ mapper.setMappedClass(Person.class);
+ }
+ catch (InvalidDataAccessApiUsageException ex) {
+ fail("Setting same class should not have thrown InvalidDataAccessApiUsageException");
+ }
+ }
+
+ public void testStaticQueryWithRowMapper() throws SQLException {
+ List result = jdbcTemplate.query("select name, age, birth_date, balance from people",
+ new BeanPropertyRowMapper(Person.class));
+ assertEquals(1, result.size());
+ Person bean = (Person) result.get(0);
+ verifyPerson(bean);
+ }
+
+ public void testMappingWithInheritance() throws SQLException {
+ List result = jdbcTemplate.query("select name, age, birth_date, balance from people",
+ new BeanPropertyRowMapper(ConcretePerson.class));
+ assertEquals(1, result.size());
+ ConcretePerson bean = (ConcretePerson) result.get(0);
+ verifyConcretePerson(bean);
+ }
+
+ public void testMappingWithNoUnpopulatedFieldsFound() throws SQLException {
+ List result = jdbcTemplate.query("select name, age, birth_date, balance from people",
+ new BeanPropertyRowMapper(ConcretePerson.class, true));
+ assertEquals(1, result.size());
+ ConcretePerson bean = (ConcretePerson) result.get(0);
+ verifyConcretePerson(bean);
+ }
+
+ public void testMappingWithUnpopulatedFieldsNotChecked() throws SQLException {
+ List result = jdbcTemplate.query("select name, age, birth_date, balance from people",
+ new BeanPropertyRowMapper(ExtendedPerson.class));
+ assertEquals(1, result.size());
+ ExtendedPerson bean = (ExtendedPerson) result.get(0);
+ verifyConcretePerson(bean);
+ }
+
+ public void testMappingWithUnpopulatedFieldsNotAccepted() throws SQLException {
+ try {
+ List result = jdbcTemplate.query("select name, age, birth_date, balance from people",
+ new BeanPropertyRowMapper(ExtendedPerson.class, true));
+ fail("Should have thrown InvalidDataAccessApiUsageException because of missing field");
+ }
+ catch (InvalidDataAccessApiUsageException ex) {
+ // expected
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/JdbcTemplateQueryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/JdbcTemplateQueryTests.java
new file mode 100644
index 00000000000..9851a23923c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/JdbcTemplateQueryTests.java
@@ -0,0 +1,983 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.core;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.List;
+import java.util.Map;
+
+import org.easymock.MockControl;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.dao.IncorrectResultSizeDataAccessException;
+import org.springframework.jdbc.AbstractJdbcTests;
+
+/**
+ * @author Juergen Hoeller
+ * @since 19.12.2004
+ */
+public class JdbcTemplateQueryTests extends AbstractJdbcTests {
+
+ private final boolean debugEnabled = LogFactory.getLog(JdbcTemplate.class).isDebugEnabled();
+
+ private MockControl ctrlStatement;
+ private Statement mockStatement;
+ private MockControl ctrlPreparedStatement;
+ private PreparedStatement mockPreparedStatement;
+ private MockControl ctrlResultSet;
+ private ResultSet mockResultSet;
+ private MockControl ctrlResultSetMetaData;
+ private ResultSetMetaData mockResultSetMetaData;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ ctrlStatement = MockControl.createControl(Statement.class);
+ mockStatement = (Statement) ctrlStatement.getMock();
+ ctrlPreparedStatement = MockControl.createControl(PreparedStatement.class);
+ mockPreparedStatement = (PreparedStatement) ctrlPreparedStatement.getMock();
+ ctrlResultSet = MockControl.createControl(ResultSet.class);
+ mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ ctrlResultSetMetaData = MockControl.createControl(ResultSetMetaData.class);
+ mockResultSetMetaData = (ResultSetMetaData) ctrlResultSetMetaData.getMock();
+ }
+
+ protected void replay() {
+ super.replay();
+ ctrlStatement.replay();
+ ctrlPreparedStatement.replay();
+ ctrlResultSet.replay();
+ ctrlResultSetMetaData.replay();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ if (shouldVerify()) {
+ ctrlStatement.verify();
+ ctrlPreparedStatement.verify();
+ ctrlResultSet.verify();
+ ctrlResultSetMetaData.verify();
+ }
+ }
+
+ public void testQueryForList() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID < 3";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1, 2);
+ mockResultSetMetaData.getColumnLabel(1);
+ ctrlResultSetMetaData.setReturnValue("age", 2);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData, 2);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getObject(1);
+ ctrlResultSet.setReturnValue(new Integer(11));
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getObject(1);
+ ctrlResultSet.setReturnValue(new Integer(12));
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+
+ List li = template.queryForList(sql);
+ assertEquals("All rows returned", 2, li.size());
+ assertEquals("First row is Integer", 11, ((Integer)((Map)li.get(0)).get("age")).intValue());
+ assertEquals("Second row is Integer", 12, ((Integer)((Map)li.get(1)).get("age")).intValue());
+ }
+
+ public void testQueryForListWithEmptyResult() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID < 3";
+
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ List li = template.queryForList(sql);
+ assertEquals("All rows returned", 0, li.size());
+ }
+
+ public void testQueryForListWithSingleRowAndColumn() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID < 3";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+ mockResultSetMetaData.getColumnLabel(1);
+ ctrlResultSetMetaData.setReturnValue("age", 1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getObject(1);
+ ctrlResultSet.setReturnValue(new Integer(11));
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+
+ List li = template.queryForList(sql);
+ assertEquals("All rows returned", 1, li.size());
+ assertEquals("First row is Integer", 11, ((Integer)((Map)li.get(0)).get("age")).intValue());
+ }
+
+ public void testQueryForListWithIntegerElement() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID < 3";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt(1);
+ ctrlResultSet.setReturnValue(11);
+ mockResultSet.wasNull();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+
+ List li = template.queryForList(sql, Integer.class);
+ assertEquals("All rows returned", 1, li.size());
+ assertEquals("Element is Integer", 11, ((Integer) li.get(0)).intValue());
+ }
+
+ public void testQueryForMapWithSingleRowAndColumn() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID < 3";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+ mockResultSetMetaData.getColumnLabel(1);
+ ctrlResultSetMetaData.setReturnValue("age", 1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getObject(1);
+ ctrlResultSet.setReturnValue(new Integer(11));
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+
+ Map map = template.queryForMap(sql);
+ assertEquals("Wow is Integer", 11, ((Integer) map.get("age")).intValue());
+ }
+
+ public void testQueryForObjectThrowsIncorrectResultSizeForMoreThanOneRow() throws Exception {
+ String sql = "select pass from t_account where first_name='Alef'";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getString(1);
+ ctrlResultSet.setReturnValue("pass");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+ mockResultSet.getString(1);
+ ctrlResultSet.setReturnValue("pass");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ try {
+ template.queryForObject(sql, String.class);
+ fail("Should have thrown IncorrectResultSizeDataAccessException");
+ }
+ catch (IncorrectResultSizeDataAccessException ex) {
+ // expected
+ }
+ }
+
+ public void testQueryForObjectWithRowMapper() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID = 3";
+
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt(1);
+ ctrlResultSet.setReturnValue(22);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+
+ Object o = template.queryForObject(sql, new RowMapper() {
+ public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
+ return new Integer(rs.getInt(1));
+ }
+ });
+ assertTrue("Correct result type", o instanceof Integer);
+ }
+
+ public void testQueryForObjectWithString() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID = 3";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getString(1);
+ ctrlResultSet.setReturnValue("myvalue");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ assertEquals("myvalue", template.queryForObject(sql, String.class));
+ }
+
+ public void testQueryForObjectWithBigInteger() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID = 3";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getObject(1);
+ ctrlResultSet.setReturnValue("22");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ assertEquals(new BigInteger("22"), template.queryForObject(sql, BigInteger.class));
+ }
+
+ public void testQueryForObjectWithBigDecimal() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID = 3";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getBigDecimal(1);
+ ctrlResultSet.setReturnValue(new BigDecimal(22.5));
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ assertEquals(new BigDecimal(22.5), template.queryForObject(sql, BigDecimal.class));
+ }
+
+ public void testQueryForObjectWithInteger() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID = 3";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt(1);
+ ctrlResultSet.setReturnValue(22);
+ mockResultSet.wasNull();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ assertEquals(new Integer(22), template.queryForObject(sql, Integer.class));
+ }
+
+ public void testQueryForObjectWithIntegerAndNull() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID = 3";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt(1);
+ ctrlResultSet.setReturnValue(0);
+ mockResultSet.wasNull();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ assertNull(template.queryForObject(sql, Integer.class));
+ }
+
+ public void testQueryForInt() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID = 3";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt(1);
+ ctrlResultSet.setReturnValue(22);
+ mockResultSet.wasNull();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ int i = template.queryForInt(sql);
+ assertEquals("Return of an int", 22, i);
+ }
+
+ public void testQueryForLong() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID = 3";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getLong(1);
+ ctrlResultSet.setReturnValue(87);
+ mockResultSet.wasNull();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ long l = template.queryForLong(sql);
+ assertEquals("Return of a long", 87, l);
+ }
+
+ public void testQueryForListWithArgs() throws Exception {
+ doTestQueryForListWithArgs("SELECT AGE FROM CUSTMR WHERE ID < ?");
+ }
+
+ public void testQueryForListIsNotConfusedByNamedParameterPrefix() throws Exception {
+ doTestQueryForListWithArgs("SELECT AGE FROM PREFIX:CUSTMR WHERE ID < ?");
+ }
+
+ private void doTestQueryForListWithArgs(String sql) throws Exception {
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1, 2);
+ mockResultSetMetaData.getColumnLabel(1);
+ ctrlResultSetMetaData.setReturnValue("age", 2);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData, 2);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getObject(1);
+ ctrlResultSet.setReturnValue(new Integer(11));
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getObject(1);
+ ctrlResultSet.setReturnValue(new Integer(12));
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(3));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sql);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+
+ List li = template.queryForList(sql, new Object[] {new Integer(3)});
+ assertEquals("All rows returned", 2, li.size());
+ assertEquals("First row is Integer", 11, ((Integer)((Map)li.get(0)).get("age")).intValue());
+ assertEquals("Second row is Integer", 12, ((Integer)((Map)li.get(1)).get("age")).intValue());
+ }
+
+ public void testQueryForListWithArgsAndEmptyResult() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID < ?";
+
+ ctrlResultSet = MockControl.createControl(ResultSet.class);
+ mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(3));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sql);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+
+ List li = template.queryForList(sql, new Object[] {new Integer(3)});
+ assertEquals("All rows returned", 0, li.size());
+ }
+
+ public void testQueryForListWithArgsAndSingleRowAndColumn() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID < ?";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+ mockResultSetMetaData.getColumnLabel(1);
+ ctrlResultSetMetaData.setReturnValue("age", 1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getObject(1);
+ ctrlResultSet.setReturnValue(new Integer(11));
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(3));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sql);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+
+ List li = template.queryForList(sql, new Object[] {new Integer(3)});
+ assertEquals("All rows returned", 1, li.size());
+ assertEquals("First row is Integer", 11, ((Integer)((Map)li.get(0)).get("age")).intValue());
+ }
+
+ public void testQueryForListWithArgsAndIntegerElementAndSingleRowAndColumn() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID < ?";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt(1);
+ ctrlResultSet.setReturnValue(11);
+ mockResultSet.wasNull();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(3));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sql);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+
+ List li = template.queryForList(sql, new Object[] {new Integer(3)}, Integer.class);
+ assertEquals("All rows returned", 1, li.size());
+ assertEquals("First row is Integer", 11, ((Integer) li.get(0)).intValue());
+ }
+
+ public void testQueryForMapWithArgsAndSingleRowAndColumn() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID < ?";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+ mockResultSetMetaData.getColumnLabel(1);
+ ctrlResultSetMetaData.setReturnValue("age", 1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getObject(1);
+ ctrlResultSet.setReturnValue(new Integer(11));
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(3));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sql);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+
+ Map map = template.queryForMap(sql, new Object[] {new Integer(3)});
+ assertEquals("Row is Integer", 11, ((Integer) map.get("age")).intValue());
+ }
+
+ public void testQueryForObjectWithArgsAndRowMapper() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID = ?";
+
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt(1);
+ ctrlResultSet.setReturnValue(22);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(3));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sql);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+
+ Object o = template.queryForObject(sql, new Object[] {new Integer(3)}, new RowMapper() {
+ public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
+ return new Integer(rs.getInt(1));
+ }
+ });
+ assertTrue("Correct result type", o instanceof Integer);
+ }
+
+ public void testQueryForObjectWithArgsAndInteger() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID = ?";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt(1);
+ ctrlResultSet.setReturnValue(22);
+ mockResultSet.wasNull();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(3));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sql);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+
+ Object o = template.queryForObject(sql, new Object[] {new Integer(3)}, Integer.class);
+ assertTrue("Correct result type", o instanceof Integer);
+ }
+
+ public void testQueryForIntWithArgs() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID = ?";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt(1);
+ ctrlResultSet.setReturnValue(22);
+ mockResultSet.wasNull();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(3));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sql);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ int i = template.queryForInt(sql, new Object[] {new Integer(3)});
+ assertEquals("Return of an int", 22, i);
+ }
+
+ public void testQueryForLongWithArgs() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID = ?";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getLong(1);
+ ctrlResultSet.setReturnValue(87);
+ mockResultSet.wasNull();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(3));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sql);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ long l = template.queryForLong(sql, new Object[] {new Integer(3)});
+ assertEquals("Return of a long", 87, l);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/JdbcTemplateTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/JdbcTemplateTests.java
new file mode 100644
index 00000000000..2014c9daf5b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/JdbcTemplateTests.java
@@ -0,0 +1,2057 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.core;
+
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.Statement;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.sql.DataSource;
+
+import org.easymock.MockControl;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+import org.springframework.dao.UncategorizedDataAccessException;
+import org.springframework.jdbc.AbstractJdbcTests;
+import org.springframework.jdbc.BadSqlGrammarException;
+import org.springframework.jdbc.CannotGetJdbcConnectionException;
+import org.springframework.jdbc.SQLWarningException;
+import org.springframework.jdbc.UncategorizedSQLException;
+import org.springframework.jdbc.core.support.AbstractInterruptibleBatchPreparedStatementSetter;
+import org.springframework.jdbc.datasource.SingleConnectionDataSource;
+import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator;
+import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
+import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
+import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractorAdapter;
+
+/**
+ * Mock object based tests for JdbcTemplate.
+ *
+ * @author Rod Johnson
+ * @author Thomas Risberg
+ * @author Juergen Hoeller
+ */
+public class JdbcTemplateTests extends AbstractJdbcTests {
+
+ private final boolean debugEnabled = LogFactory.getLog(JdbcTemplate.class).isDebugEnabled();
+
+
+ public void testBeanProperties() throws Exception {
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ assertTrue("datasource ok", template.getDataSource() == mockDataSource);
+ assertTrue("ignores warnings by default", template.isIgnoreWarnings());
+ template.setIgnoreWarnings(false);
+ assertTrue("can set NOT to ignore warnings", !template.isIgnoreWarnings());
+ }
+
+ public void testUpdateCount() throws Exception {
+ final String sql =
+ "UPDATE INVOICE SET DATE_DISPATCHED = SYSDATE WHERE ID = ?";
+ int idParam = 11111;
+
+ MockControl ctrlPreparedStatement =
+ MockControl.createControl(PreparedStatement.class);
+ PreparedStatement mockPreparedStatement =
+ (PreparedStatement) ctrlPreparedStatement.getMock();
+ mockPreparedStatement.setInt(1, idParam);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(1);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sql);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ ctrlPreparedStatement.replay();
+ replay();
+
+ Dispatcher d = new Dispatcher(idParam, sql);
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+
+ int rowsAffected = template.update(d);
+ assertTrue("1 update affected 1 row", rowsAffected == 1);
+
+ /*
+ d = new Dispatcher(idParam);
+ rowsAffected = template.update(d);
+ assertTrue("bogus update affected 0 rows", rowsAffected == 0);
+ */
+
+ ctrlPreparedStatement.verify();
+ }
+
+ public void testBogusUpdate() throws Exception {
+ final String sql =
+ "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = ?";
+ final int idParam = 6666;
+
+ // It's because Integers aren't canonical
+ SQLException sex = new SQLException("bad update");
+
+ MockControl ctrlPreparedStatement =
+ MockControl.createControl(PreparedStatement.class);
+ PreparedStatement mockPreparedStatement =
+ (PreparedStatement) ctrlPreparedStatement.getMock();
+ mockPreparedStatement.setInt(1, idParam);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setThrowable(sex);
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sql);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ ctrlPreparedStatement.replay();
+ replay();
+
+ Dispatcher d = new Dispatcher(idParam, sql);
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+
+ try {
+ template.update(d);
+ fail("Bogus update should throw exception");
+ }
+ catch (UncategorizedDataAccessException ex) {
+ // pass
+ assertTrue(
+ "Correct exception",
+ ex instanceof UncategorizedSQLException);
+ assertTrue("Root cause is correct", ex.getCause() == sex);
+ //assertTrue("no update occurred", !je.getDataWasUpdated());
+ }
+
+ ctrlPreparedStatement.verify();
+ }
+
+ public void testStringsWithStaticSql() throws Exception {
+ doTestStrings(new JdbcTemplateCallback() {
+ public void doInJdbcTemplate(JdbcTemplate template, String sql, RowCallbackHandler rch) {
+ template.query(sql, rch);
+ }
+ }, false, null, null, null, null);
+ }
+
+ public void testStringsWithStaticSqlAndFetchSizeAndMaxRows() throws Exception {
+ doTestStrings(new JdbcTemplateCallback() {
+ public void doInJdbcTemplate(JdbcTemplate template, String sql, RowCallbackHandler rch) {
+ template.query(sql, rch);
+ }
+ }, false, new Integer(10), new Integer(20), new Integer(30), null);
+ }
+
+ public void testStringsWithEmptyPreparedStatementSetter() throws Exception {
+ doTestStrings(new JdbcTemplateCallback() {
+ public void doInJdbcTemplate(JdbcTemplate template, String sql, RowCallbackHandler rch) {
+ template.query(sql, (PreparedStatementSetter) null, rch);
+ }
+ }, true, null, null, null, null);
+ }
+
+ public void testStringsWithPreparedStatementSetter() throws Exception {
+ final Integer argument = new Integer(99);
+ doTestStrings(new JdbcTemplateCallback() {
+ public void doInJdbcTemplate(JdbcTemplate template, String sql, RowCallbackHandler rch) {
+ template.query(sql, new PreparedStatementSetter() {
+ public void setValues(PreparedStatement ps) throws SQLException {
+ ps.setObject(1, argument);
+ }
+ }, rch);
+ }
+ }, true, null, null, null, argument);
+ }
+
+ public void testStringsWithEmptyPreparedStatementArgs() throws Exception {
+ doTestStrings(new JdbcTemplateCallback() {
+ public void doInJdbcTemplate(JdbcTemplate template, String sql, RowCallbackHandler rch) {
+ template.query(sql, (Object[]) null, rch);
+ }
+ }, true, null, null, null, null);
+ }
+
+ public void testStringsWithPreparedStatementArgs() throws Exception {
+ final Integer argument = new Integer(99);
+ doTestStrings(new JdbcTemplateCallback() {
+ public void doInJdbcTemplate(JdbcTemplate template, String sql, RowCallbackHandler rch) {
+ template.query(sql, new Object[] {argument}, rch);
+ }
+ }, true, null, null, null, argument);
+ }
+
+ private void doTestStrings(
+ JdbcTemplateCallback jdbcTemplateCallback, boolean usePreparedStatement,
+ Integer fetchSize, Integer maxRows, Integer queryTimeout, Object argument)
+ throws Exception {
+
+ String sql = "SELECT FORENAME FROM CUSTMR";
+ String[] results = { "rod", "gary", " portia" };
+
+ class StringHandler implements RowCallbackHandler {
+ private List list = new LinkedList();
+ public void processRow(ResultSet rs) throws SQLException {
+ list.add(rs.getString(1));
+ }
+ public String[] getStrings() {
+ return (String[]) list.toArray(new String[list.size()]);
+ }
+ }
+
+ MockControl ctrlResultSet = MockControl.createControl(ResultSet.class);
+ ResultSet mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getString(1);
+ ctrlResultSet.setReturnValue(results[0]);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getString(1);
+ ctrlResultSet.setReturnValue(results[1]);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getString(1);
+ ctrlResultSet.setReturnValue(results[2]);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ MockControl ctrlStatement = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement mockStatement = (PreparedStatement) ctrlStatement.getMock();
+ if (fetchSize != null) {
+ mockStatement.setFetchSize(fetchSize.intValue());
+ }
+ if (maxRows != null) {
+ mockStatement.setMaxRows(maxRows.intValue());
+ }
+ if (queryTimeout != null) {
+ mockStatement.setQueryTimeout(queryTimeout.intValue());
+ }
+ if (argument != null) {
+ mockStatement.setObject(1, argument);
+ }
+ if (usePreparedStatement) {
+ mockStatement.executeQuery();
+ }
+ else {
+ mockStatement.executeQuery(sql);
+ }
+ ctrlStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ if (usePreparedStatement) {
+ mockConnection.prepareStatement(sql);
+ }
+ else {
+ mockConnection.createStatement();
+ }
+ ctrlConnection.setReturnValue(mockStatement);
+
+ ctrlResultSet.replay();
+ ctrlStatement.replay();
+ replay();
+
+ StringHandler sh = new StringHandler();
+ JdbcTemplate template = new JdbcTemplate();
+ template.setDataSource(mockDataSource);
+ if (fetchSize != null) {
+ template.setFetchSize(fetchSize.intValue());
+ }
+ if (maxRows != null) {
+ template.setMaxRows(maxRows.intValue());
+ }
+ if (queryTimeout != null) {
+ template.setQueryTimeout(queryTimeout.intValue());
+ }
+ jdbcTemplateCallback.doInJdbcTemplate(template, sql, sh);
+
+ // Match
+ String[] forenames = sh.getStrings();
+ assertTrue("same length", forenames.length == results.length);
+ for (int i = 0; i < forenames.length; i++) {
+ assertTrue("Row " + i + " matches", forenames[i].equals(results[i]));
+ }
+
+ ctrlResultSet.verify();
+ ctrlStatement.verify();
+ }
+
+ public void testLeaveConnectionOpenOnRequest() throws Exception {
+ String sql = "SELECT ID, FORENAME FROM CUSTMR WHERE ID < 3";
+
+ MockControl ctrlResultSet = MockControl.createControl(ResultSet.class);
+ ResultSet mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ ctrlResultSet = MockControl.createControl(ResultSet.class);
+ mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ MockControl ctrlStatement = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement mockStatement = (PreparedStatement) ctrlStatement.getMock();
+ ctrlStatement = MockControl.createControl(PreparedStatement.class);
+ mockStatement = (PreparedStatement) ctrlStatement.getMock();
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.isClosed();
+ ctrlConnection.setReturnValue(false, 2);
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+ // if close is called entire test will fail
+ mockConnection.close();
+ ctrlConnection.setDefaultThrowable(new RuntimeException());
+
+ ctrlResultSet.replay();
+ ctrlStatement.replay();
+ replay();
+
+ SingleConnectionDataSource scf = new SingleConnectionDataSource(mockDataSource.getConnection(), false);
+ JdbcTemplate template2 = new JdbcTemplate(scf, false);
+ RowCountCallbackHandler rcch = new RowCountCallbackHandler();
+ template2.query(sql, rcch);
+
+ ctrlResultSet.verify();
+ ctrlStatement.verify();
+ }
+
+ public void testConnectionCallback() throws Exception {
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ template.setNativeJdbcExtractor(new PlainNativeJdbcExtractor());
+ Object result = template.execute(new ConnectionCallback() {
+ public Object doInConnection(Connection con) {
+ assertSame(mockConnection, con);
+ return "test";
+ }
+ });
+
+ assertEquals("test", result);
+ }
+
+ public void testConnectionCallbackWithStatementSettings() throws Exception {
+ MockControl ctrlStatement = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement mockStatement = (PreparedStatement) ctrlStatement.getMock();
+ mockConnection.prepareStatement("some SQL");
+ ctrlConnection.setReturnValue(mockStatement, 1);
+ mockStatement.setFetchSize(10);
+ ctrlStatement.setVoidCallable(1);
+ mockStatement.setMaxRows(20);
+ ctrlStatement.setVoidCallable(1);
+ mockStatement.close();
+ ctrlStatement.setVoidCallable(1);
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ Object result = template.execute(new ConnectionCallback() {
+ public Object doInConnection(Connection con) throws SQLException {
+ PreparedStatement ps = con.prepareStatement("some SQL");
+ ps.close();
+ assertSame(mockConnection, new PlainNativeJdbcExtractor().getNativeConnection(con));
+ return "test";
+ }
+ });
+
+ assertEquals("test", result);
+ }
+
+ public void testCloseConnectionOnRequest() throws Exception {
+ String sql = "SELECT ID, FORENAME FROM CUSTMR WHERE ID < 3";
+
+ MockControl ctrlResultSet = MockControl.createControl(ResultSet.class);
+ ResultSet mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ MockControl ctrlStatement = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement mockStatement = (PreparedStatement) ctrlStatement.getMock();
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ ctrlResultSet.replay();
+ ctrlStatement.replay();
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ RowCountCallbackHandler rcch = new RowCountCallbackHandler();
+ template.query(sql, rcch);
+
+ ctrlResultSet.verify();
+ ctrlStatement.verify();
+ }
+
+ /**
+ * Test that we see a runtime exception come back.
+ */
+ public void testExceptionComesBack() throws Exception {
+ final String sql = "SELECT ID FROM CUSTMR";
+ final RuntimeException rex = new RuntimeException("What I want to see");
+
+ MockControl ctrlResultSet = MockControl.createControl(ResultSet.class);
+ ResultSet mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ MockControl ctrlStatement = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement mockStatement = (PreparedStatement) ctrlStatement.getMock();
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ ctrlResultSet.replay();
+ ctrlStatement.replay();
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ try {
+ template.query(sql, new RowCallbackHandler() {
+ public void processRow(ResultSet rs) {
+ throw rex;
+ }
+ });
+ fail("Should have thrown exception");
+ }
+ catch (RuntimeException ex) {
+ assertTrue("Wanted same exception back, not " + ex, ex == rex);
+ }
+ }
+
+ /**
+ * Test update with static SQL.
+ */
+ public void testSqlUpdate() throws Exception {
+ final String sql = "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = 4";
+ int rowsAffected = 33;
+
+ MockControl ctrlStatement = MockControl.createControl(Statement.class);
+ Statement mockStatement = (Statement) ctrlStatement.getMock();
+ mockStatement.executeUpdate(sql);
+ ctrlStatement.setReturnValue(rowsAffected);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+ ctrlStatement.replay();
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ int actualRowsAffected = template.update(sql);
+ assertTrue("Actual rows affected is correct", actualRowsAffected == rowsAffected);
+ ctrlStatement.verify();
+ }
+
+ /**
+ * Test update with dynamic SQL.
+ */
+ public void testSqlUpdateWithArguments() throws Exception {
+ final String sql = "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = ? and PR = ?";
+ int rowsAffected = 33;
+
+ MockControl ctrlStatement = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement mockStatement = (PreparedStatement) ctrlStatement.getMock();
+ mockStatement.setObject(1, new Integer(4));
+ ctrlStatement.setVoidCallable();
+ mockStatement.setObject(2, new Float(1.4142), Types.NUMERIC, 2);
+ ctrlStatement.setVoidCallable();
+ mockStatement.executeUpdate();
+ ctrlStatement.setReturnValue(33);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sql);
+ ctrlConnection.setReturnValue(mockStatement);
+ ctrlStatement.replay();
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ int actualRowsAffected = template.update(sql,
+ new Object[] {new Integer(4), new SqlParameterValue(Types.NUMERIC, 2, new Float(1.4142))});
+ assertTrue("Actual rows affected is correct", actualRowsAffected == rowsAffected);
+ ctrlStatement.verify();
+ }
+
+ public void testSqlUpdateEncountersSqlException() throws Exception {
+ SQLException sex = new SQLException("bad update");
+ final String sql = "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = 4";
+
+ MockControl ctrlStatement = MockControl.createControl(Statement.class);
+ Statement mockStatement = (Statement) ctrlStatement.getMock();
+ mockStatement.executeUpdate(sql);
+ ctrlStatement.setThrowable(sex);
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ ctrlStatement.replay();
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ try {
+ template.update(sql);
+ }
+ catch (DataAccessException ex) {
+ assertTrue("root cause is correct", ex.getCause() == sex);
+ }
+
+ ctrlStatement.verify();
+ }
+
+ public void testSqlUpdateWithThreadConnection() throws Exception {
+ final String sql = "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = 4";
+ int rowsAffected = 33;
+
+ MockControl ctrlStatement = MockControl.createControl(Statement.class);
+ Statement mockStatement = (Statement) ctrlStatement.getMock();
+ mockStatement.executeUpdate(sql);
+ ctrlStatement.setReturnValue(rowsAffected);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ ctrlStatement.replay();
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+
+ int actualRowsAffected = template.update(sql);
+ assertTrue(
+ "Actual rows affected is correct",
+ actualRowsAffected == rowsAffected);
+
+ ctrlStatement.verify();
+ }
+
+ public void testBatchUpdate() throws Exception {
+ final String[] sql = {"UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = 1",
+ "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = 2"};
+
+ MockControl ctrlStatement = MockControl.createControl(Statement.class);
+ Statement mockStatement = (Statement) ctrlStatement.getMock();
+ mockStatement.getConnection();
+ ctrlStatement.setReturnValue(mockConnection);
+ mockStatement.addBatch(sql[0]);
+ ctrlStatement.setVoidCallable();
+ mockStatement.addBatch(sql[1]);
+ ctrlStatement.setVoidCallable();
+ mockStatement.executeBatch();
+ ctrlStatement.setReturnValue(new int[] {1, 1});
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ MockControl ctrlDatabaseMetaData = MockControl.createControl(DatabaseMetaData.class);
+ DatabaseMetaData mockDatabaseMetaData = (DatabaseMetaData) ctrlDatabaseMetaData.getMock();
+ mockDatabaseMetaData.getDatabaseProductName();
+ ctrlDatabaseMetaData.setReturnValue("MySQL");
+ mockDatabaseMetaData.supportsBatchUpdates();
+ ctrlDatabaseMetaData.setReturnValue(true);
+
+ mockConnection.getMetaData();
+ ctrlConnection.setReturnValue(mockDatabaseMetaData, 2);
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ ctrlStatement.replay();
+ ctrlDatabaseMetaData.replay();
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource, false);
+
+ int[] actualRowsAffected = template.batchUpdate(sql);
+ assertTrue("executed 2 updates", actualRowsAffected.length == 2);
+
+ ctrlStatement.verify();
+ ctrlDatabaseMetaData.verify();
+ }
+
+ public void testBatchUpdateWithNoBatchSupport() throws Exception {
+ final String[] sql = {"UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = 1",
+ "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = 2"};
+
+ MockControl ctrlStatement = MockControl.createControl(Statement.class);
+ Statement mockStatement = (Statement) ctrlStatement.getMock();
+ mockStatement.getConnection();
+ ctrlStatement.setReturnValue(mockConnection);
+ mockStatement.execute(sql[0]);
+ ctrlStatement.setReturnValue(false);
+ mockStatement.getUpdateCount();
+ ctrlStatement.setReturnValue(1);
+ mockStatement.execute(sql[1]);
+ ctrlStatement.setReturnValue(false);
+ mockStatement.getUpdateCount();
+ ctrlStatement.setReturnValue(1);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ MockControl ctrlDatabaseMetaData = MockControl.createControl(DatabaseMetaData.class);
+ DatabaseMetaData mockDatabaseMetaData = (DatabaseMetaData) ctrlDatabaseMetaData.getMock();
+ mockDatabaseMetaData.getDatabaseProductName();
+ ctrlDatabaseMetaData.setReturnValue("MySQL");
+ mockDatabaseMetaData.supportsBatchUpdates();
+ ctrlDatabaseMetaData.setReturnValue(false);
+
+ mockConnection.getMetaData();
+ ctrlConnection.setReturnValue(mockDatabaseMetaData, 2);
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ ctrlStatement.replay();
+ ctrlDatabaseMetaData.replay();
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource, false);
+
+ int[] actualRowsAffected = template.batchUpdate(sql);
+ assertTrue("executed 2 updates", actualRowsAffected.length == 2);
+
+ ctrlStatement.verify();
+ ctrlDatabaseMetaData.verify();
+ }
+
+ public void testBatchUpdateWithNoBatchSupportAndSelect() throws Exception {
+ final String[] sql = {"UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = 1",
+ "SELECT * FROM NOSUCHTABLE"};
+
+ MockControl ctrlStatement = MockControl.createControl(Statement.class);
+ Statement mockStatement = (Statement) ctrlStatement.getMock();
+ mockStatement.getConnection();
+ ctrlStatement.setReturnValue(mockConnection);
+ mockStatement.execute(sql[0]);
+ ctrlStatement.setReturnValue(false);
+ mockStatement.getUpdateCount();
+ ctrlStatement.setReturnValue(1);
+ mockStatement.execute(sql[1]);
+ ctrlStatement.setReturnValue(true);
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ MockControl ctrlDatabaseMetaData = MockControl.createControl(DatabaseMetaData.class);
+ DatabaseMetaData mockDatabaseMetaData = (DatabaseMetaData) ctrlDatabaseMetaData.getMock();
+ mockDatabaseMetaData.getDatabaseProductName();
+ ctrlDatabaseMetaData.setReturnValue("MySQL");
+ mockDatabaseMetaData.supportsBatchUpdates();
+ ctrlDatabaseMetaData.setReturnValue(false);
+
+ mockConnection.getMetaData();
+ ctrlConnection.setReturnValue(mockDatabaseMetaData, 2);
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ ctrlStatement.replay();
+ ctrlDatabaseMetaData.replay();
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource, false);
+
+ try {
+ template.batchUpdate(sql);
+ fail("Shouldn't have executed batch statement with a select");
+ }
+ catch (DataAccessException ex) {
+ // pass
+ assertTrue("Check exception type", ex.getClass() == InvalidDataAccessApiUsageException.class);
+ }
+
+ ctrlStatement.verify();
+ ctrlDatabaseMetaData.verify();
+ }
+
+ public void testBatchUpdateWithPreparedStatement() throws Exception {
+ final String sql = "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = ?";
+ final int[] ids = new int[] { 100, 200 };
+ final int[] rowsAffected = new int[] { 1, 2 };
+
+ MockControl ctrlPreparedStatement = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement mockPreparedStatement = (PreparedStatement) ctrlPreparedStatement.getMock();
+ mockPreparedStatement.getConnection();
+ ctrlPreparedStatement.setReturnValue(mockConnection);
+ mockPreparedStatement.setInt(1, ids[0]);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.addBatch();
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setInt(1, ids[1]);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.addBatch();
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeBatch();
+ ctrlPreparedStatement.setReturnValue(rowsAffected);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ MockControl ctrlDatabaseMetaData = MockControl.createControl(DatabaseMetaData.class);
+ DatabaseMetaData mockDatabaseMetaData = (DatabaseMetaData) ctrlDatabaseMetaData.getMock();
+ mockDatabaseMetaData.getDatabaseProductName();
+ ctrlDatabaseMetaData.setReturnValue("MySQL");
+ mockDatabaseMetaData.supportsBatchUpdates();
+ ctrlDatabaseMetaData.setReturnValue(true);
+
+ mockConnection.prepareStatement(sql);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+ mockConnection.getMetaData();
+ ctrlConnection.setReturnValue(mockDatabaseMetaData, 2);
+
+ ctrlPreparedStatement.replay();
+ ctrlDatabaseMetaData.replay();
+ replay();
+
+ BatchPreparedStatementSetter setter =
+ new BatchPreparedStatementSetter() {
+ public void setValues(PreparedStatement ps, int i)
+ throws SQLException {
+ ps.setInt(1, ids[i]);
+ }
+ public int getBatchSize() {
+ return ids.length;
+ }
+ };
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource, false);
+
+ int[] actualRowsAffected = template.batchUpdate(sql, setter);
+ assertTrue("executed 2 updates", actualRowsAffected.length == 2);
+ assertEquals(rowsAffected[0], actualRowsAffected[0]);
+ assertEquals(rowsAffected[1], actualRowsAffected[1]);
+
+ ctrlPreparedStatement.verify();
+ ctrlDatabaseMetaData.verify();
+ }
+
+ public void testInterruptibleBatchUpdate() throws Exception {
+ final String sql = "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = ?";
+ final int[] ids = new int[] { 100, 200 };
+ final int[] rowsAffected = new int[] { 1, 2 };
+
+ MockControl ctrlPreparedStatement = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement mockPreparedStatement = (PreparedStatement) ctrlPreparedStatement.getMock();
+ mockPreparedStatement.getConnection();
+ ctrlPreparedStatement.setReturnValue(mockConnection);
+ mockPreparedStatement.setInt(1, ids[0]);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.addBatch();
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setInt(1, ids[1]);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.addBatch();
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeBatch();
+ ctrlPreparedStatement.setReturnValue(rowsAffected);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ MockControl ctrlDatabaseMetaData = MockControl.createControl(DatabaseMetaData.class);
+ DatabaseMetaData mockDatabaseMetaData = (DatabaseMetaData) ctrlDatabaseMetaData.getMock();
+ mockDatabaseMetaData.getDatabaseProductName();
+ ctrlDatabaseMetaData.setReturnValue("MySQL");
+ mockDatabaseMetaData.supportsBatchUpdates();
+ ctrlDatabaseMetaData.setReturnValue(true);
+
+ mockConnection.prepareStatement(sql);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+ mockConnection.getMetaData();
+ ctrlConnection.setReturnValue(mockDatabaseMetaData, 2);
+
+ ctrlPreparedStatement.replay();
+ ctrlDatabaseMetaData.replay();
+ replay();
+
+ BatchPreparedStatementSetter setter =
+ new InterruptibleBatchPreparedStatementSetter() {
+ public void setValues(PreparedStatement ps, int i) throws SQLException {
+ if (i < ids.length) {
+ ps.setInt(1, ids[i]);
+ }
+ }
+ public int getBatchSize() {
+ return 1000;
+ }
+ public boolean isBatchExhausted(int i) {
+ return (i >= ids.length);
+ }
+ };
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource, false);
+
+ int[] actualRowsAffected = template.batchUpdate(sql, setter);
+ assertTrue("executed 2 updates", actualRowsAffected.length == 2);
+ assertEquals(rowsAffected[0], actualRowsAffected[0]);
+ assertEquals(rowsAffected[1], actualRowsAffected[1]);
+
+ ctrlPreparedStatement.verify();
+ ctrlDatabaseMetaData.verify();
+ }
+
+ public void testInterruptibleBatchUpdateWithBaseClass() throws Exception {
+ final String sql = "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = ?";
+ final int[] ids = new int[] { 100, 200 };
+ final int[] rowsAffected = new int[] { 1, 2 };
+
+ MockControl ctrlPreparedStatement = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement mockPreparedStatement = (PreparedStatement) ctrlPreparedStatement.getMock();
+ mockPreparedStatement.getConnection();
+ ctrlPreparedStatement.setReturnValue(mockConnection);
+ mockPreparedStatement.setInt(1, ids[0]);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.addBatch();
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setInt(1, ids[1]);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.addBatch();
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeBatch();
+ ctrlPreparedStatement.setReturnValue(rowsAffected);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ MockControl ctrlDatabaseMetaData = MockControl.createControl(DatabaseMetaData.class);
+ DatabaseMetaData mockDatabaseMetaData = (DatabaseMetaData) ctrlDatabaseMetaData.getMock();
+ mockDatabaseMetaData.getDatabaseProductName();
+ ctrlDatabaseMetaData.setReturnValue("MySQL");
+ mockDatabaseMetaData.supportsBatchUpdates();
+ ctrlDatabaseMetaData.setReturnValue(true);
+
+ mockConnection.prepareStatement(sql);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+ mockConnection.getMetaData();
+ ctrlConnection.setReturnValue(mockDatabaseMetaData, 2);
+
+ ctrlPreparedStatement.replay();
+ ctrlDatabaseMetaData.replay();
+ replay();
+
+ BatchPreparedStatementSetter setter =
+ new AbstractInterruptibleBatchPreparedStatementSetter() {
+ protected boolean setValuesIfAvailable(PreparedStatement ps, int i) throws SQLException {
+ if (i < ids.length) {
+ ps.setInt(1, ids[i]);
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ };
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource, false);
+
+ int[] actualRowsAffected = template.batchUpdate(sql, setter);
+ assertTrue("executed 2 updates", actualRowsAffected.length == 2);
+ assertEquals(rowsAffected[0], actualRowsAffected[0]);
+ assertEquals(rowsAffected[1], actualRowsAffected[1]);
+
+ ctrlPreparedStatement.verify();
+ ctrlDatabaseMetaData.verify();
+ }
+
+ public void testInterruptibleBatchUpdateWithBaseClassAndNoBatchSupport() throws Exception {
+ final String sql = "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = ?";
+ final int[] ids = new int[] { 100, 200 };
+ final int[] rowsAffected = new int[] { 1, 2 };
+
+ MockControl ctrlPreparedStatement = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement mockPreparedStatement = (PreparedStatement) ctrlPreparedStatement.getMock();
+ mockPreparedStatement.getConnection();
+ ctrlPreparedStatement.setReturnValue(mockConnection);
+ mockPreparedStatement.setInt(1, ids[0]);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(rowsAffected[0]);
+ mockPreparedStatement.setInt(1, ids[1]);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(rowsAffected[1]);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ MockControl ctrlDatabaseMetaData = MockControl.createControl(DatabaseMetaData.class);
+ DatabaseMetaData mockDatabaseMetaData = (DatabaseMetaData) ctrlDatabaseMetaData.getMock();
+ mockDatabaseMetaData.getDatabaseProductName();
+ ctrlDatabaseMetaData.setReturnValue("MySQL");
+ mockDatabaseMetaData.supportsBatchUpdates();
+ ctrlDatabaseMetaData.setReturnValue(false);
+
+ mockConnection.prepareStatement(sql);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+ mockConnection.getMetaData();
+ ctrlConnection.setReturnValue(mockDatabaseMetaData, 2);
+
+ ctrlPreparedStatement.replay();
+ ctrlDatabaseMetaData.replay();
+ replay();
+
+ BatchPreparedStatementSetter setter =
+ new AbstractInterruptibleBatchPreparedStatementSetter() {
+ protected boolean setValuesIfAvailable(PreparedStatement ps, int i) throws SQLException {
+ if (i < ids.length) {
+ ps.setInt(1, ids[i]);
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ };
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource, false);
+
+ int[] actualRowsAffected = template.batchUpdate(sql, setter);
+ assertTrue("executed 2 updates", actualRowsAffected.length == 2);
+ assertEquals(rowsAffected[0], actualRowsAffected[0]);
+ assertEquals(rowsAffected[1], actualRowsAffected[1]);
+
+ ctrlPreparedStatement.verify();
+ ctrlDatabaseMetaData.verify();
+ }
+
+ public void testBatchUpdateWithPreparedStatementAndNoBatchSupport() throws Exception {
+ final String sql = "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = ?";
+ final int[] ids = new int[] { 100, 200 };
+ final int[] rowsAffected = new int[] { 1, 2 };
+
+ MockControl ctrlPreparedStatement = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement mockPreparedStatement = (PreparedStatement) ctrlPreparedStatement.getMock();
+ mockPreparedStatement.getConnection();
+ ctrlPreparedStatement.setReturnValue(mockConnection);
+ mockPreparedStatement.setInt(1, ids[0]);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(rowsAffected[0]);
+ mockPreparedStatement.setInt(1, ids[1]);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(rowsAffected[1]);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sql);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ ctrlPreparedStatement.replay();
+ replay();
+
+ BatchPreparedStatementSetter setter = new BatchPreparedStatementSetter() {
+ public void setValues(PreparedStatement ps, int i) throws SQLException {
+ ps.setInt(1, ids[i]);
+ }
+ public int getBatchSize() {
+ return ids.length;
+ }
+ };
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+
+ int[] actualRowsAffected = template.batchUpdate(sql, setter);
+ assertTrue("executed 2 updates", actualRowsAffected.length == 2);
+ assertEquals(rowsAffected[0], actualRowsAffected[0]);
+ assertEquals(rowsAffected[1], actualRowsAffected[1]);
+
+ ctrlPreparedStatement.verify();
+ }
+
+ public void testBatchUpdateFails() throws Exception {
+ final String sql = "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = ?";
+ final int[] ids = new int[] { 100, 200 };
+ SQLException sex = new SQLException();
+
+ MockControl ctrlPreparedStatement = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement mockPreparedStatement = (PreparedStatement) ctrlPreparedStatement.getMock();
+ mockPreparedStatement.getConnection();
+ ctrlPreparedStatement.setReturnValue(mockConnection);
+ mockPreparedStatement.setInt(1, ids[0]);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.addBatch();
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setInt(1, ids[1]);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.addBatch();
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeBatch();
+ ctrlPreparedStatement.setThrowable(sex);
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ MockControl ctrlDatabaseMetaData = MockControl.createControl(DatabaseMetaData.class);
+ DatabaseMetaData mockDatabaseMetaData = (DatabaseMetaData) ctrlDatabaseMetaData.getMock();
+ mockDatabaseMetaData.getDatabaseProductName();
+ ctrlDatabaseMetaData.setReturnValue("MySQL");
+ mockDatabaseMetaData.supportsBatchUpdates();
+ ctrlDatabaseMetaData.setReturnValue(true);
+
+ ctrlConnection.reset();
+ mockConnection.prepareStatement(sql);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+ mockConnection.getMetaData();
+ ctrlConnection.setReturnValue(mockDatabaseMetaData, 2);
+ mockConnection.close();
+ ctrlConnection.setVoidCallable(2);
+
+ ctrlPreparedStatement.replay();
+ ctrlDatabaseMetaData.replay();
+ replay();
+
+ BatchPreparedStatementSetter setter = new BatchPreparedStatementSetter() {
+ public void setValues(PreparedStatement ps, int i) throws SQLException {
+ ps.setInt(1, ids[i]);
+ }
+ public int getBatchSize() {
+ return ids.length;
+ }
+ };
+
+ try {
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ template.batchUpdate(sql, setter);
+ fail("Should have failed because of SQLException in bulk update");
+ }
+ catch (DataAccessException ex) {
+ assertTrue("Root cause is SQLException", ex.getCause() == sex);
+ }
+
+ ctrlPreparedStatement.verify();
+ ctrlDatabaseMetaData.verify();
+ }
+
+ public void testCouldntGetConnectionOrExceptionTranslator() throws SQLException {
+ SQLException sex = new SQLException("foo", "07xxx");
+
+ ctrlDataSource = MockControl.createControl(DataSource.class);
+ mockDataSource = (DataSource) ctrlDataSource.getMock();
+ mockDataSource.getConnection();
+ // Expect two calls (one call after caching data product name): make get metadata fail also
+ ctrlDataSource.setThrowable(sex, 2);
+ replay();
+
+ try {
+ JdbcTemplate template = new JdbcTemplate(mockDataSource, false);
+ RowCountCallbackHandler rcch = new RowCountCallbackHandler();
+ template.query("SELECT ID, FORENAME FROM CUSTMR WHERE ID < 3", rcch);
+ fail("Shouldn't have executed query without a connection");
+ }
+ catch (CannotGetJdbcConnectionException ex) {
+ // pass
+ assertTrue("Check root cause", ex.getCause() == sex);
+ }
+
+ ctrlDataSource.verify();
+ }
+
+ public void testCouldntGetConnectionForOperationOrExceptionTranslator() throws SQLException {
+ SQLException sex = new SQLException("foo", "07xxx");
+
+ // Change behavior in setUp() because we only expect one call to getConnection():
+ // none is necessary to get metadata for exception translator
+ ctrlDataSource = MockControl.createControl(DataSource.class);
+ mockDataSource = (DataSource) ctrlDataSource.getMock();
+ mockDataSource.getConnection();
+ // Expect two calls (one call after caching data product name): make get Metadata fail also
+ ctrlDataSource.setThrowable(sex, 2);
+ replay();
+
+ try {
+ JdbcTemplate template = new JdbcTemplate(mockDataSource, false);
+ RowCountCallbackHandler rcch = new RowCountCallbackHandler();
+ template.query("SELECT ID, FORENAME FROM CUSTMR WHERE ID < 3", rcch);
+ fail("Shouldn't have executed query without a connection");
+ }
+ catch (CannotGetJdbcConnectionException ex) {
+ // pass
+ assertTrue("Check root cause", ex.getCause() == sex);
+ }
+
+ ctrlDataSource.verify();
+ }
+
+ public void testCouldntGetConnectionForOperationWithLazyExceptionTranslator() throws SQLException {
+ SQLException sex = new SQLException("foo", "07xxx");
+
+ ctrlDataSource = MockControl.createControl(DataSource.class);
+ mockDataSource = (DataSource) ctrlDataSource.getMock();
+ mockDataSource.getConnection();
+ ctrlDataSource.setThrowable(sex, 1);
+ replay();
+
+ try {
+ JdbcTemplate template2 = new JdbcTemplate();
+ template2.setDataSource(mockDataSource);
+ template2.afterPropertiesSet();
+ RowCountCallbackHandler rcch = new RowCountCallbackHandler();
+ template2.query("SELECT ID, FORENAME FROM CUSTMR WHERE ID < 3", rcch);
+ fail("Shouldn't have executed query without a connection");
+ }
+ catch (CannotGetJdbcConnectionException ex) {
+ // pass
+ assertTrue("Check root cause", ex.getCause() == sex);
+ }
+
+ ctrlDataSource.verify();
+ }
+
+ /**
+ * Verify that afterPropertiesSet invokes exception translator.
+ */
+ public void testCouldntGetConnectionInOperationWithExceptionTranslatorInitialized() throws SQLException {
+ SQLException sex = new SQLException("foo", "07xxx");
+
+ ctrlDataSource = MockControl.createControl(DataSource.class);
+ mockDataSource = (DataSource) ctrlDataSource.getMock();
+ //mockConnection.getMetaData();
+ //ctrlConnection.setReturnValue(null, 1);
+ //mockConnection.close();
+ //ctrlConnection.setVoidCallable(1);
+ ctrlConnection.replay();
+
+ // Change behaviour in setUp() because we only expect one call to getConnection():
+ // none is necessary to get metadata for exception translator
+ ctrlDataSource = MockControl.createControl(DataSource.class);
+ mockDataSource = (DataSource) ctrlDataSource.getMock();
+ // Upfront call for metadata - no longer the case
+ //mockDataSource.getConnection();
+ //ctrlDataSource.setReturnValue(mockConnection, 1);
+ // One call for operation
+ mockDataSource.getConnection();
+ ctrlDataSource.setThrowable(sex, 2);
+ ctrlDataSource.replay();
+
+ try {
+ JdbcTemplate template = new JdbcTemplate(mockDataSource, false);
+ RowCountCallbackHandler rcch = new RowCountCallbackHandler();
+ template.query("SELECT ID, FORENAME FROM CUSTMR WHERE ID < 3", rcch);
+ fail("Shouldn't have executed query without a connection");
+ }
+ catch (CannotGetJdbcConnectionException ex) {
+ // pass
+ assertTrue("Check root cause", ex.getCause() == sex);
+ }
+
+ ctrlDataSource.verify();
+ ctrlConnection.verify();
+ }
+
+ public void testCouldntGetConnectionInOperationWithExceptionTranslatorInitializedViaBeanProperty()
+ throws Exception {
+ doTestCouldntGetConnectionInOperationWithExceptionTranslatorInitialized(true);
+ }
+
+ public void testCouldntGetConnectionInOperationWithExceptionTranslatorInitializedInAfterPropertiesSet()
+ throws Exception {
+ doTestCouldntGetConnectionInOperationWithExceptionTranslatorInitialized(false);
+ }
+
+ /**
+ * If beanProperty is true, initialize via exception translator bean property;
+ * if false, use afterPropertiesSet().
+ */
+ private void doTestCouldntGetConnectionInOperationWithExceptionTranslatorInitialized(boolean beanProperty)
+ throws SQLException {
+
+ SQLException sex = new SQLException("foo", "07xxx");
+
+ ctrlConnection = MockControl.createControl(Connection.class);
+ mockConnection = (Connection) ctrlConnection.getMock();
+ //mockConnection.getMetaData();
+ //ctrlConnection.setReturnValue(null, 1);
+ //mockConnection.close();
+ //ctrlConnection.setVoidCallable(1);
+ ctrlConnection.replay();
+
+ // Change behaviour in setUp() because we only expect one call to getConnection():
+ // none is necessary to get metadata for exception translator
+ ctrlDataSource = MockControl.createControl(DataSource.class);
+ mockDataSource = (DataSource) ctrlDataSource.getMock();
+ // Upfront call for metadata - no longer the case
+ //mockDataSource.getConnection();
+ //ctrlDataSource.setReturnValue(mockConnection, 1);
+ // One call for operation
+ mockDataSource.getConnection();
+ ctrlDataSource.setThrowable(sex, 2);
+ ctrlDataSource.replay();
+
+ try {
+ JdbcTemplate template2 = new JdbcTemplate();
+ template2.setDataSource(mockDataSource);
+ template2.setLazyInit(false);
+ if (beanProperty) {
+ // This will get a connection.
+ template2.setExceptionTranslator(new SQLErrorCodeSQLExceptionTranslator(mockDataSource));
+ }
+ else {
+ // This will cause creation of default SQL translator.
+ // Note that only call should be effective.
+ template2.afterPropertiesSet();
+ template2.afterPropertiesSet();
+ }
+ RowCountCallbackHandler rcch = new RowCountCallbackHandler();
+ template2.query(
+ "SELECT ID, FORENAME FROM CUSTMR WHERE ID < 3",
+ rcch);
+ fail("Shouldn't have executed query without a connection");
+ }
+ catch (CannotGetJdbcConnectionException ex) {
+ // pass
+ assertTrue("Check root cause", ex.getCause() == sex);
+ }
+
+ ctrlDataSource.verify();
+ ctrlConnection.verify();
+ }
+
+ public void testPreparedStatementSetterSucceeds() throws Exception {
+ final String sql = "UPDATE FOO SET NAME=? WHERE ID = 1";
+ final String name = "Gary";
+ int expectedRowsUpdated = 1;
+
+ MockControl ctrlPreparedStatement =
+ MockControl.createControl(PreparedStatement.class);
+ PreparedStatement mockPreparedStatement =
+ (PreparedStatement) ctrlPreparedStatement.getMock();
+ mockPreparedStatement.setString(1, name);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(expectedRowsUpdated);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sql);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ ctrlPreparedStatement.replay();
+ replay();
+
+ PreparedStatementSetter pss = new PreparedStatementSetter() {
+ public void setValues(PreparedStatement ps) throws SQLException {
+ ps.setString(1, name);
+ }
+ };
+ int actualRowsUpdated =
+ new JdbcTemplate(mockDataSource).update(sql, pss);
+ assertTrue(
+ "updated correct # of rows",
+ actualRowsUpdated == expectedRowsUpdated);
+
+ ctrlPreparedStatement.verify();
+ }
+
+ public void testPreparedStatementSetterFails() throws Exception {
+ final String sql = "UPDATE FOO SET NAME=? WHERE ID = 1";
+ final String name = "Gary";
+ SQLException sex = new SQLException();
+
+ MockControl ctrlPreparedStatement =
+ MockControl.createControl(PreparedStatement.class);
+ PreparedStatement mockPreparedStatement =
+ (PreparedStatement) ctrlPreparedStatement.getMock();
+ mockPreparedStatement.setString(1, name);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setThrowable(sex);
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sql);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ ctrlPreparedStatement.replay();
+ replay();
+
+ PreparedStatementSetter pss = new PreparedStatementSetter() {
+ public void setValues(PreparedStatement ps) throws SQLException {
+ ps.setString(1, name);
+ }
+ };
+ try {
+ new JdbcTemplate(mockDataSource).update(sql, pss);
+ fail("Should have failed with SQLException");
+ }
+ catch (DataAccessException ex) {
+ assertTrue("root cause was preserved", ex.getCause() == sex);
+ }
+
+ ctrlPreparedStatement.verify();
+ }
+
+ public void testCouldntClose() throws Exception {
+ MockControl ctrlStatement = MockControl.createControl(Statement.class);
+ Statement mockStatement = (Statement) ctrlStatement.getMock();
+ MockControl ctrlResultSet = MockControl.createControl(ResultSet.class);
+ ResultSet mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+ String sql = "SELECT ID, FORENAME FROM CUSTMR WHERE ID < 3";
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ SQLException sex = new SQLException("bar");
+ mockResultSet.close();
+ ctrlResultSet.setThrowable(sex);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setThrowable(sex);
+ mockConnection.close();
+ ctrlConnection.setThrowable(sex);
+
+ ctrlStatement.replay();
+ ctrlResultSet.replay();
+ replay();
+
+ JdbcTemplate template2 = new JdbcTemplate(mockDataSource);
+ RowCountCallbackHandler rcch = new RowCountCallbackHandler();
+ template2.query("SELECT ID, FORENAME FROM CUSTMR WHERE ID < 3", rcch);
+
+ ctrlStatement.verify();
+ ctrlResultSet.verify();
+ }
+
+ /**
+ * Mock objects allow us to produce warnings at will
+ */
+ public void testFatalWarning() throws Exception {
+ String sql = "SELECT forename from custmr";
+ SQLWarning warnings = new SQLWarning("My warning");
+
+ MockControl ctrlResultSet = MockControl.createControl(ResultSet.class);
+ ResultSet mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ MockControl ctrlStatement = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement mockStatement = (PreparedStatement) ctrlStatement.getMock();
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(warnings);
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ ctrlResultSet.replay();
+ ctrlStatement.replay();
+ replay();
+
+ JdbcTemplate t = new JdbcTemplate(mockDataSource);
+ t.setIgnoreWarnings(false);
+ try {
+ t.query(sql, new RowCallbackHandler() {
+ public void processRow(ResultSet rs) throws SQLException {
+ rs.getByte(1);
+ }
+ });
+ fail("Should have thrown exception on warning");
+ }
+ catch (SQLWarningException ex) {
+ // Pass
+ assertTrue(
+ "Root cause of warning was correct",
+ ex.getCause() == warnings);
+ }
+
+ ctrlResultSet.verify();
+ ctrlStatement.verify();
+ }
+
+ public void testIgnoredWarning() throws Exception {
+ String sql = "SELECT forename from custmr";
+ SQLWarning warnings = new SQLWarning("My warning");
+
+ MockControl ctrlResultSet = MockControl.createControl(ResultSet.class);
+ ResultSet mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ MockControl ctrlStatement =
+ MockControl.createControl(PreparedStatement.class);
+ PreparedStatement mockStatement =
+ (PreparedStatement) ctrlStatement.getMock();
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ ctrlResultSet.replay();
+ ctrlStatement.replay();
+ replay();
+
+ // Too long: truncation
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ template.setIgnoreWarnings(true);
+ template.query(sql, new RowCallbackHandler() {
+ public void processRow(ResultSet rs)
+ throws java.sql.SQLException {
+ rs.getByte(1);
+ }
+ });
+
+ ctrlResultSet.verify();
+ ctrlStatement.verify();
+ }
+
+ public void testSQLErrorCodeTranslation() throws Exception {
+ final SQLException sex = new SQLException("I have a known problem", "99999", 1054);
+ final String sql = "SELECT ID FROM CUSTOMER";
+
+ MockControl ctrlResultSet = MockControl.createControl(ResultSet.class);
+ ResultSet mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ MockControl ctrlStatement = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement mockStatement = (PreparedStatement) ctrlStatement.getMock();
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ MockControl ctrlDatabaseMetaData = MockControl.createControl(DatabaseMetaData.class);
+ DatabaseMetaData mockDatabaseMetaData = (DatabaseMetaData) ctrlDatabaseMetaData.getMock();
+ mockDatabaseMetaData.getDatabaseProductName();
+ ctrlDatabaseMetaData.setReturnValue("MySQL");
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+ mockConnection.getMetaData();
+ ctrlConnection.setReturnValue(mockDatabaseMetaData);
+
+ ctrlResultSet.replay();
+ ctrlStatement.replay();
+ ctrlDatabaseMetaData.replay();
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ try {
+ template.query(sql, new RowCallbackHandler() {
+ public void processRow(ResultSet rs) throws SQLException {
+ throw sex;
+ }
+ });
+ fail("Should have thrown BadSqlGrammarException");
+ }
+ catch (BadSqlGrammarException ex) {
+ // expected
+ assertTrue("Wanted same exception back, not " + ex, sex == ex.getCause());
+ }
+
+ ctrlResultSet.verify();
+ ctrlStatement.verify();
+ ctrlDatabaseMetaData.verify();
+ }
+
+ public void testSQLErrorCodeTranslationWithSpecifiedDbName() throws Exception {
+ final SQLException sex = new SQLException("I have a known problem", "99999", 1054);
+ final String sql = "SELECT ID FROM CUSTOMER";
+
+ MockControl ctrlResultSet = MockControl.createControl(ResultSet.class);
+ ResultSet mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ MockControl ctrlStatement = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement mockStatement = (PreparedStatement) ctrlStatement.getMock();
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ ctrlResultSet.replay();
+ ctrlStatement.replay();
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate();
+ template.setDataSource(mockDataSource);
+ template.setDatabaseProductName("MySQL");
+ template.afterPropertiesSet();
+ try {
+ template.query(sql, new RowCallbackHandler() {
+ public void processRow(ResultSet rs) throws SQLException {
+ throw sex;
+ }
+ });
+ fail("Should have thrown BadSqlGrammarException");
+ }
+ catch (BadSqlGrammarException ex) {
+ // expected
+ assertTrue("Wanted same exception back, not " + ex, sex == ex.getCause());
+ }
+
+ ctrlResultSet.verify();
+ ctrlStatement.verify();
+ }
+
+ /**
+ * Test that we see an SQLException translated using Error Code.
+ * If we provide the SQLExceptionTranslator, we shouldn't use a connection
+ * to get the metadata
+ */
+ public void testUseCustomSQLErrorCodeTranslator() throws Exception {
+ // Bad SQL state
+ final SQLException sex = new SQLException("I have a known problem", "07000", 1054);
+ final String sql = "SELECT ID FROM CUSTOMER";
+
+ MockControl ctrlResultSet = MockControl.createControl(ResultSet.class);
+ ResultSet mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ MockControl ctrlStatement = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement mockStatement = (PreparedStatement) ctrlStatement.getMock();
+ mockStatement.executeQuery(sql);
+ ctrlStatement.setReturnValue(mockResultSet);
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ // Change behaviour in setUp() because we only expect one call to getConnection():
+ // none is necessary to get metadata for exception translator
+ ctrlConnection = MockControl.createControl(Connection.class);
+ mockConnection = (Connection) ctrlConnection.getMock();
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement, 1);
+ mockConnection.close();
+ ctrlConnection.setVoidCallable(1);
+ ctrlConnection.replay();
+
+ ctrlDataSource = MockControl.createControl(DataSource.class);
+ mockDataSource = (DataSource) ctrlDataSource.getMock();
+ mockDataSource.getConnection();
+ ctrlDataSource.setReturnValue(mockConnection, 1);
+ ctrlDataSource.replay();
+ ///// end changed behaviour
+
+ ctrlResultSet.replay();
+ ctrlStatement.replay();
+
+ JdbcTemplate template = new JdbcTemplate();
+ template.setDataSource(mockDataSource);
+ // Set custom exception translator
+ template.setExceptionTranslator(new SQLStateSQLExceptionTranslator());
+ template.afterPropertiesSet();
+ try {
+ template.query(sql, new RowCallbackHandler() {
+ public void processRow(ResultSet rs)
+ throws SQLException {
+ throw sex;
+ }
+ });
+ fail("Should have thrown exception");
+ }
+ catch (BadSqlGrammarException ex) {
+ assertTrue(
+ "Wanted same exception back, not " + ex,
+ sex == ex.getCause());
+ }
+
+ ctrlResultSet.verify();
+ ctrlStatement.verify();
+
+ // We didn't call superclass replay() so we need to check these ourselves
+ ctrlDataSource.verify();
+ ctrlConnection.verify();
+ }
+
+ public void testNativeJdbcExtractorInvoked() throws Exception {
+ MockControl ctrlResultSet = MockControl.createControl(ResultSet.class);
+ final ResultSet mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable(2);
+
+ MockControl ctrlStatement = MockControl.createControl(Statement.class);
+ final Statement mockStatement = (Statement) ctrlStatement.getMock();
+ if (debugEnabled) {
+ mockStatement.getWarnings();
+ ctrlStatement.setReturnValue(null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+ MockControl ctrlStatement2 = MockControl.createControl(Statement.class);
+ final Statement mockStatement2 = (Statement) ctrlStatement2.getMock();
+ mockStatement2.executeQuery("my query");
+ ctrlStatement2.setReturnValue(mockResultSet, 1);
+
+ MockControl ctrlPreparedStatement = MockControl.createControl(PreparedStatement.class);
+ final PreparedStatement mockPreparedStatement = (PreparedStatement) ctrlPreparedStatement.getMock();
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+ MockControl ctrlPreparedStatement2 = MockControl.createControl(PreparedStatement.class);
+ final PreparedStatement mockPreparedStatement2 = (PreparedStatement) ctrlPreparedStatement2.getMock();
+ mockPreparedStatement2.executeQuery();
+ ctrlPreparedStatement2.setReturnValue(mockResultSet, 1);
+
+ MockControl ctrlReturnResultSet = MockControl.createControl(ResultSet.class);
+ final ResultSet mockReturnResultSet = (ResultSet) ctrlReturnResultSet.getMock();
+ mockReturnResultSet.next();
+ ctrlReturnResultSet.setReturnValue(false);
+ mockReturnResultSet.close();
+ ctrlReturnResultSet.setVoidCallable(2);
+
+ MockControl ctrlCallableStatement = MockControl.createControl(CallableStatement.class);
+ final CallableStatement mockCallableStatement = (CallableStatement) ctrlCallableStatement.getMock();
+ if (debugEnabled) {
+ mockCallableStatement.getWarnings();
+ ctrlCallableStatement.setReturnValue(null);
+ }
+ mockCallableStatement.close();
+ ctrlCallableStatement.setVoidCallable();
+ MockControl ctrlCallableStatement2 = MockControl.createControl(CallableStatement.class);
+ final CallableStatement mockCallableStatement2 = (CallableStatement) ctrlCallableStatement2.getMock();
+ mockCallableStatement2.execute();
+ ctrlCallableStatement2.setReturnValue(true);
+ mockCallableStatement2.getUpdateCount();
+ ctrlCallableStatement2.setReturnValue(-1);
+ mockCallableStatement2.getResultSet();
+ ctrlCallableStatement2.setReturnValue(mockReturnResultSet);
+ mockCallableStatement2.getMoreResults();
+ ctrlCallableStatement2.setReturnValue(false);
+ mockCallableStatement2.getUpdateCount();
+ ctrlCallableStatement2.setReturnValue(-1);
+
+ ctrlResultSet.replay();
+ ctrlStatement.replay();
+ ctrlStatement2.replay();
+ ctrlPreparedStatement.replay();
+ ctrlPreparedStatement2.replay();
+ ctrlReturnResultSet.replay();;
+ ctrlCallableStatement.replay();
+ ctrlCallableStatement2.replay();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement, 1);
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ template.setNativeJdbcExtractor(new NativeJdbcExtractor() {
+ public boolean isNativeConnectionNecessaryForNativeStatements() {
+ return false;
+ }
+ public boolean isNativeConnectionNecessaryForNativePreparedStatements() {
+ return false;
+ }
+ public boolean isNativeConnectionNecessaryForNativeCallableStatements() {
+ return false;
+ }
+ public Connection getNativeConnection(Connection con) {
+ return con;
+ }
+ public Connection getNativeConnectionFromStatement(Statement stmt) throws SQLException {
+ return stmt.getConnection();
+ }
+ public Statement getNativeStatement(Statement stmt) {
+ assertTrue(stmt == mockStatement);
+ return mockStatement2;
+ }
+ public PreparedStatement getNativePreparedStatement(PreparedStatement ps) {
+ assertTrue(ps == mockPreparedStatement);
+ return mockPreparedStatement2;
+ }
+ public CallableStatement getNativeCallableStatement(CallableStatement cs) {
+ assertTrue(cs == mockCallableStatement);
+ return mockCallableStatement2;
+ }
+ public ResultSet getNativeResultSet(ResultSet rs) {
+ return rs;
+ }
+ });
+
+ template.query("my query", new ResultSetExtractor() {
+ public Object extractData(ResultSet rs2) {
+ assertEquals(mockResultSet, rs2);
+ return null;
+ }
+ });
+
+ template.query(new PreparedStatementCreator() {
+ public PreparedStatement createPreparedStatement(Connection conn) {
+ return mockPreparedStatement;
+ }
+ }, new ResultSetExtractor() {
+ public Object extractData(ResultSet rs2) {
+ assertEquals(mockResultSet, rs2);
+ return null;
+ }
+ });
+
+ template.call(new CallableStatementCreator() {
+ public CallableStatement createCallableStatement(Connection con) {
+ return mockCallableStatement;
+ }
+ },
+ new ArrayList());
+
+ ctrlStatement.verify();
+ ctrlStatement2.verify();
+ ctrlPreparedStatement.verify();
+ ctrlPreparedStatement2.verify();
+ ctrlCallableStatement.verify();
+ ctrlCallableStatement2.verify();
+ }
+
+ public void testStaticResultSetClosed() throws Exception {
+ MockControl ctrlResultSet;
+ ResultSet mockResultSet;
+ MockControl ctrlStatement;
+ Statement mockStatement;
+ MockControl ctrlResultSet2;
+ ResultSet mockResultSet2;
+ MockControl ctrlPreparedStatement;
+ PreparedStatement mockPreparedStatement;
+
+ ctrlResultSet = MockControl.createControl(ResultSet.class);
+ mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ ctrlStatement = MockControl.createControl(Statement.class);
+ mockStatement = (Statement) ctrlStatement.getMock();
+ mockStatement.executeQuery("my query");
+ ctrlStatement.setReturnValue(mockResultSet);
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ ctrlResultSet2 = MockControl.createControl(ResultSet.class);
+ mockResultSet2 = (ResultSet) ctrlResultSet2.getMock();
+ mockResultSet2.close();
+ ctrlResultSet2.setVoidCallable();
+
+ ctrlPreparedStatement = MockControl.createControl(PreparedStatement.class);
+ mockPreparedStatement = (PreparedStatement) ctrlPreparedStatement.getMock();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet2);
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+ mockConnection.prepareStatement("my query");
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ ctrlResultSet.replay();
+ ctrlStatement.replay();
+ ctrlResultSet2.replay();
+ ctrlPreparedStatement.replay();
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+
+ try {
+ template.query("my query", new ResultSetExtractor() {
+ public Object extractData(ResultSet rs) {
+ throw new InvalidDataAccessApiUsageException("");
+ }
+ });
+ fail("Should have thrown InvalidDataAccessApiUsageException");
+ }
+ catch (InvalidDataAccessApiUsageException idaauex) {
+ // ok
+ }
+
+ try {
+ template.query(new PreparedStatementCreator() {
+ public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
+ return con.prepareStatement("my query");
+ }
+ public String getSql() {
+ return null;
+ }
+ }, new ResultSetExtractor() {
+ public Object extractData(ResultSet rs2) {
+ throw new InvalidDataAccessApiUsageException("");
+ }
+ });
+ fail("Should have thrown InvalidDataAccessApiUsageException");
+ }
+ catch (InvalidDataAccessApiUsageException idaauex) {
+ // ok
+ }
+
+ // verify confirms if test is successful by checking if close() called
+ ctrlResultSet.verify();
+ ctrlStatement.verify();
+ ctrlResultSet2.verify();
+ ctrlPreparedStatement.verify();
+ }
+
+ public void testExecuteClosed() throws Exception {
+ MockControl ctrlResultSet;
+ ResultSet mockResultSet;
+ MockControl ctrlCallable;
+ CallableStatement mockCallable;
+
+ ctrlResultSet = MockControl.createControl(ResultSet.class);
+ mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ ctrlCallable = MockControl.createControl(CallableStatement.class);
+ mockCallable = (CallableStatement) ctrlCallable.getMock();
+ mockCallable.execute();
+ ctrlCallable.setReturnValue(true);
+ mockCallable.getUpdateCount();
+ ctrlCallable.setReturnValue(-1);
+ mockCallable.getResultSet();
+ ctrlCallable.setReturnValue(mockResultSet);
+ mockCallable.close();
+ ctrlCallable.setVoidCallable();
+
+ mockConnection.prepareCall("my query");
+ ctrlConnection.setReturnValue(mockCallable);
+
+ ctrlResultSet.replay();
+ ctrlCallable.replay();
+ replay();
+
+ List params = new ArrayList();
+ params.add(new SqlReturnResultSet("", new RowCallbackHandler() {
+ public void processRow(ResultSet rs) {
+ throw new InvalidDataAccessApiUsageException("");
+ }
+
+ }));
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ try {
+ template.call(new CallableStatementCreator() {
+ public CallableStatement createCallableStatement(Connection conn)
+ throws SQLException {
+ return conn.prepareCall("my query");
+ }
+ }, params);
+ }
+ catch (InvalidDataAccessApiUsageException idaauex) {
+ // ok
+ }
+
+ // verify confirms if test is successful by checking if close() called
+ ctrlResultSet.verify();
+ ctrlCallable.verify();
+ }
+
+ public void testCaseInsensitiveResultsMap() throws Exception {
+
+ MockControl ctrlCallable;
+ CallableStatement mockCallable;
+
+ ctrlCallable = MockControl.createControl(CallableStatement.class);
+ mockCallable = (CallableStatement) ctrlCallable.getMock();
+ mockCallable.execute();
+ ctrlCallable.setReturnValue(false);
+ mockCallable.getUpdateCount();
+ ctrlCallable.setReturnValue(-1);
+ mockCallable.getObject(1);
+ ctrlCallable.setReturnValue("X");
+ if (debugEnabled) {
+ mockCallable.getWarnings();
+ ctrlCallable.setReturnValue(null);
+ }
+ mockCallable.close();
+ ctrlCallable.setVoidCallable();
+
+ mockConnection.prepareCall("my query");
+ ctrlConnection.setReturnValue(mockCallable);
+
+ ctrlCallable.replay();
+ replay();
+
+ JdbcTemplate template = new JdbcTemplate(mockDataSource);
+ assertTrue("default should have been NOT case insensitive", !template.isResultsMapCaseInsensitive());
+
+ template.setResultsMapCaseInsensitive(true);
+ assertTrue("now it should have been set to case insensitive", template.isResultsMapCaseInsensitive());
+
+ List params = new ArrayList();
+ params.add(new SqlOutParameter("a", 12));
+
+ Map out = template.call(new CallableStatementCreator() {
+ public CallableStatement createCallableStatement(Connection conn)
+ throws SQLException {
+ return conn.prepareCall("my query");
+ }
+ }, params);
+ assertTrue("this should have been an Apache Commons Collections class",
+ out.getClass().getName().startsWith("org.apache.commons.collections.map"));
+ assertNotNull("we should have gotten the result with upper case", out.get("A"));
+ assertNotNull("we should have gotten the result with lower case", out.get("a"));
+
+ ctrlCallable.verify();
+ }
+
+
+ private static class PlainNativeJdbcExtractor extends NativeJdbcExtractorAdapter {
+
+ protected Connection doGetNativeConnection(Connection con) throws SQLException {
+ return con;
+ }
+ }
+
+
+ private static interface JdbcTemplateCallback {
+
+ void doInJdbcTemplate(JdbcTemplate template, String sql, RowCallbackHandler rch);
+ }
+
+
+ private static class Dispatcher implements PreparedStatementCreator, SqlProvider {
+
+ private int id;
+ private String sql;
+
+ public Dispatcher(int id, String sql) {
+ this.id = id;
+ this.sql = sql;
+ }
+
+ public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {
+ PreparedStatement ps = conn.prepareStatement(sql);
+ ps.setInt(1, id);
+ return ps;
+ }
+
+ public String getSql() {
+ return sql;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/RowMapperTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/RowMapperTests.java
new file mode 100644
index 00000000000..bd992919cb2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/RowMapperTests.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.core;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Types;
+import java.util.List;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.beans.TestBean;
+import org.springframework.jdbc.datasource.SingleConnectionDataSource;
+import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
+
+/**
+ * @author Juergen Hoeller
+ * @since 02.08.2004
+ */
+public class RowMapperTests extends TestCase {
+
+ private final boolean debugEnabled = LogFactory.getLog(JdbcTemplate.class).isDebugEnabled();
+
+ private MockControl conControl;
+ private Connection con;
+ private MockControl rsControl;
+ private ResultSet rs;
+ private JdbcTemplate jdbcTemplate;
+ private List result;
+
+ protected void setUp() throws SQLException {
+ conControl = MockControl.createControl(Connection.class);
+ con = (Connection) conControl.getMock();
+ con.isClosed();
+ conControl.setDefaultReturnValue(false);
+
+ rsControl = MockControl.createControl(ResultSet.class);
+ rs = (ResultSet) rsControl.getMock();
+ rs.next();
+ rsControl.setReturnValue(true, 1);
+ rs.getString(1);
+ rsControl.setReturnValue("tb1", 1);
+ rs.getInt(2);
+ rsControl.setReturnValue(1, 1);
+ rs.next();
+ rsControl.setReturnValue(true, 1);
+ rs.getString(1);
+ rsControl.setReturnValue("tb2", 1);
+ rs.getInt(2);
+ rsControl.setReturnValue(2, 1);
+ rs.next();
+ rsControl.setReturnValue(false, 1);
+ rs.close();
+ rsControl.setVoidCallable(1);
+ rsControl.replay();
+
+ jdbcTemplate = new JdbcTemplate();
+ jdbcTemplate.setDataSource(new SingleConnectionDataSource(con, false));
+ jdbcTemplate.setExceptionTranslator(new SQLStateSQLExceptionTranslator());
+ jdbcTemplate.afterPropertiesSet();
+ }
+
+ public void testStaticQueryWithRowMapper() throws SQLException {
+ MockControl stmtControl = MockControl.createControl(Statement.class);
+ Statement stmt = (Statement) stmtControl.getMock();
+
+ con.createStatement();
+ conControl.setReturnValue(stmt, 1);
+ stmt.executeQuery("some SQL");
+ stmtControl.setReturnValue(rs, 1);
+ if (debugEnabled) {
+ stmt.getWarnings();
+ stmtControl.setReturnValue(null, 1);
+ }
+ stmt.close();
+ stmtControl.setVoidCallable(1);
+
+ conControl.replay();
+ stmtControl.replay();
+
+ result = jdbcTemplate.query("some SQL", new TestRowMapper());
+
+ stmtControl.verify();
+ verify();
+ }
+
+ public void testPreparedStatementCreatorWithRowMapper() throws SQLException {
+ MockControl psControl = MockControl.createControl(PreparedStatement.class);
+ final PreparedStatement ps = (PreparedStatement) psControl.getMock();
+
+ ps.executeQuery();
+ psControl.setReturnValue(rs, 1);
+ if (debugEnabled) {
+ ps.getWarnings();
+ psControl.setReturnValue(null, 1);
+ }
+ ps.close();
+ psControl.setVoidCallable(1);
+
+ conControl.replay();
+ psControl.replay();
+
+ result = jdbcTemplate.query(
+ new PreparedStatementCreator() {
+ public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
+ return ps;
+ }
+ }, new TestRowMapper());
+
+ psControl.verify();
+ verify();
+ }
+
+ public void testPreparedStatementSetterWithRowMapper() throws SQLException {
+ MockControl psControl = MockControl.createControl(PreparedStatement.class);
+ final PreparedStatement ps = (PreparedStatement) psControl.getMock();
+
+ con.prepareStatement("some SQL");
+ conControl.setReturnValue(ps, 1);
+ ps.setString(1, "test");
+ psControl.setVoidCallable(1);
+ ps.executeQuery();
+ psControl.setReturnValue(rs, 1);
+ if (debugEnabled) {
+ ps.getWarnings();
+ psControl.setReturnValue(null, 1);
+ }
+ ps.close();
+ psControl.setVoidCallable(1);
+
+ conControl.replay();
+ psControl.replay();
+
+ result = jdbcTemplate.query(
+ "some SQL",
+ new PreparedStatementSetter() {
+ public void setValues(PreparedStatement ps) throws SQLException {
+ ps.setString(1, "test");
+ }
+ }, new TestRowMapper());
+
+ psControl.verify();
+ verify();
+ }
+
+ public void testQueryWithArgsAndRowMapper() throws SQLException {
+ MockControl psControl = MockControl.createControl(PreparedStatement.class);
+ final PreparedStatement ps = (PreparedStatement) psControl.getMock();
+
+ con.prepareStatement("some SQL");
+ conControl.setReturnValue(ps, 1);
+ ps.setString(1, "test1");
+ ps.setString(2, "test2");
+ psControl.setVoidCallable(1);
+ ps.executeQuery();
+ psControl.setReturnValue(rs, 1);
+ if (debugEnabled) {
+ ps.getWarnings();
+ psControl.setReturnValue(null, 1);
+ }
+ ps.close();
+ psControl.setVoidCallable(1);
+
+ conControl.replay();
+ psControl.replay();
+
+ result = jdbcTemplate.query(
+ "some SQL",
+ new Object[] {"test1", "test2"},
+ new TestRowMapper());
+
+ psControl.verify();
+ verify();
+ }
+
+ public void testQueryWithArgsAndTypesAndRowMapper() throws SQLException {
+ MockControl psControl = MockControl.createControl(PreparedStatement.class);
+ final PreparedStatement ps = (PreparedStatement) psControl.getMock();
+
+ con.prepareStatement("some SQL");
+ conControl.setReturnValue(ps, 1);
+ ps.setString(1, "test1");
+ ps.setString(2, "test2");
+ psControl.setVoidCallable(1);
+ ps.executeQuery();
+ psControl.setReturnValue(rs, 1);
+ if (debugEnabled) {
+ ps.getWarnings();
+ psControl.setReturnValue(null, 1);
+ }
+ ps.close();
+ psControl.setVoidCallable(1);
+
+ conControl.replay();
+ psControl.replay();
+
+ result = jdbcTemplate.query(
+ "some SQL",
+ new Object[] {"test1", "test2"},
+ new int[] {Types.VARCHAR, Types.VARCHAR},
+ new TestRowMapper());
+
+ psControl.verify();
+ verify();
+ }
+
+ protected void verify() {
+ conControl.verify();
+ rsControl.verify();
+
+ assertTrue(result != null);
+ assertEquals(2, result.size());
+ TestBean tb1 = (TestBean) result.get(0);
+ TestBean tb2 = (TestBean) result.get(1);
+ assertEquals("tb1", tb1.getName());
+ assertEquals(1, tb1.getAge());
+ assertEquals("tb2", tb2.getName());
+ assertEquals(2, tb2.getAge());
+ }
+
+
+ private static class TestRowMapper implements RowMapper {
+
+ public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
+ return new TestBean(rs.getString(1), rs.getInt(2));
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/SimpleRowCountCallbackHandler.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/SimpleRowCountCallbackHandler.java
new file mode 100644
index 00000000000..ae4d9737026
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/SimpleRowCountCallbackHandler.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jdbc.core;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * Simple row count callback handler for testing purposes.
+ * Does not call any JDBC methods on the given ResultSet.
+ *
+ * @author Juergen Hoeller
+ * @since 2.0
+ */
+public class SimpleRowCountCallbackHandler implements RowCallbackHandler {
+
+ private int count;
+
+
+ public void processRow(ResultSet rs) throws SQLException {
+ count++;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/StatementCreatorUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/StatementCreatorUtilsTests.java
new file mode 100644
index 00000000000..17292869391
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/StatementCreatorUtilsTests.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.core;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.GregorianCalendar;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+/**
+ * @author Juergen Hoeller
+ * @since 31.08.2004
+ */
+public class StatementCreatorUtilsTests extends TestCase {
+
+ private MockControl psControl;
+ private PreparedStatement ps;
+
+ protected void setUp() {
+ psControl = MockControl.createControl(PreparedStatement.class);
+ ps = (PreparedStatement) psControl.getMock();
+ }
+
+ protected void tearDown() {
+ psControl.verify();
+ }
+
+ public void testSetParameterValueWithNullAndType() throws SQLException {
+ ps.setNull(1, Types.VARCHAR);
+ psControl.setVoidCallable(1);
+ psControl.replay();
+ StatementCreatorUtils.setParameterValue(ps, 1, Types.VARCHAR, null, null);
+ }
+
+ public void testSetParameterValueWithNullAndTypeName() throws SQLException {
+ ps.setNull(1, Types.VARCHAR, "mytype");
+ psControl.setVoidCallable(1);
+ psControl.replay();
+ StatementCreatorUtils.setParameterValue(ps, 1, Types.VARCHAR, "mytype", null);
+ }
+
+ public void testSetParameterValueWithNullAndUnknownType() throws SQLException {
+ ps.setNull(1, Types.NULL);
+ psControl.setVoidCallable(1);
+ psControl.replay();
+ StatementCreatorUtils.setParameterValue(ps, 1, SqlTypeValue.TYPE_UNKNOWN, null, null);
+ }
+
+ public void testSetParameterValueWithNullAndUnknownTypeOnInformix() throws SQLException {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl metaDataControl = MockControl.createControl(DatabaseMetaData.class);
+ DatabaseMetaData metaData = (DatabaseMetaData) metaDataControl.getMock();
+ ps.getConnection();
+ psControl.setReturnValue(con, 1);
+ con.getMetaData();
+ conControl.setReturnValue(metaData, 1);
+ metaData.getDatabaseProductName();
+ metaDataControl.setReturnValue("Informix Dynamic Server");
+ metaData.getDriverName();
+ metaDataControl.setReturnValue("Informix Driver");
+ ps.setObject(1, null);
+ psControl.setVoidCallable(1);
+ psControl.replay();
+ conControl.replay();
+ metaDataControl.replay();
+ StatementCreatorUtils.setParameterValue(ps, 1, SqlTypeValue.TYPE_UNKNOWN, null, null);
+ conControl.verify();
+ metaDataControl.verify();
+ }
+
+ public void testSetParameterValueWithNullAndUnknownTypeOnDerbyEmbedded() throws SQLException {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl metaDataControl = MockControl.createControl(DatabaseMetaData.class);
+ DatabaseMetaData metaData = (DatabaseMetaData) metaDataControl.getMock();
+ ps.getConnection();
+ psControl.setReturnValue(con, 1);
+ con.getMetaData();
+ conControl.setReturnValue(metaData, 1);
+ metaData.getDatabaseProductName();
+ metaDataControl.setReturnValue("Apache Derby");
+ metaData.getDriverName();
+ metaDataControl.setReturnValue("Apache Derby Embedded Driver");
+ ps.setNull(1, Types.VARCHAR);
+ psControl.setVoidCallable(1);
+ psControl.replay();
+ conControl.replay();
+ metaDataControl.replay();
+ StatementCreatorUtils.setParameterValue(ps, 1, SqlTypeValue.TYPE_UNKNOWN, null, null);
+ conControl.verify();
+ metaDataControl.verify();
+ }
+
+ public void testSetParameterValueWithString() throws SQLException {
+ ps.setString(1, "test");
+ psControl.setVoidCallable(1);
+ psControl.replay();
+ StatementCreatorUtils.setParameterValue(ps, 1, Types.VARCHAR, null, "test");
+ }
+
+ public void testSetParameterValueWithStringAndSpecialType() throws SQLException {
+ ps.setObject(1, "test", Types.CHAR);
+ psControl.setVoidCallable(1);
+ psControl.replay();
+ StatementCreatorUtils.setParameterValue(ps, 1, Types.CHAR, null, "test");
+ }
+
+ public void testSetParameterValueWithStringAndUnknownType() throws SQLException {
+ ps.setString(1, "test");
+ psControl.setVoidCallable(1);
+ psControl.replay();
+ StatementCreatorUtils.setParameterValue(ps, 1, SqlTypeValue.TYPE_UNKNOWN, null, "test");
+ }
+
+ public void testSetParameterValueWithSqlDate() throws SQLException {
+ java.sql.Date date = new java.sql.Date(1000);
+ ps.setDate(1, date);
+ psControl.setVoidCallable(1);
+ psControl.replay();
+ StatementCreatorUtils.setParameterValue(ps, 1, Types.DATE, null, date);
+ }
+
+ public void testSetParameterValueWithDateAndUtilDate() throws SQLException {
+ java.util.Date date = new java.util.Date(1000);
+ ps.setDate(1, new java.sql.Date(1000));
+ psControl.setVoidCallable(1);
+ psControl.replay();
+ StatementCreatorUtils.setParameterValue(ps, 1, Types.DATE, null, date);
+ }
+
+ public void testSetParameterValueWithDateAndCalendar() throws SQLException {
+ java.util.Calendar cal = new GregorianCalendar();
+ ps.setDate(1, new java.sql.Date(cal.getTime().getTime()), cal);
+ psControl.setVoidCallable(1);
+ psControl.replay();
+ StatementCreatorUtils.setParameterValue(ps, 1, Types.DATE, null, cal);
+ }
+
+ public void testSetParameterValueWithSqlTime() throws SQLException {
+ java.sql.Time time = new java.sql.Time(1000);
+ ps.setTime(1, time);
+ psControl.setVoidCallable(1);
+ psControl.replay();
+ StatementCreatorUtils.setParameterValue(ps, 1, Types.TIME, null, time);
+ }
+
+ public void testSetParameterValueWithTimeAndUtilDate() throws SQLException {
+ java.util.Date date = new java.util.Date(1000);
+ ps.setTime(1, new java.sql.Time(1000));
+ psControl.setVoidCallable(1);
+ psControl.replay();
+ StatementCreatorUtils.setParameterValue(ps, 1, Types.TIME, null, date);
+ }
+
+ public void testSetParameterValueWithTimeAndCalendar() throws SQLException {
+ java.util.Calendar cal = new GregorianCalendar();
+ ps.setTime(1, new java.sql.Time(cal.getTime().getTime()), cal);
+ psControl.setVoidCallable(1);
+ psControl.replay();
+ StatementCreatorUtils.setParameterValue(ps, 1, Types.TIME, null, cal);
+ }
+
+ public void testSetParameterValueWithSqlTimestamp() throws SQLException {
+ java.sql.Timestamp timestamp = new java.sql.Timestamp(1000);
+ ps.setTimestamp(1, timestamp);
+ psControl.setVoidCallable(1);
+ psControl.replay();
+ StatementCreatorUtils.setParameterValue(ps, 1, Types.TIMESTAMP, null, timestamp);
+ }
+
+ public void testSetParameterValueWithTimestampAndUtilDate() throws SQLException {
+ java.util.Date date = new java.util.Date(1000);
+ ps.setTimestamp(1, new java.sql.Timestamp(1000));
+ psControl.setVoidCallable(1);
+ psControl.replay();
+ StatementCreatorUtils.setParameterValue(ps, 1, Types.TIMESTAMP, null, date);
+ }
+
+ public void testSetParameterValueWithTimestampAndCalendar() throws SQLException {
+ java.util.Calendar cal = new GregorianCalendar();
+ ps.setTimestamp(1, new java.sql.Timestamp(cal.getTime().getTime()), cal);
+ psControl.setVoidCallable(1);
+ psControl.replay();
+ StatementCreatorUtils.setParameterValue(ps, 1, Types.TIMESTAMP, null, cal);
+ }
+
+ public void testSetParameterValueWithDateAndUnknownType() throws SQLException {
+ java.util.Date date = new java.util.Date(1000);
+ ps.setTimestamp(1, new java.sql.Timestamp(1000));
+ psControl.setVoidCallable(1);
+ psControl.replay();
+ StatementCreatorUtils.setParameterValue(ps, 1, SqlTypeValue.TYPE_UNKNOWN, null, date);
+ }
+
+ public void testSetParameterValueWithCalendarAndUnknownType() throws SQLException {
+ java.util.Calendar cal = new GregorianCalendar();
+ ps.setTimestamp(1, new java.sql.Timestamp(cal.getTime().getTime()), cal);
+ psControl.setVoidCallable(1);
+ psControl.replay();
+ StatementCreatorUtils.setParameterValue(ps, 1, SqlTypeValue.TYPE_UNKNOWN, null, cal);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/namedparam/BeanPropertySqlParameterSourceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/namedparam/BeanPropertySqlParameterSourceTests.java
new file mode 100644
index 00000000000..d5644769793
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/namedparam/BeanPropertySqlParameterSourceTests.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.core.namedparam;
+
+import java.sql.Types;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class BeanPropertySqlParameterSourceTests extends TestCase {
+
+ public void testWithNullBeanPassedToCtor() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new BeanPropertySqlParameterSource(null);
+ }
+ }.runTest();
+ }
+
+ public void testGetValueWhereTheUnderlyingBeanHasNoSuchProperty() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ BeanPropertySqlParameterSource source = new BeanPropertySqlParameterSource(new TestBean());
+ source.getValue("thisPropertyDoesNotExist");
+ }
+ }.runTest();
+ }
+
+ public void testSuccessfulPropertyAccess(){
+ BeanPropertySqlParameterSource source = new BeanPropertySqlParameterSource(new TestBean("tb", 99));
+ assertTrue(Arrays.asList(source.getReadablePropertyNames()).contains("name"));
+ assertTrue(Arrays.asList(source.getReadablePropertyNames()).contains("age"));
+ assertEquals("tb", source.getValue("name"));
+ assertEquals(new Integer(99), source.getValue("age"));
+ assertEquals(Types.VARCHAR, source.getSqlType("name"));
+ assertEquals(Types.INTEGER, source.getSqlType("age"));
+ }
+
+ public void testSuccessfulPropertyAccessWithOverriddenSqlType(){
+ BeanPropertySqlParameterSource source = new BeanPropertySqlParameterSource(new TestBean("tb", 99));
+ source.registerSqlType("age", Types.NUMERIC);
+ assertEquals("tb", source.getValue("name"));
+ assertEquals(new Integer(99), source.getValue("age"));
+ assertEquals(Types.VARCHAR, source.getSqlType("name"));
+ assertEquals(Types.NUMERIC, source.getSqlType("age"));
+ }
+
+ public void testHasValueWhereTheUnderlyingBeanHasNoSuchProperty() throws Exception {
+ BeanPropertySqlParameterSource source = new BeanPropertySqlParameterSource(new TestBean());
+ assertFalse(source.hasValue("thisPropertyDoesNotExist"));
+ }
+
+ public void testGetValueWhereTheUnderlyingBeanPropertyIsNotReadable() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ BeanPropertySqlParameterSource source = new BeanPropertySqlParameterSource(new NoReadableProperties());
+ source.getValue("noOp");
+ }
+ }.runTest();
+ }
+
+ public void testHasValueWhereTheUnderlyingBeanPropertyIsNotReadable() throws Exception {
+ BeanPropertySqlParameterSource source = new BeanPropertySqlParameterSource(new NoReadableProperties());
+ assertFalse(source.hasValue("noOp"));
+ }
+
+
+ private static final class NoReadableProperties {
+
+ public void setNoOp(String noOp) {
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/namedparam/MapSqlParameterSourceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/namedparam/MapSqlParameterSourceTests.java
new file mode 100644
index 00000000000..707c20447ef
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/namedparam/MapSqlParameterSourceTests.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jdbc.core.namedparam;
+
+import junit.framework.TestCase;
+
+import org.springframework.test.AssertThrows;
+import org.springframework.jdbc.core.SqlParameterValue;
+
+/**
+ * @author Rick Evans
+ */
+public final class MapSqlParameterSourceTests extends TestCase {
+
+ public void testNullParameterValuesPassedToCtorIsOk() throws Exception {
+ new MapSqlParameterSource(null);
+ }
+
+ public void testGetValueChokesIfParameterIsNotPresent() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ MapSqlParameterSource source = new MapSqlParameterSource();
+ source.getValue("pechorin was right!");
+ }
+ }.runTest();
+ }
+
+ public void testSqlParameterValueRegistersSqlType() throws Exception {
+ MapSqlParameterSource msps = new MapSqlParameterSource("FOO", new SqlParameterValue(2, "Foo"));
+ assertEquals("Correct SQL Type not registered", 2, msps.getSqlType("FOO"));
+ MapSqlParameterSource msps2 = new MapSqlParameterSource();
+ msps2.addValues(msps.getValues());
+ assertEquals("Correct SQL Type not registered", 2, msps2.getSqlType("FOO"));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplateTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplateTests.java
new file mode 100644
index 00000000000..b2b6f0f73d4
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplateTests.java
@@ -0,0 +1,415 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.core.namedparam;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.sql.DataSource;
+
+import org.easymock.MockControl;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.dao.DataAccessException;
+import org.springframework.jdbc.AbstractJdbcTests;
+import org.springframework.jdbc.Customer;
+import org.springframework.jdbc.core.JdbcOperations;
+import org.springframework.jdbc.core.PreparedStatementCallback;
+import org.springframework.jdbc.core.ResultSetExtractor;
+import org.springframework.jdbc.core.RowCallbackHandler;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.SqlParameterValue;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class NamedParameterJdbcTemplateTests extends AbstractJdbcTests {
+
+ private static final String SELECT_NAMED_PARAMETERS =
+ "select id, forename from custmr where id = :id and country = :country";
+ private static final String SELECT_NAMED_PARAMETERS_PARSED =
+ "select id, forename from custmr where id = ? and country = ?";
+
+ private static final String UPDATE_NAMED_PARAMETERS =
+ "update seat_status set booking_id = null where performance_id = :perfId and price_band_id = :priceId";
+ private static final String UPDATE_NAMED_PARAMETERS_PARSED =
+ "update seat_status set booking_id = null where performance_id = ? and price_band_id = ?";
+
+ private static final String[] COLUMN_NAMES = new String[] {"id", "forename"};
+
+ private final boolean debugEnabled = LogFactory.getLog(JdbcTemplate.class).isDebugEnabled();
+
+ private MockControl ctrlPreparedStatement;
+ private PreparedStatement mockPreparedStatement;
+ private MockControl ctrlResultSet;
+ private ResultSet mockResultSet;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ ctrlPreparedStatement = MockControl.createControl(PreparedStatement.class);
+ mockPreparedStatement = (PreparedStatement) ctrlPreparedStatement.getMock();
+ ctrlResultSet = MockControl.createControl(ResultSet.class);
+ mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ if (shouldVerify()) {
+ ctrlPreparedStatement.verify();
+ ctrlResultSet.verify();
+ }
+ }
+
+ protected void replay() {
+ super.replay();
+ ctrlPreparedStatement.replay();
+ ctrlResultSet.replay();
+ }
+
+
+ public void testNullDataSourceProvidedToCtor() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new NamedParameterJdbcTemplate((DataSource) null);
+ }
+ }.runTest();
+ }
+
+ public void testNullJdbcTemplateProvidedToCtor() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new NamedParameterJdbcTemplate((JdbcOperations) null);
+ }
+ }.runTest();
+ }
+
+ public void testExecute() throws SQLException {
+ mockPreparedStatement.setObject(1, new Integer(1));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setObject(2, new Integer(1));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(1);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(UPDATE_NAMED_PARAMETERS_PARSED);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ NamedParameterJdbcTemplate jt = new NamedParameterJdbcTemplate(mockDataSource);
+ Map params = new HashMap();
+ params.put("perfId", new Integer(1));
+ params.put("priceId", new Integer(1));
+ assertEquals("result", jt.execute(UPDATE_NAMED_PARAMETERS, params, new PreparedStatementCallback() {
+ public Object doInPreparedStatement(PreparedStatement ps) throws SQLException {
+ assertEquals(mockPreparedStatement, ps);
+ ps.executeUpdate();
+ return "result";
+ }
+ }));
+ }
+
+ public void testExecuteWithTypedParameters() throws SQLException {
+ mockPreparedStatement.setObject(1, new Integer(1), Types.DECIMAL);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setObject(2, new Integer(1), Types.INTEGER);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(1);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(UPDATE_NAMED_PARAMETERS_PARSED);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ NamedParameterJdbcTemplate jt = new NamedParameterJdbcTemplate(mockDataSource);
+ Map params = new HashMap();
+ params.put("perfId", new SqlParameterValue(Types.DECIMAL, new Integer(1)));
+ params.put("priceId", new SqlParameterValue(Types.INTEGER, new Integer(1)));
+ assertEquals("result", jt.execute(UPDATE_NAMED_PARAMETERS, params, new PreparedStatementCallback() {
+ public Object doInPreparedStatement(PreparedStatement ps) throws SQLException {
+ assertEquals(mockPreparedStatement, ps);
+ ps.executeUpdate();
+ return "result";
+ }
+ }));
+ }
+
+ public void testUpdate() throws SQLException {
+ mockPreparedStatement.setObject(1, new Integer(1));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setObject(2, new Integer(1));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(1);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(UPDATE_NAMED_PARAMETERS_PARSED);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ NamedParameterJdbcTemplate jt = new NamedParameterJdbcTemplate(mockDataSource);
+ Map params = new HashMap();
+ params.put("perfId", new Integer(1));
+ params.put("priceId", new Integer(1));
+ int rowsAffected = jt.update(UPDATE_NAMED_PARAMETERS, params);
+ assertEquals(1, rowsAffected);
+ }
+
+ public void testUpdateWithTypedParameters() throws SQLException {
+ mockPreparedStatement.setObject(1, new Integer(1), Types.DECIMAL);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setObject(2, new Integer(1), Types.INTEGER);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(1);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(UPDATE_NAMED_PARAMETERS_PARSED);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ NamedParameterJdbcTemplate jt = new NamedParameterJdbcTemplate(mockDataSource);
+ Map params = new HashMap();
+ params.put("perfId", new SqlParameterValue(Types.DECIMAL, new Integer(1)));
+ params.put("priceId", new SqlParameterValue(Types.INTEGER, new Integer(1)));
+ int rowsAffected = jt.update(UPDATE_NAMED_PARAMETERS, params);
+ assertEquals(1, rowsAffected);
+ }
+
+ public void testQueryWithResultSetExtractor() throws SQLException {
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt("id");
+ ctrlResultSet.setReturnValue(1);
+ mockResultSet.getString("forename");
+ ctrlResultSet.setReturnValue("rod");
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(1), Types.DECIMAL);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setString(2, "UK");
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(SELECT_NAMED_PARAMETERS_PARSED);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ NamedParameterJdbcTemplate jt = new NamedParameterJdbcTemplate(mockDataSource);
+ Map params = new HashMap();
+ params.put("id", new SqlParameterValue(Types.DECIMAL, new Integer(1)));
+ params.put("country", "UK");
+ Customer cust = (Customer) jt.query(SELECT_NAMED_PARAMETERS, params, new ResultSetExtractor() {
+ public Object extractData(ResultSet rs) throws SQLException, DataAccessException {
+ rs.next();
+ Customer cust = new Customer();
+ cust.setId(rs.getInt(COLUMN_NAMES[0]));
+ cust.setForename(rs.getString(COLUMN_NAMES[1]));
+ return cust;
+ }
+ });
+ assertTrue("Customer id was assigned correctly", cust.getId() == 1);
+ assertTrue("Customer forename was assigned correctly", cust.getForename().equals("rod"));
+ }
+
+ public void testQueryWithRowCallbackHandler() throws SQLException {
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt("id");
+ ctrlResultSet.setReturnValue(1);
+ mockResultSet.getString("forename");
+ ctrlResultSet.setReturnValue("rod");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(1), Types.DECIMAL);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setString(2, "UK");
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(SELECT_NAMED_PARAMETERS_PARSED);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ NamedParameterJdbcTemplate jt = new NamedParameterJdbcTemplate(mockDataSource);
+ Map params = new HashMap();
+ params.put("id", new SqlParameterValue(Types.DECIMAL, new Integer(1)));
+ params.put("country", "UK");
+ final List customers = new LinkedList();
+ jt.query(SELECT_NAMED_PARAMETERS, params, new RowCallbackHandler() {
+ public void processRow(ResultSet rs) throws SQLException {
+ Customer cust = new Customer();
+ cust.setId(rs.getInt(COLUMN_NAMES[0]));
+ cust.setForename(rs.getString(COLUMN_NAMES[1]));
+ customers.add(cust);
+ }
+ });
+ assertEquals(1, customers.size());
+ Customer cust = (Customer) customers.get(0);
+ assertTrue("Customer id was assigned correctly", cust.getId() == 1);
+ assertTrue("Customer forename was assigned correctly", cust.getForename().equals("rod"));
+ }
+
+ public void testQueryWithRowMapper() throws SQLException {
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt("id");
+ ctrlResultSet.setReturnValue(1);
+ mockResultSet.getString("forename");
+ ctrlResultSet.setReturnValue("rod");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(1), Types.DECIMAL);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setString(2, "UK");
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(SELECT_NAMED_PARAMETERS_PARSED);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ NamedParameterJdbcTemplate jt = new NamedParameterJdbcTemplate(mockDataSource);
+ Map params = new HashMap();
+ params.put("id", new SqlParameterValue(Types.DECIMAL, new Integer(1)));
+ params.put("country", "UK");
+ List customers = jt.query(SELECT_NAMED_PARAMETERS, params, new RowMapper() {
+ public Object mapRow(ResultSet rs, int rownum) throws SQLException {
+ Customer cust = new Customer();
+ cust.setId(rs.getInt(COLUMN_NAMES[0]));
+ cust.setForename(rs.getString(COLUMN_NAMES[1]));
+ return cust;
+ }
+ });
+ assertEquals(1, customers.size());
+ Customer cust = (Customer) customers.get(0);
+ assertTrue("Customer id was assigned correctly", cust.getId() == 1);
+ assertTrue("Customer forename was assigned correctly", cust.getForename().equals("rod"));
+ }
+
+ public void testQueryForObjectWithRowMapper() throws SQLException {
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt("id");
+ ctrlResultSet.setReturnValue(1);
+ mockResultSet.getString("forename");
+ ctrlResultSet.setReturnValue("rod");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(1), Types.DECIMAL);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setString(2, "UK");
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(SELECT_NAMED_PARAMETERS_PARSED);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ NamedParameterJdbcTemplate jt = new NamedParameterJdbcTemplate(mockDataSource);
+ Map params = new HashMap();
+ params.put("id", new SqlParameterValue(Types.DECIMAL, new Integer(1)));
+ params.put("country", "UK");
+ Customer cust = (Customer) jt.queryForObject(SELECT_NAMED_PARAMETERS, params, new RowMapper() {
+ public Object mapRow(ResultSet rs, int rownum) throws SQLException {
+ Customer cust = new Customer();
+ cust.setId(rs.getInt(COLUMN_NAMES[0]));
+ cust.setForename(rs.getString(COLUMN_NAMES[1]));
+ return cust;
+ }
+ });
+ assertTrue("Customer id was assigned correctly", cust.getId() == 1);
+ assertTrue("Customer forename was assigned correctly", cust.getForename().equals("rod"));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterQueryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterQueryTests.java
new file mode 100644
index 00000000000..67dadc84a2a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterQueryTests.java
@@ -0,0 +1,608 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.core.namedparam;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.easymock.MockControl;
+
+import org.springframework.jdbc.AbstractJdbcTests;
+import org.springframework.jdbc.core.RowMapper;
+
+/**
+ * @author Thomas Risberg
+ */
+public class NamedParameterQueryTests extends AbstractJdbcTests {
+
+ private MockControl ctrlPreparedStatement;
+ private PreparedStatement mockPreparedStatement;
+ private MockControl ctrlResultSet;
+ private ResultSet mockResultSet;
+ private MockControl ctrlResultSetMetaData;
+ private ResultSetMetaData mockResultSetMetaData;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ ctrlPreparedStatement = MockControl.createControl(PreparedStatement.class);
+ mockPreparedStatement = (PreparedStatement) ctrlPreparedStatement.getMock();
+ ctrlResultSet = MockControl.createControl(ResultSet.class);
+ mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ ctrlResultSetMetaData = MockControl.createControl(ResultSetMetaData.class);
+ mockResultSetMetaData = (ResultSetMetaData) ctrlResultSetMetaData.getMock();
+ }
+
+ protected void replay() {
+ super.replay();
+ ctrlPreparedStatement.replay();
+ ctrlResultSet.replay();
+ ctrlResultSetMetaData.replay();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ if (false && shouldVerify()) {
+ ctrlPreparedStatement.verify();
+ ctrlResultSet.verify();
+ ctrlResultSetMetaData.verify();
+ }
+ }
+
+ public void testQueryForListWithParamMap() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID < :id";
+ String sqlToUse = "SELECT AGE FROM CUSTMR WHERE ID < ?";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1, 2);
+ mockResultSetMetaData.getColumnLabel(1);
+ ctrlResultSetMetaData.setReturnValue("age", 2);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData, 2);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getObject(1);
+ ctrlResultSet.setReturnValue(new Integer(11));
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getObject(1);
+ ctrlResultSet.setReturnValue(new Integer(12));
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(3));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sqlToUse);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(mockDataSource);
+
+ MapSqlParameterSource parms = new MapSqlParameterSource();
+ parms.addValue("id", new Integer(3));
+
+ List li = template.queryForList(sql, parms);
+ assertEquals("All rows returned", 2, li.size());
+ assertEquals("First row is Integer", 11, ((Integer)((Map)li.get(0)).get("age")).intValue());
+ assertEquals("Second row is Integer", 12, ((Integer)((Map)li.get(1)).get("age")).intValue());
+ }
+
+ public void testQueryForListWithParamMapAndEmptyResult() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID < :id";
+ String sqlToUse = "SELECT AGE FROM CUSTMR WHERE ID < ?";
+
+ ctrlResultSet = MockControl.createControl(ResultSet.class);
+ mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(3));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sqlToUse);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(mockDataSource);
+
+ MapSqlParameterSource parms = new MapSqlParameterSource();
+ parms.addValue("id", new Integer(3));
+
+ List li = template.queryForList(sql, parms);
+ assertEquals("All rows returned", 0, li.size());
+ }
+
+ public void testQueryForListWithParamMapAndSingleRowAndColumn() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID < :id";
+ String sqlToUse = "SELECT AGE FROM CUSTMR WHERE ID < ?";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+ mockResultSetMetaData.getColumnLabel(1);
+ ctrlResultSetMetaData.setReturnValue("age", 1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getObject(1);
+ ctrlResultSet.setReturnValue(new Integer(11));
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(3));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sqlToUse);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(mockDataSource);
+
+ MapSqlParameterSource parms = new MapSqlParameterSource();
+ parms.addValue("id", new Integer(3));
+
+ List li = template.queryForList(sql, parms);
+ assertEquals("All rows returned", 1, li.size());
+ assertEquals("First row is Integer", 11, ((Integer)((Map)li.get(0)).get("age")).intValue());
+ }
+
+ public void testQueryForListWithParamMapAndIntegerElementAndSingleRowAndColumn() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID < :id";
+ String sqlToUse = "SELECT AGE FROM CUSTMR WHERE ID < ?";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt(1);
+ ctrlResultSet.setReturnValue(11);
+ mockResultSet.wasNull();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(3));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sqlToUse);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(mockDataSource);
+
+ MapSqlParameterSource parms = new MapSqlParameterSource();
+ parms.addValue("id", new Integer(3));
+
+ List li = template.queryForList(sql, parms, Integer.class);
+ assertEquals("All rows returned", 1, li.size());
+ assertEquals("First row is Integer", 11, ((Integer) li.get(0)).intValue());
+ }
+
+ public void testQueryForMapWithParamMapAndSingleRowAndColumn() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID < :id";
+ String sqlToUse = "SELECT AGE FROM CUSTMR WHERE ID < ?";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+ mockResultSetMetaData.getColumnLabel(1);
+ ctrlResultSetMetaData.setReturnValue("age", 1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getObject(1);
+ ctrlResultSet.setReturnValue(new Integer(11));
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(3));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sqlToUse);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(mockDataSource);
+
+ MapSqlParameterSource parms = new MapSqlParameterSource();
+ parms.addValue("id", new Integer(3));
+
+ Map map = template.queryForMap(sql, parms);
+ assertEquals("Row is Integer", 11, ((Integer) map.get("age")).intValue());
+ }
+
+ public void testQueryForObjectWithParamMapAndRowMapper() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID = :id";
+ String sqlToUse = "SELECT AGE FROM CUSTMR WHERE ID = ?";
+
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt(1);
+ ctrlResultSet.setReturnValue(22);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(3));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sqlToUse);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(mockDataSource);
+
+ MapSqlParameterSource parms = new MapSqlParameterSource();
+ parms.addValue("id", new Integer(3));
+
+ Object o = template.queryForObject(sql, parms, new RowMapper() {
+ public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
+ return new Integer(rs.getInt(1));
+ }
+ });
+ assertTrue("Correct result type", o instanceof Integer);
+ }
+
+ public void testQueryForObjectWithMapAndInteger() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID = :id";
+ String sqlToUse = "SELECT AGE FROM CUSTMR WHERE ID = ?";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt(1);
+ ctrlResultSet.setReturnValue(22);
+ mockResultSet.wasNull();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(3));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sqlToUse);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(mockDataSource);
+
+ Map parms = new HashMap();
+ parms.put("id", new Integer(3));
+
+ Object o = template.queryForObject(sql, parms, Integer.class);
+ assertTrue("Correct result type", o instanceof Integer);
+ }
+
+ public void testQueryForObjectWithParamMapAndInteger() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID = :id";
+ String sqlToUse = "SELECT AGE FROM CUSTMR WHERE ID = ?";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt(1);
+ ctrlResultSet.setReturnValue(22);
+ mockResultSet.wasNull();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(3));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sqlToUse);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(mockDataSource);
+
+ MapSqlParameterSource parms = new MapSqlParameterSource();
+ parms.addValue("id", new Integer(3));
+
+ Object o = template.queryForObject(sql, parms, Integer.class);
+ assertTrue("Correct result type", o instanceof Integer);
+ }
+
+ public void testQueryForObjectWithParamMapAndList() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID IN (:ids)";
+ String sqlToUse = "SELECT AGE FROM CUSTMR WHERE ID IN (?, ?)";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt(1);
+ ctrlResultSet.setReturnValue(22);
+ mockResultSet.wasNull();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(3));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setObject(2, new Integer(4));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sqlToUse);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(mockDataSource);
+
+ MapSqlParameterSource parms = new MapSqlParameterSource();
+ parms.addValue("ids", Arrays.asList(new Object[] {new Integer(3), new Integer(4)}));
+
+ Object o = template.queryForObject(sql, parms, Integer.class);
+ assertTrue("Correct result type", o instanceof Integer);
+ }
+
+ public void testQueryForObjectWithParamMapAndListOfExpressionLists() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE (ID, NAME) IN (:multiExpressionList)";
+ String sqlToUse = "SELECT AGE FROM CUSTMR WHERE (ID, NAME) IN ((?, ?), (?, ?))";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt(1);
+ ctrlResultSet.setReturnValue(22);
+ mockResultSet.wasNull();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(3));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setString(2, "Rod");
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setObject(3, new Integer(4));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setString(4, "Juergen");
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sqlToUse);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(mockDataSource);
+
+ MapSqlParameterSource parms = new MapSqlParameterSource();
+ List l1 = new ArrayList();
+ l1.add(new Object[] {new Integer(3), "Rod"});
+ l1.add(new Object[] {new Integer(4), "Juergen"});
+ parms.addValue("multiExpressionList", l1);
+
+ Object o = template.queryForObject(sql, parms, Integer.class);
+ assertTrue("Correct result type", o instanceof Integer);
+ }
+
+ public void testQueryForIntWithParamMap() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID = :id";
+ String sqlToUse = "SELECT AGE FROM CUSTMR WHERE ID = ?";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getDouble(1);
+ ctrlResultSet.setReturnValue(22.0d);
+ mockResultSet.wasNull();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(3));
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sqlToUse);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(mockDataSource);
+
+ MapSqlParameterSource parms = new MapSqlParameterSource();
+ parms.addValue("id", new Integer(3));
+
+ int i = template.queryForInt(sql, parms);
+ assertEquals("Return of an int", 22, i);
+ }
+
+ public void testQueryForLongWithParamBean() throws Exception {
+ String sql = "SELECT AGE FROM CUSTMR WHERE ID = :id";
+ String sqlToUse = "SELECT AGE FROM CUSTMR WHERE ID = ?";
+
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getDouble(1);
+ ctrlResultSet.setReturnValue(87.0d);
+ mockResultSet.wasNull();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(3), Types.INTEGER);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(sqlToUse);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(mockDataSource);
+ BeanPropertySqlParameterSource parms = new BeanPropertySqlParameterSource(new ParameterBean(3));
+
+ long l = template.queryForLong(sql, parms);
+ assertEquals("Return of a long", 87, l);
+ }
+
+
+ private static class ParameterBean {
+
+ private int id;
+
+ public ParameterBean(int id) {
+ this.id = id;
+ }
+
+ public int getId() {
+ return id;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterUtilsTests.java
new file mode 100644
index 00000000000..ccecc08a64e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterUtilsTests.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.core.namedparam;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Thomas Risberg
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ */
+public class NamedParameterUtilsTests extends TestCase {
+
+ public void testParseSql() {
+ String sql = "xxx :a yyyy :b :c :a zzzzz";
+ ParsedSql psql = NamedParameterUtils.parseSqlStatement(sql);
+ assertEquals("xxx ? yyyy ? ? ? zzzzz", NamedParameterUtils.substituteNamedParameters(psql, null));
+ assertEquals("a", psql.getParameterNames().get(0));
+ assertEquals("c", psql.getParameterNames().get(2));
+ assertEquals("a", psql.getParameterNames().get(3));
+ assertEquals(4, psql.getTotalParameterCount());
+ assertEquals(3, psql.getNamedParameterCount());
+
+ String sql2 = "xxx &a yyyy ? zzzzz";
+ ParsedSql psql2 = NamedParameterUtils.parseSqlStatement(sql2);
+ assertEquals("xxx ? yyyy ? zzzzz", NamedParameterUtils.substituteNamedParameters(psql2, null));
+ assertEquals("a", psql2.getParameterNames().get(0));
+ assertEquals(2, psql2.getTotalParameterCount());
+ assertEquals(1, psql2.getNamedParameterCount());
+
+ String sql3 = "xxx &a+:b" + '\t' + ":c%10 yyyy ? zzzzz";
+ ParsedSql psql3 = NamedParameterUtils.parseSqlStatement(sql3);
+ assertEquals("a", psql3.getParameterNames().get(0));
+ assertEquals("b", psql3.getParameterNames().get(1));
+ assertEquals("c", psql3.getParameterNames().get(2));
+
+ }
+
+ public void testSubstituteNamedParameters() {
+ MapSqlParameterSource namedParams = new MapSqlParameterSource();
+ namedParams.addValue("a", "a").addValue("b", "b").addValue("c", "c");
+ assertEquals("xxx ? ? ?", NamedParameterUtils.substituteNamedParameters("xxx :a :b :c", namedParams));
+ assertEquals("xxx ? ? ? xx ? ?", NamedParameterUtils.substituteNamedParameters("xxx :a :b :c xx :a :a", namedParams));
+ }
+
+ public void testConvertParamMapToArray() {
+ Map paramMap = new HashMap();
+ paramMap.put("a", "a");
+ paramMap.put("b", "b");
+ paramMap.put("c", "c");
+ assertTrue(3 == NamedParameterUtils.buildValueArray("xxx :a :b :c", paramMap).length);
+ assertTrue(5 == NamedParameterUtils.buildValueArray("xxx :a :b :c xx :a :b", paramMap).length);
+ assertTrue(5 == NamedParameterUtils.buildValueArray("xxx :a :a :a xx :a :a", paramMap).length);
+ assertEquals("b", NamedParameterUtils.buildValueArray("xxx :a :b :c xx :a :b", paramMap)[4]);
+ try {
+ NamedParameterUtils.buildValueArray("xxx :a :b ?", paramMap);
+ fail("mixed named parameters and ? placeholders not detected");
+ }
+ catch (InvalidDataAccessApiUsageException expected) {
+ }
+ }
+
+ public void testConvertTypeMapToArray() {
+ MapSqlParameterSource namedParams = new MapSqlParameterSource();
+ namedParams.addValue("a", "a", 1).addValue("b", "b", 2).addValue("c", "c", 3);
+ assertTrue(3 == NamedParameterUtils.buildSqlTypeArray(NamedParameterUtils.parseSqlStatement("xxx :a :b :c"), namedParams).length);
+ assertTrue(5 == NamedParameterUtils.buildSqlTypeArray(NamedParameterUtils.parseSqlStatement("xxx :a :b :c xx :a :b"), namedParams).length);
+ assertTrue(5 == NamedParameterUtils.buildSqlTypeArray(NamedParameterUtils.parseSqlStatement("xxx :a :a :a xx :a :a"), namedParams).length);
+ assertEquals(2, NamedParameterUtils.buildSqlTypeArray(NamedParameterUtils.parseSqlStatement("xxx :a :b :c xx :a :b"), namedParams)[4]);
+ }
+
+ public void testBuildValueArrayWithMissingParameterValue() throws Exception {
+ new AssertThrows(InvalidDataAccessApiUsageException.class) {
+ public void test() throws Exception {
+ String sql = "select count(0) from foo where id = :id";
+ NamedParameterUtils.buildValueArray(sql, new HashMap());
+ }
+ }.runTest();
+ }
+
+ public void testSubstituteNamedParametersWithStringContainingQuotes() throws Exception {
+ String expectedSql = "select 'first name' from artists where id = ? and quote = 'exsqueeze me?'";
+ String sql = "select 'first name' from artists where id = :id and quote = 'exsqueeze me?'";
+ String newSql = NamedParameterUtils.substituteNamedParameters(sql, new MapSqlParameterSource());
+ assertEquals(expectedSql, newSql);
+ }
+
+ public void testParseSqlStatementWithStringContainingQuotes() throws Exception {
+ String expectedSql = "select 'first name' from artists where id = ? and quote = 'exsqueeze me?'";
+ String sql = "select 'first name' from artists where id = :id and quote = 'exsqueeze me?'";
+ ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(sql);
+ assertEquals(expectedSql, NamedParameterUtils.substituteNamedParameters(parsedSql, null));
+ }
+
+ /*
+ * SPR-4789
+ */
+ public void testParseSqlContainingComments() {
+ String sql1 = "/*+ HINT */ xxx /* comment ? */ :a yyyy :b :c :a zzzzz -- :xx XX\n";
+ ParsedSql psql1 = NamedParameterUtils.parseSqlStatement(sql1);
+ assertEquals("/*+ HINT */ xxx /* comment ? */ ? yyyy ? ? ? zzzzz -- :xx XX\n",
+ NamedParameterUtils.substituteNamedParameters(psql1, null));
+ MapSqlParameterSource paramMap = new MapSqlParameterSource();
+ paramMap.addValue("a", "a");
+ paramMap.addValue("b", "b");
+ paramMap.addValue("c", "c");
+ Object[] params = NamedParameterUtils.buildValueArray(psql1, paramMap, null);
+ assertEquals(4, params.length);
+ assertEquals("a", params[0]);
+ assertEquals("b", params[1]);
+ assertEquals("c", params[2]);
+ assertEquals("a", params[3]);
+
+ String sql2 = "/*+ HINT */ xxx /* comment ? */ :a yyyy :b :c :a zzzzz -- :xx XX";
+ ParsedSql psql2 = NamedParameterUtils.parseSqlStatement(sql2);
+ assertEquals("/*+ HINT */ xxx /* comment ? */ ? yyyy ? ? ? zzzzz -- :xx XX",
+ NamedParameterUtils.substituteNamedParameters(psql2, null));
+
+ String sql3 = "/*+ HINT */ xxx /* comment ? */ :a yyyy :b :c :a zzzzz /* :xx XX*";
+ ParsedSql psql3 = NamedParameterUtils.parseSqlStatement(sql3);
+ assertEquals("/*+ HINT */ xxx /* comment ? */ ? yyyy ? ? ? zzzzz /* :xx XX*",
+ NamedParameterUtils.substituteNamedParameters(psql3, null));
+
+ String sql4 = "/*+ HINT */ xxx /* comment :a ? */ :a yyyy :b :c :a zzzzz /* :xx XX*";
+ ParsedSql psql4 = NamedParameterUtils.parseSqlStatement(sql4);
+ Map parameters = Collections.singletonMap("a", "0");
+ assertEquals("/*+ HINT */ xxx /* comment :a ? */ ? yyyy ? ? ? zzzzz /* :xx XX*",
+ NamedParameterUtils.substituteNamedParameters(psql4, new MapSqlParameterSource(parameters)));
+ }
+
+ /*
+ * SPR-4612
+ */
+ public void testParseSqlStatementWithPostgresCasting() throws Exception {
+ String expectedSql = "select 'first name' from artists where id = ? and birth_date=?::timestamp";
+ String sql = "select 'first name' from artists where id = :id and birth_date=:birthDate::timestamp";
+ ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(sql);
+ assertEquals(expectedSql, NamedParameterUtils.substituteNamedParameters(parsedSql, null));
+ }
+
+ /*
+ * SPR-2544
+ */
+ public void testParseSqlStatementWithLogicalAnd() {
+ String expectedSql = "xxx & yyyy";
+ ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(expectedSql);
+ assertEquals(expectedSql, NamedParameterUtils.substituteNamedParameters(parsedSql, null));
+ }
+
+ /*
+ * SPR-2544
+ */
+ public void testSubstituteNamedParametersWithLogicalAnd() throws Exception {
+ String expectedSql = "xxx & yyyy";
+ String newSql = NamedParameterUtils.substituteNamedParameters(expectedSql, new MapSqlParameterSource());
+ assertEquals(expectedSql, newSql);
+ }
+
+ /*
+ * SPR-3173
+ */
+ public void testVariableAssignmentOperator() throws Exception {
+ String expectedSql = "x := 1";
+ String newSql = NamedParameterUtils.substituteNamedParameters(expectedSql, new MapSqlParameterSource());
+ assertEquals(expectedSql, newSql);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/support/JdbcBeanDefinitionReaderTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/support/JdbcBeanDefinitionReaderTests.java
new file mode 100644
index 00000000000..16f620942cb
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/support/JdbcBeanDefinitionReaderTests.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.core.support;
+
+import java.sql.ResultSet;
+import java.sql.Statement;
+
+import org.easymock.MockControl;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.jdbc.AbstractJdbcTests;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+/**
+ * @author Rod Johnson
+ */
+public class JdbcBeanDefinitionReaderTests extends AbstractJdbcTests {
+
+ private final boolean debugEnabled = LogFactory.getLog(JdbcTemplate.class).isDebugEnabled();
+
+
+ public void testValid() throws Exception {
+ String sql = "SELECT NAME AS NAME, PROPERTY AS PROPERTY, VALUE AS VALUE FROM T";
+
+ MockControl ctrlResultSet = MockControl.createControl(ResultSet.class);
+ ResultSet mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ ctrlResultSet.expectAndReturn(mockResultSet.next(), true, 2);
+ ctrlResultSet.expectAndReturn(mockResultSet.next(), false);
+
+ // first row
+ ctrlResultSet.expectAndReturn(mockResultSet.getString(1), "one");
+ ctrlResultSet.expectAndReturn(mockResultSet.getString(2), "(class)");
+ ctrlResultSet.expectAndReturn(mockResultSet.getString(3), "org.springframework.beans.TestBean");
+
+ // second row
+ ctrlResultSet.expectAndReturn(mockResultSet.getString(1), "one");
+ ctrlResultSet.expectAndReturn(mockResultSet.getString(2), "age");
+ ctrlResultSet.expectAndReturn(mockResultSet.getString(3), "53");
+
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ MockControl ctrlStatement = MockControl.createControl(Statement.class);
+ Statement mockStatement = (Statement) ctrlStatement.getMock();
+ ctrlStatement.expectAndReturn(mockStatement.executeQuery(sql), mockResultSet);
+ if (debugEnabled) {
+ ctrlStatement.expectAndReturn(mockStatement.getWarnings(), null);
+ }
+ mockStatement.close();
+ ctrlStatement.setVoidCallable();
+
+ mockConnection.createStatement();
+ ctrlConnection.setReturnValue(mockStatement);
+
+ ctrlResultSet.replay();
+ ctrlStatement.replay();
+ replay();
+
+ DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
+ JdbcBeanDefinitionReader reader = new JdbcBeanDefinitionReader(bf);
+ reader.setDataSource(mockDataSource);
+ reader.loadBeanDefinitions(sql);
+ assertEquals("Incorrect number of bean definitions", 1, bf.getBeanDefinitionCount());
+ TestBean tb = (TestBean) bf.getBean("one");
+ assertEquals("Age in TestBean was wrong.", 53, tb.getAge());
+
+ ctrlResultSet.verify();
+ ctrlStatement.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/support/JdbcDaoSupportTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/support/JdbcDaoSupportTests.java
new file mode 100644
index 00000000000..d9cb7118cc0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/support/JdbcDaoSupportTests.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jdbc.core.support;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.sql.DataSource;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.jdbc.core.JdbcTemplate;
+
+/**
+ * @author Juergen Hoeller
+ * @since 30.07.2003
+ */
+public class JdbcDaoSupportTests extends TestCase {
+
+ public void testJdbcDaoSupportWithDataSource() throws Exception {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ DataSource ds = (DataSource) dsControl.getMock();
+ final List test = new ArrayList();
+ JdbcDaoSupport dao = new JdbcDaoSupport() {
+ protected void initDao() {
+ test.add("test");
+ }
+ };
+ dao.setDataSource(ds);
+ dao.afterPropertiesSet();
+ assertEquals("Correct DataSource", ds, dao.getDataSource());
+ assertEquals("Correct JdbcTemplate", ds, dao.getJdbcTemplate().getDataSource());
+ assertEquals("initDao called", test.size(), 1);
+ }
+
+ public void testJdbcDaoSupportWithJdbcTemplate() throws Exception {
+ JdbcTemplate template = new JdbcTemplate();
+ final List test = new ArrayList();
+ JdbcDaoSupport dao = new JdbcDaoSupport() {
+ protected void initDao() {
+ test.add("test");
+ }
+ };
+ dao.setJdbcTemplate(template);
+ dao.afterPropertiesSet();
+ assertEquals("Correct JdbcTemplate", dao.getJdbcTemplate(), template);
+ assertEquals("initDao called", test.size(), 1);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/support/LobSupportTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/support/LobSupportTests.java
new file mode 100644
index 00000000000..08f3a84f18f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/support/LobSupportTests.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jdbc.core.support;
+
+import java.io.IOException;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.IncorrectResultSizeDataAccessException;
+import org.springframework.jdbc.LobRetrievalFailureException;
+import org.springframework.jdbc.support.lob.LobCreator;
+import org.springframework.jdbc.support.lob.LobHandler;
+
+/**
+ * @author Alef Arendsen
+ */
+public class LobSupportTests extends TestCase {
+
+ public void testCreatingPreparedStatementCallback() throws SQLException {
+ // - return value should match
+ // - lob creator should be closed
+ // - set return value should be called
+ // - execute update should be called
+
+ MockControl lobHandlerControl = MockControl.createControl(LobHandler.class);
+ LobHandler handler = (LobHandler)lobHandlerControl.getMock();
+
+ MockControl lobCreatorControl = MockControl.createControl(LobCreator.class);
+ LobCreator creator = (LobCreator)lobCreatorControl.getMock();
+
+ MockControl psControl = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement ps = (PreparedStatement)psControl.getMock();
+
+ handler.getLobCreator();
+ lobHandlerControl.setReturnValue(creator);
+ ps.executeUpdate();
+ psControl.setReturnValue(3);
+ creator.close();
+
+ lobHandlerControl.replay();
+ lobCreatorControl.replay();
+ psControl.replay();
+
+ class SetValuesCalled {
+ boolean b = false;
+ }
+
+ final SetValuesCalled svc = new SetValuesCalled();
+
+ AbstractLobCreatingPreparedStatementCallback psc =
+ new AbstractLobCreatingPreparedStatementCallback(handler) {
+
+ protected void setValues(PreparedStatement ps, LobCreator lobCreator)
+ throws SQLException, DataAccessException {
+ svc.b = true;
+ }
+ };
+
+ assertEquals(new Integer(3), psc.doInPreparedStatement(ps));
+
+ lobHandlerControl.verify();
+ lobCreatorControl.verify();
+ psControl.verify();
+ assertTrue(svc.b);
+ }
+
+ public void testAbstractLobStreamingResultSetExtractorNoRows() throws SQLException {
+ MockControl rsetControl = MockControl.createControl(ResultSet.class);
+ ResultSet rset = (ResultSet)rsetControl.getMock();
+ rset.next();
+ rsetControl.setReturnValue(false);
+ rsetControl.replay();
+
+ AbstractLobStreamingResultSetExtractor lobRse = getResultSetExtractor(false);
+ try {
+ lobRse.extractData(rset);
+ fail("IncorrectResultSizeDataAccessException should have been thrown");
+ } catch (IncorrectResultSizeDataAccessException e) {
+ // expected
+ }
+ }
+
+ public void testAbstractLobStreamingResultSetExtractorOneRow() throws SQLException {
+ MockControl rsetControl = MockControl.createControl(ResultSet.class);
+ ResultSet rset = (ResultSet)rsetControl.getMock();
+ rset.next();
+ rsetControl.setReturnValue(true);
+ // see if it's called
+ rset.clearWarnings();
+ rset.next();
+ rsetControl.setReturnValue(false);
+ rsetControl.replay();
+
+ AbstractLobStreamingResultSetExtractor lobRse = getResultSetExtractor(false);
+ lobRse.extractData(rset);
+ rsetControl.verify();
+ }
+
+ public void testAbstractLobStreamingResultSetExtractorMultipleRows() throws SQLException {
+ MockControl rsetControl = MockControl.createControl(ResultSet.class);
+ ResultSet rset = (ResultSet)rsetControl.getMock();
+ rset.next();
+ rsetControl.setReturnValue(true);
+ // see if it's called
+ rset.clearWarnings();
+ rset.next();
+ rsetControl.setReturnValue(true);
+ rsetControl.replay();
+
+ AbstractLobStreamingResultSetExtractor lobRse = getResultSetExtractor(false);
+ try {
+ lobRse.extractData(rset);
+ fail("IncorrectResultSizeDataAccessException should have been thrown");
+ } catch (IncorrectResultSizeDataAccessException e) {
+ // expected
+ }
+ rsetControl.verify();
+ }
+
+ public void testAbstractLobStreamingResultSetExtractorCorrectException() throws SQLException {
+ MockControl rsetControl = MockControl.createControl(ResultSet.class);
+ ResultSet rset = (ResultSet)rsetControl.getMock();
+ rset.next();
+ rsetControl.setReturnValue(true);
+ rsetControl.replay();
+
+ AbstractLobStreamingResultSetExtractor lobRse = getResultSetExtractor(true);
+ try {
+ lobRse.extractData(rset);
+ fail("LobRetrievalFailureException should have been thrown");
+ } catch (LobRetrievalFailureException e) {
+ // expected
+ }
+ rsetControl.verify();
+ }
+
+ private AbstractLobStreamingResultSetExtractor getResultSetExtractor(final boolean ex) {
+ AbstractLobStreamingResultSetExtractor lobRse = new AbstractLobStreamingResultSetExtractor() {
+ protected void streamData(ResultSet rs) throws SQLException, IOException {
+ if (ex) {
+ throw new IOException();
+ }
+ else {
+ rs.clearWarnings();
+ }
+ }
+ };
+ return lobRse;
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/support/SqlLobValueTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/support/SqlLobValueTests.java
new file mode 100644
index 00000000000..29a4a51fbc1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/support/SqlLobValueTests.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jdbc.core.support;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStreamReader;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.Arrays;
+import java.util.Date;
+
+import junit.framework.TestCase;
+import org.easymock.ArgumentsMatcher;
+import org.easymock.MockControl;
+
+import org.springframework.jdbc.support.lob.LobCreator;
+import org.springframework.jdbc.support.lob.LobHandler;
+
+/**
+ * Test cases for the sql lob value:
+ *
+ * BLOB:
+ * 1. Types.BLOB: setBlobAsBytes (byte[])
+ * 2. String: setBlobAsBytes (byte[])
+ * 3. else: IllegalArgumentException
+ *
+ * CLOB:
+ * 4. String or NULL: setClobAsString (String)
+ * 5. InputStream: setClobAsAsciiStream (InputStream)
+ * 6. Reader: setClobAsCharacterStream (Reader)
+ * 7. else: IllegalArgumentException
+ *
+ * @author Alef Arendsen
+ */
+public class SqlLobValueTests extends TestCase {
+
+ private MockControl psControl;
+ private PreparedStatement ps;
+
+ private MockControl lobHandlerControl;
+ private LobHandler handler;
+
+ private MockControl lobCreatorControl;
+ private LobCreator creator;
+
+ public void setUp() {
+ // create preparedstatement
+ psControl = MockControl.createControl(PreparedStatement.class);
+ ps = (PreparedStatement) psControl.getMock();
+
+ // create handler controler
+ lobHandlerControl = MockControl.createControl(LobHandler.class);
+ handler = (LobHandler) lobHandlerControl.getMock();
+
+ // create creator control
+ lobCreatorControl = MockControl.createControl(LobCreator.class);
+ creator = (LobCreator) lobCreatorControl.getMock();
+
+ // set initial state
+ handler.getLobCreator();
+ lobHandlerControl.setReturnValue(creator);
+ }
+
+ private void replay() {
+ psControl.replay();
+ lobHandlerControl.replay();
+ lobCreatorControl.replay();
+ }
+
+ public void test1() throws SQLException {
+ byte[] testBytes = "Bla".getBytes();
+ creator.setBlobAsBytes(ps, 1, testBytes);
+ replay();
+ SqlLobValue lob = new SqlLobValue(testBytes, handler);
+ lob.setTypeValue(ps, 1, Types.BLOB, "test");
+ lobHandlerControl.verify();
+ lobCreatorControl.verify();
+ }
+
+ public void test2() throws SQLException {
+ String testString = "Bla";
+
+ creator.setBlobAsBytes(ps, 1, testString.getBytes());
+ // set a matcher to match the byte array!
+ lobCreatorControl.setMatcher(new ArgumentsMatcher() {
+ public boolean matches(Object[] arg0, Object[] arg1) {
+ byte[] one = (byte[]) arg0[2];
+ byte[] two = (byte[]) arg1[2];
+ return Arrays.equals(one, two);
+ }
+ public String toString(Object[] arg0) {
+ return "bla";
+ }
+ });
+
+ replay();
+
+ SqlLobValue lob = new SqlLobValue(testString, handler);
+ lob.setTypeValue(ps, 1, Types.BLOB, "test");
+ lobHandlerControl.verify();
+ lobCreatorControl.verify();
+
+ }
+
+ public void test3()
+ throws SQLException {
+
+ Date testContent = new Date();
+
+ SqlLobValue lob =
+ new SqlLobValue(new InputStreamReader(new ByteArrayInputStream("Bla".getBytes())), 12);
+ try {
+ lob.setTypeValue(ps, 1, Types.BLOB, "test");
+ fail("IllegalArgumentException should have been thrown");
+ }
+ catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void test4() throws SQLException {
+ String testContent = "Bla";
+ creator.setClobAsString(ps, 1, testContent);
+
+ replay();
+
+ SqlLobValue lob = new SqlLobValue(testContent, handler);
+ lob.setTypeValue(ps, 1, Types.CLOB, "test");
+ lobHandlerControl.verify();
+ lobCreatorControl.verify();
+ }
+
+ public void test5() throws SQLException {
+ byte[] testContent = "Bla".getBytes();
+ ByteArrayInputStream bais = new ByteArrayInputStream(testContent);
+ creator.setClobAsAsciiStream(ps, 1, bais, 3);
+ lobCreatorControl.setMatcher(new ArgumentsMatcher() {
+ public boolean matches(Object[] arg0, Object[] arg1) {
+ // for now, match always
+ return true;
+ }
+ public String toString(Object[] arg0) {
+ return null;
+ }
+ });
+
+ replay();
+
+ SqlLobValue lob = new SqlLobValue(new ByteArrayInputStream(testContent), 3, handler);
+ lob.setTypeValue(ps, 1, Types.CLOB, "test");
+ lobHandlerControl.verify();
+ lobCreatorControl.verify();
+ }
+
+ public void test6()throws SQLException {
+ byte[] testContent = "Bla".getBytes();
+ ByteArrayInputStream bais = new ByteArrayInputStream(testContent);
+ InputStreamReader reader = new InputStreamReader(bais);
+ creator.setClobAsCharacterStream(ps, 1, reader, 3);
+ lobCreatorControl.setMatcher(new ArgumentsMatcher() {
+ public boolean matches(Object[] arg0, Object[] arg1) {
+ // for now, match always
+ return true;
+ }
+ public String toString(Object[] arg0) {
+ return null;
+ }
+ });
+
+ replay();
+
+ SqlLobValue lob = new SqlLobValue(reader, 3, handler);
+ lob.setTypeValue(ps, 1, Types.CLOB, "test");
+ lobHandlerControl.verify();
+ lobCreatorControl.verify();
+
+ }
+
+ public void test7() throws SQLException {
+ Date testContent = new Date();
+
+ SqlLobValue lob = new SqlLobValue("bla".getBytes());
+ try {
+ lob.setTypeValue(ps, 1, Types.CLOB, "test");
+ fail("IllegalArgumentException should have been thrown");
+ }
+ catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testOtherConstructors() throws SQLException {
+ // a bit BS, but we need to test them, as long as they don't throw exceptions
+
+ SqlLobValue lob = new SqlLobValue("bla");
+ lob.setTypeValue(ps, 1, Types.CLOB, "test");
+
+ try {
+ lob = new SqlLobValue("bla".getBytes());
+ lob.setTypeValue(ps, 1, Types.CLOB, "test");
+ fail("IllegalArgumentException should have been thrown");
+ }
+ catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ lob = new SqlLobValue(new ByteArrayInputStream("bla".getBytes()), 3);
+ lob.setTypeValue(ps, 1, Types.CLOB, "test");
+
+ lob = new SqlLobValue(new InputStreamReader(
+ new ByteArrayInputStream("bla".getBytes())), 3);
+ lob.setTypeValue(ps, 1, Types.CLOB, "test");
+
+ // same for BLOB
+ lob = new SqlLobValue("bla");
+ lob.setTypeValue(ps, 1, Types.BLOB, "test");
+
+ lob = new SqlLobValue("bla".getBytes());
+ lob.setTypeValue(ps, 1, Types.BLOB, "test");
+
+ lob = new SqlLobValue(new ByteArrayInputStream("bla".getBytes()), 3);
+ lob.setTypeValue(ps, 1, Types.BLOB, "test");
+
+ lob = new SqlLobValue(new InputStreamReader(
+ new ByteArrayInputStream("bla".getBytes())), 3);
+
+ try {
+ lob.setTypeValue(ps, 1, Types.BLOB, "test");
+ fail("IllegalArgumentException should have been thrown");
+ }
+ catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testCorrectCleanup() throws SQLException {
+ creator.setClobAsString(ps, 1, "Bla");
+ creator.close();
+
+ replay();
+ SqlLobValue lob = new SqlLobValue("Bla", handler);
+ lob.setTypeValue(ps, 1, Types.CLOB, "test");
+ lob.cleanup();
+
+ lobCreatorControl.verify();
+ }
+
+ public void testOtherSqlType() throws SQLException {
+ replay();
+ SqlLobValue lob = new SqlLobValue("Bla", handler);
+ try {
+ lob.setTypeValue(ps, 1, Types.SMALLINT, "test");
+ fail("IllegalArgumentException should have been thrown");
+ }
+ catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/test/AbstractPerson.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/test/AbstractPerson.java
new file mode 100644
index 00000000000..89148bc0821
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/test/AbstractPerson.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.core.test;
+
+import java.util.Date;
+
+/**
+ * @author Thomas Risberg
+ */
+public abstract class AbstractPerson {
+
+ private String name;
+
+ private long age;
+
+ private java.util.Date birth_date;
+
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public long getAge() {
+ return age;
+ }
+
+ public void setAge(long age) {
+ this.age = age;
+ }
+
+ public Date getBirth_date() {
+ return birth_date;
+ }
+
+ public void setBirth_date(Date birth_date) {
+ this.birth_date = birth_date;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/test/ConcretePerson.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/test/ConcretePerson.java
new file mode 100644
index 00000000000..5d13c99c1b0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/test/ConcretePerson.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.core.test;
+
+import java.math.BigDecimal;
+
+/**
+ * @author Thomas Risberg
+ */
+public class ConcretePerson extends AbstractPerson {
+
+ private BigDecimal balance;
+
+
+ public BigDecimal getBalance() {
+ return balance;
+ }
+
+ public void setBalance(BigDecimal balance) {
+ this.balance = balance;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/test/ExtendedPerson.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/test/ExtendedPerson.java
new file mode 100644
index 00000000000..21c4f2eb6e2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/test/ExtendedPerson.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.core.test;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class ExtendedPerson extends ConcretePerson {
+
+ private Object someField;
+
+
+ public Object getSomeField() {
+ return someField;
+ }
+
+ public void setSomeField(Object someField) {
+ this.someField = someField;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/test/Person.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/test/Person.java
new file mode 100644
index 00000000000..9613b37e94b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/core/test/Person.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.core.test;
+
+import java.math.BigDecimal;
+
+/**
+ * @author Thomas Risberg
+ */
+public class Person {
+
+ private String name;
+
+ private long age;
+
+ private java.util.Date birth_date;
+
+ private BigDecimal balance;
+
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public long getAge() {
+ return age;
+ }
+
+ public void setAge(long age) {
+ this.age = age;
+ }
+
+ public java.util.Date getBirth_date() {
+ return birth_date;
+ }
+
+ public void setBirth_date(java.util.Date birth_date) {
+ this.birth_date = birth_date;
+ }
+
+ public BigDecimal getBalance() {
+ return balance;
+ }
+
+ public void setBalance(BigDecimal balanace) {
+ this.balance = balanace;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/DataSourceJtaTransactionTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/DataSourceJtaTransactionTests.java
new file mode 100644
index 00000000000..3dcee9661cf
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/DataSourceJtaTransactionTests.java
@@ -0,0 +1,901 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jdbc.datasource;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.sql.DataSource;
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.beans.factory.support.StaticListableBeanFactory;
+import org.springframework.jdbc.datasource.lookup.BeanFactoryDataSourceLookup;
+import org.springframework.jdbc.datasource.lookup.IsolationLevelDataSourceRouter;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionException;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.jta.JtaTransactionManager;
+import org.springframework.transaction.jta.JtaTransactionObject;
+import org.springframework.transaction.support.TransactionCallbackWithoutResult;
+import org.springframework.transaction.support.TransactionSynchronization;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+import org.springframework.transaction.support.TransactionTemplate;
+
+/**
+ * @author Juergen Hoeller
+ * @since 17.10.2005
+ */
+public class DataSourceJtaTransactionTests extends TestCase {
+
+ public void testJtaTransactionCommit() throws Exception {
+ doTestJtaTransaction(false);
+ }
+
+ public void testJtaTransactionRollback() throws Exception {
+ doTestJtaTransaction(true);
+ }
+
+ private void doTestJtaTransaction(final boolean rollback) throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ if (rollback) {
+ ut.rollback();
+ }
+ else {
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ ut.commit();
+ }
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+ conControl.replay();
+ dsControl.replay();
+
+ JtaTransactionManager ptm = new JtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Is new transaction", status.isNewTransaction());
+
+ Connection c = DataSourceUtils.getConnection(ds);
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ DataSourceUtils.releaseConnection(c, ds);
+
+ c = DataSourceUtils.getConnection(ds);
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ DataSourceUtils.releaseConnection(c, ds);
+
+ if (rollback) {
+ status.setRollbackOnly();
+ }
+ }
+ });
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ dsControl.verify();
+ conControl.verify();
+ utControl.verify();
+ }
+
+ public void testJtaTransactionCommitWithPropagationRequiresNew() throws Exception {
+ doTestJtaTransactionWithPropagationRequiresNew(false, false, false, false);
+ }
+
+ public void testJtaTransactionCommitWithPropagationRequiresNewWithAccessAfterResume() throws Exception {
+ doTestJtaTransactionWithPropagationRequiresNew(false, false, true, false);
+ }
+
+ public void testJtaTransactionCommitWithPropagationRequiresNewWithOpenOuterConnection() throws Exception {
+ doTestJtaTransactionWithPropagationRequiresNew(false, true, false, false);
+ }
+
+ public void testJtaTransactionCommitWithPropagationRequiresNewWithOpenOuterConnectionAccessed() throws Exception {
+ doTestJtaTransactionWithPropagationRequiresNew(false, true, true, false);
+ }
+
+ public void testJtaTransactionCommitWithPropagationRequiresNewWithTransactionAwareDataSource() throws Exception {
+ doTestJtaTransactionWithPropagationRequiresNew(false, false, true, true);
+ }
+
+ public void testJtaTransactionRollbackWithPropagationRequiresNew() throws Exception {
+ doTestJtaTransactionWithPropagationRequiresNew(true, false, false, false);
+ }
+
+ public void testJtaTransactionRollbackWithPropagationRequiresNewWithAccessAfterResume() throws Exception {
+ doTestJtaTransactionWithPropagationRequiresNew(true, false, true, false);
+ }
+
+ public void testJtaTransactionRollbackWithPropagationRequiresNewWithOpenOuterConnection() throws Exception {
+ doTestJtaTransactionWithPropagationRequiresNew(true, true, false, false);
+ }
+
+ public void testJtaTransactionRollbackWithPropagationRequiresNewWithOpenOuterConnectionAccessed() throws Exception {
+ doTestJtaTransactionWithPropagationRequiresNew(true, true, true, false);
+ }
+
+ public void testJtaTransactionRollbackWithPropagationRequiresNewWithTransactionAwareDataSource() throws Exception {
+ doTestJtaTransactionWithPropagationRequiresNew(true, false, true, true);
+ }
+
+ private void doTestJtaTransactionWithPropagationRequiresNew(
+ final boolean rollback, final boolean openOuterConnection, final boolean accessAfterResume,
+ final boolean useTransactionAwareDataSource) throws Exception {
+
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 16);
+ tm.suspend();
+ tmControl.setReturnValue(tx, 5);
+ ut.begin();
+ utControl.setVoidCallable(5);
+ ut.commit();
+ utControl.setVoidCallable(5);
+ tm.resume(tx);
+ tmControl.setVoidCallable(5);
+ if (rollback) {
+ ut.rollback();
+ }
+ else {
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ ut.commit();
+ }
+ utControl.setVoidCallable(1);
+ utControl.replay();
+ tmControl.replay();
+
+ final MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ final MockControl conControl = MockControl.createControl(Connection.class);
+ final Connection con = (Connection) conControl.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ con.isReadOnly();
+ conControl.setReturnValue(true, 1);
+ if (!openOuterConnection) {
+ con.close();
+ conControl.setVoidCallable(1);
+ }
+ conControl.replay();
+ dsControl.replay();
+
+ final DataSource dsToUse = useTransactionAwareDataSource ?
+ new TransactionAwareDataSourceProxy(ds) : ds;
+
+ JtaTransactionManager ptm = new JtaTransactionManager(ut, tm);
+ final TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(dsToUse));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(dsToUse));
+ assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Is new transaction", status.isNewTransaction());
+
+ Connection c = DataSourceUtils.getConnection(dsToUse);
+ try {
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(dsToUse));
+ c.isReadOnly();
+ DataSourceUtils.releaseConnection(c, dsToUse);
+
+ c = DataSourceUtils.getConnection(dsToUse);
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(dsToUse));
+ if (!openOuterConnection) {
+ DataSourceUtils.releaseConnection(c, dsToUse);
+ }
+ }
+ catch (SQLException ex) {
+ }
+
+ for (int i = 0; i < 5; i++) {
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(dsToUse));
+ assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Is new transaction", status.isNewTransaction());
+
+ try {
+ dsControl.verify();
+ conControl.verify();
+ dsControl.reset();
+ conControl.reset();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ con.isReadOnly();
+ conControl.setReturnValue(true, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+ dsControl.replay();
+ conControl.replay();
+
+ Connection c = DataSourceUtils.getConnection(dsToUse);
+ c.isReadOnly();
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(dsToUse));
+ DataSourceUtils.releaseConnection(c, dsToUse);
+
+ c = DataSourceUtils.getConnection(dsToUse);
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(dsToUse));
+ DataSourceUtils.releaseConnection(c, dsToUse);
+ }
+ catch (SQLException ex) {
+ }
+ }
+ });
+
+ }
+
+ if (rollback) {
+ status.setRollbackOnly();
+ }
+
+ if (accessAfterResume) {
+ try {
+ if (!openOuterConnection) {
+ dsControl.verify();
+ dsControl.reset();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ dsControl.replay();
+ }
+ conControl.verify();
+ conControl.reset();
+ con.isReadOnly();
+ conControl.setReturnValue(true, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+ conControl.replay();
+
+ if (!openOuterConnection) {
+ c = DataSourceUtils.getConnection(dsToUse);
+ }
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(dsToUse));
+ c.isReadOnly();
+ DataSourceUtils.releaseConnection(c, dsToUse);
+
+ c = DataSourceUtils.getConnection(dsToUse);
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(dsToUse));
+ DataSourceUtils.releaseConnection(c, dsToUse);
+ }
+ catch (SQLException ex) {
+ }
+ }
+
+ else {
+ if (openOuterConnection) {
+ try {
+ conControl.verify();
+ conControl.reset();
+ con.close();
+ conControl.setVoidCallable(1);
+ conControl.replay();
+ }
+ catch (SQLException ex) {
+ }
+ DataSourceUtils.releaseConnection(c, dsToUse);
+ }
+ }
+ }
+ });
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(dsToUse));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ dsControl.verify();
+ conControl.verify();
+ utControl.verify();
+ tmControl.verify();
+ }
+
+ public void testJtaTransactionCommitWithPropagationRequiredWithinSupports() throws Exception {
+ doTestJtaTransactionCommitWithNewTransactionWithinEmptyTransaction(false, false);
+ }
+
+ public void testJtaTransactionCommitWithPropagationRequiredWithinNotSupported() throws Exception {
+ doTestJtaTransactionCommitWithNewTransactionWithinEmptyTransaction(false, true);
+ }
+
+ public void testJtaTransactionCommitWithPropagationRequiresNewWithinSupports() throws Exception {
+ doTestJtaTransactionCommitWithNewTransactionWithinEmptyTransaction(true, false);
+ }
+
+ public void testJtaTransactionCommitWithPropagationRequiresNewWithinNotSupported() throws Exception {
+ doTestJtaTransactionCommitWithNewTransactionWithinEmptyTransaction(true, true);
+ }
+
+ private void doTestJtaTransactionCommitWithNewTransactionWithinEmptyTransaction(
+ final boolean requiresNew, boolean notSupported) throws Exception {
+
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+ if (notSupported) {
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ tm.suspend();
+ tmControl.setReturnValue(tx, 1);
+ }
+ else {
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ }
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.commit();
+ utControl.setVoidCallable(1);
+ if (notSupported) {
+ tm.resume(tx);
+ tmControl.setVoidCallable(1);
+ }
+ utControl.replay();
+ tmControl.replay();
+ txControl.replay();
+
+ final MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ final MockControl con1Control = MockControl.createControl(Connection.class);
+ final Connection con1 = (Connection) con1Control.getMock();
+ final MockControl con2Control = MockControl.createControl(Connection.class);
+ final Connection con2 = (Connection) con2Control.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con1, 1);
+ ds.getConnection();
+ dsControl.setReturnValue(con2, 1);
+ con2.close();
+ con2Control.setVoidCallable(1);
+ con1.close();
+ con1Control.setVoidCallable(1);
+ dsControl.replay();
+ con1Control.replay();
+ con2Control.replay();
+
+ final JtaTransactionManager ptm = new JtaTransactionManager(ut, tm);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setPropagationBehavior(notSupported ?
+ TransactionDefinition.PROPAGATION_NOT_SUPPORTED : TransactionDefinition.PROPAGATION_SUPPORTS);
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertSame(con1, DataSourceUtils.getConnection(ds));
+ assertSame(con1, DataSourceUtils.getConnection(ds));
+
+ TransactionTemplate tt2 = new TransactionTemplate(ptm);
+ tt2.setPropagationBehavior(requiresNew ?
+ TransactionDefinition.PROPAGATION_REQUIRES_NEW : TransactionDefinition.PROPAGATION_REQUIRED);
+ tt2.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ assertSame(con2, DataSourceUtils.getConnection(ds));
+ assertSame(con2, DataSourceUtils.getConnection(ds));
+ }
+ });
+
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertSame(con1, DataSourceUtils.getConnection(ds));
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ tmControl.verify();
+ txControl.verify();
+ dsControl.verify();
+ con1Control.verify();
+ con2Control.verify();
+ }
+
+ public void testJtaTransactionCommitWithPropagationRequiresNewAndSuspendException() throws Exception {
+ doTestJtaTransactionWithPropagationRequiresNewAndBeginException(true, false, false);
+ }
+
+ public void testJtaTransactionCommitWithPropagationRequiresNewWithOpenOuterConnectionAndSuspendException() throws Exception {
+ doTestJtaTransactionWithPropagationRequiresNewAndBeginException(true, true, false);
+ }
+
+ public void testJtaTransactionCommitWithPropagationRequiresNewWithTransactionAwareDataSourceAndSuspendException() throws Exception {
+ doTestJtaTransactionWithPropagationRequiresNewAndBeginException(true, false, true);
+ }
+
+ public void testJtaTransactionCommitWithPropagationRequiresNewWithOpenOuterConnectionAndTransactionAwareDataSourceAndSuspendException() throws Exception {
+ doTestJtaTransactionWithPropagationRequiresNewAndBeginException(true, true, true);
+ }
+
+ public void testJtaTransactionCommitWithPropagationRequiresNewAndBeginException() throws Exception {
+ doTestJtaTransactionWithPropagationRequiresNewAndBeginException(false, false, false);
+ }
+
+ public void testJtaTransactionCommitWithPropagationRequiresNewWithOpenOuterConnectionAndBeginException() throws Exception {
+ doTestJtaTransactionWithPropagationRequiresNewAndBeginException(false, true, false);
+ }
+
+ public void testJtaTransactionCommitWithPropagationRequiresNewWithOpenOuterConnectionAndTransactionAwareDataSourceAndBeginException() throws Exception {
+ doTestJtaTransactionWithPropagationRequiresNewAndBeginException(false, true, true);
+ }
+
+ public void testJtaTransactionCommitWithPropagationRequiresNewWithTransactionAwareDataSourceAndBeginException() throws Exception {
+ doTestJtaTransactionWithPropagationRequiresNewAndBeginException(false, false, true);
+ }
+
+ private void doTestJtaTransactionWithPropagationRequiresNewAndBeginException(boolean suspendException,
+ final boolean openOuterConnection, final boolean useTransactionAwareDataSource) throws Exception {
+
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ if (suspendException) {
+ tm.suspend();
+ tmControl.setThrowable(new SystemException(), 1);
+ }
+ else {
+ tm.suspend();
+ tmControl.setReturnValue(tx, 1);
+ ut.begin();
+ utControl.setThrowable(new SystemException(), 1);
+ tm.resume(tx);
+ tmControl.setVoidCallable(1);
+ }
+ ut.rollback();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+ tmControl.replay();
+
+ final MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ final MockControl conControl = MockControl.createControl(Connection.class);
+ final Connection con = (Connection) conControl.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ con.isReadOnly();
+ conControl.setReturnValue(true, 1);
+ if (!openOuterConnection || useTransactionAwareDataSource) {
+ con.close();
+ conControl.setVoidCallable(1);
+ }
+ conControl.replay();
+ dsControl.replay();
+
+ final DataSource dsToUse = useTransactionAwareDataSource ?
+ new TransactionAwareDataSourceProxy(ds) : ds;
+ if (dsToUse instanceof TransactionAwareDataSourceProxy) {
+ ((TransactionAwareDataSourceProxy) dsToUse).setReobtainTransactionalConnections(true);
+ }
+
+ JtaTransactionManager ptm = new JtaTransactionManager(ut, tm);
+ final TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(dsToUse));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ try {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(dsToUse));
+ assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Is new transaction", status.isNewTransaction());
+
+ Connection c = DataSourceUtils.getConnection(dsToUse);
+ try {
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(dsToUse));
+ c.isReadOnly();
+ DataSourceUtils.releaseConnection(c, dsToUse);
+
+ c = DataSourceUtils.getConnection(dsToUse);
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(dsToUse));
+ if (!openOuterConnection) {
+ DataSourceUtils.releaseConnection(c, dsToUse);
+ }
+ }
+ catch (SQLException ex) {
+ }
+
+ try {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(dsToUse));
+ assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Is new transaction", status.isNewTransaction());
+
+ try {
+ dsControl.verify();
+ conControl.verify();
+ dsControl.reset();
+ conControl.reset();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+ dsControl.replay();
+ conControl.replay();
+
+ Connection c = DataSourceUtils.getConnection(dsToUse);
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(dsToUse));
+ DataSourceUtils.releaseConnection(c, dsToUse);
+
+ c = DataSourceUtils.getConnection(dsToUse);
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(dsToUse));
+ DataSourceUtils.releaseConnection(c, dsToUse);
+ }
+ catch (SQLException ex) {
+ }
+ }
+ });
+ }
+ finally {
+ if (openOuterConnection) {
+ try {
+ dsControl.verify();
+ dsControl.reset();
+ conControl.verify();
+ conControl.reset();
+
+ if (useTransactionAwareDataSource) {
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ }
+ con.isReadOnly();
+ conControl.setReturnValue(true, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+ dsControl.replay();
+ conControl.replay();
+
+ c.isReadOnly();
+ DataSourceUtils.releaseConnection(c, dsToUse);
+ }
+ catch (SQLException ex) {
+ }
+ }
+ }
+ }
+ });
+
+ fail("Should have thrown TransactionException");
+ }
+ catch (TransactionException ex) {
+ // expected
+ }
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(dsToUse));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ dsControl.verify();
+ conControl.verify();
+ utControl.verify();
+ tmControl.verify();
+ }
+
+ public void testJtaTransactionWithConnectionHolderStillBound() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+
+ JtaTransactionManager ptm = new JtaTransactionManager(ut) {
+ protected void doRegisterAfterCompletionWithJtaTransaction(
+ JtaTransactionObject txObject, final List synchronizations) {
+ Thread async = new Thread() {
+ public void run() {
+ invokeAfterCompletion(synchronizations, TransactionSynchronization.STATUS_COMMITTED);
+ }
+ };
+ async.start();
+ try {
+ async.join();
+ }
+ catch (InterruptedException ex) {
+ ex.printStackTrace();
+ }
+ }
+ };
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ for (int i = 0; i < 3; i++) {
+ utControl.reset();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ utControl.replay();
+
+ dsControl.reset();
+ conControl.reset();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+ dsControl.replay();
+ conControl.replay();
+
+ final boolean releaseCon = (i != 1);
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Is existing transaction", !status.isNewTransaction());
+
+ Connection c = DataSourceUtils.getConnection(ds);
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ DataSourceUtils.releaseConnection(c, ds);
+
+ c = DataSourceUtils.getConnection(ds);
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ if (releaseCon) {
+ DataSourceUtils.releaseConnection(c, ds);
+ }
+ }
+ });
+
+ if (!releaseCon) {
+ assertTrue("Still has connection holder", TransactionSynchronizationManager.hasResource(ds));
+ }
+ else {
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ }
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ conControl.verify();
+ dsControl.verify();
+ utControl.verify();
+ }
+ }
+
+ public void testJtaTransactionWithIsolationLevelDataSourceAdapter() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.commit();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.commit();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ MockControl ds1Control = MockControl.createControl(DataSource.class);
+ final DataSource ds1 = (DataSource) ds1Control.getMock();
+ MockControl con1Control = MockControl.createControl(Connection.class);
+ final Connection con1 = (Connection) con1Control.getMock();
+ ds1.getConnection();
+ ds1Control.setReturnValue(con1, 1);
+ con1.close();
+ con1Control.setVoidCallable(1);
+ ds1.getConnection();
+ ds1Control.setReturnValue(con1, 1);
+ con1.setReadOnly(true);
+ con1Control.setVoidCallable(1);
+ con1.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
+ con1Control.setVoidCallable(1);
+ con1.close();
+ con1Control.setVoidCallable(1);
+ con1Control.replay();
+ ds1Control.replay();
+
+ final IsolationLevelDataSourceAdapter dsToUse = new IsolationLevelDataSourceAdapter();
+ dsToUse.setTargetDataSource(ds1);
+ dsToUse.afterPropertiesSet();
+
+ JtaTransactionManager ptm = new JtaTransactionManager(ut);
+ ptm.setAllowCustomIsolationLevels(true);
+
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ Connection c = DataSourceUtils.getConnection(dsToUse);
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(dsToUse));
+ assertSame(con1, c);
+ DataSourceUtils.releaseConnection(c, dsToUse);
+ }
+ });
+
+ tt.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
+ tt.setReadOnly(true);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ Connection c = DataSourceUtils.getConnection(dsToUse);
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(dsToUse));
+ assertSame(con1, c);
+ DataSourceUtils.releaseConnection(c, dsToUse);
+ }
+ });
+
+ ds1Control.verify();
+ con1Control.verify();
+ utControl.verify();
+ }
+
+ public void testJtaTransactionWithIsolationLevelDataSourceRouter() throws Exception {
+ doTestJtaTransactionWithIsolationLevelDataSourceRouter(false);
+ }
+
+ public void testJtaTransactionWithIsolationLevelDataSourceRouterWithDataSourceLookup() throws Exception {
+ doTestJtaTransactionWithIsolationLevelDataSourceRouter(true);
+ }
+
+ private void doTestJtaTransactionWithIsolationLevelDataSourceRouter(boolean dataSourceLookup) throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.commit();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.commit();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ MockControl ds1Control = MockControl.createControl(DataSource.class);
+ final DataSource ds1 = (DataSource) ds1Control.getMock();
+ MockControl con1Control = MockControl.createControl(Connection.class);
+ final Connection con1 = (Connection) con1Control.getMock();
+ ds1.getConnection();
+ ds1Control.setReturnValue(con1, 1);
+ con1.close();
+ con1Control.setVoidCallable(1);
+ con1Control.replay();
+ ds1Control.replay();
+
+ MockControl ds2Control = MockControl.createControl(DataSource.class);
+ final DataSource ds2 = (DataSource) ds2Control.getMock();
+ MockControl con2Control = MockControl.createControl(Connection.class);
+ final Connection con2 = (Connection) con2Control.getMock();
+ ds2.getConnection();
+ ds2Control.setReturnValue(con2, 1);
+ con2.close();
+ con2Control.setVoidCallable(1);
+ con2Control.replay();
+ ds2Control.replay();
+
+ final IsolationLevelDataSourceRouter dsToUse = new IsolationLevelDataSourceRouter();
+ Map targetDataSources = new HashMap();
+ if (dataSourceLookup) {
+ targetDataSources.put("ISOLATION_REPEATABLE_READ", "ds2");
+ dsToUse.setDefaultTargetDataSource("ds1");
+ StaticListableBeanFactory beanFactory = new StaticListableBeanFactory();
+ beanFactory.addBean("ds1", ds1);
+ beanFactory.addBean("ds2", ds2);
+ dsToUse.setDataSourceLookup(new BeanFactoryDataSourceLookup(beanFactory));
+ }
+ else {
+ targetDataSources.put("ISOLATION_REPEATABLE_READ", ds2);
+ dsToUse.setDefaultTargetDataSource(ds1);
+ }
+ dsToUse.setTargetDataSources(targetDataSources);
+ dsToUse.afterPropertiesSet();
+
+ JtaTransactionManager ptm = new JtaTransactionManager(ut);
+ ptm.setAllowCustomIsolationLevels(true);
+
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ Connection c = DataSourceUtils.getConnection(dsToUse);
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(dsToUse));
+ assertSame(con1, c);
+ DataSourceUtils.releaseConnection(c, dsToUse);
+ }
+ });
+
+ tt.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ Connection c = DataSourceUtils.getConnection(dsToUse);
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(dsToUse));
+ assertSame(con2, c);
+ DataSourceUtils.releaseConnection(c, dsToUse);
+ }
+ });
+
+ ds1Control.verify();
+ con1Control.verify();
+ ds2Control.verify();
+ con2Control.verify();
+ utControl.verify();
+ }
+
+ protected void tearDown() {
+ assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertNull(TransactionSynchronizationManager.getCurrentTransactionName());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertNull(TransactionSynchronizationManager.getCurrentTransactionIsolationLevel());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/DataSourceTransactionManagerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/DataSourceTransactionManagerTests.java
new file mode 100644
index 00000000000..703e6930d08
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/DataSourceTransactionManagerTests.java
@@ -0,0 +1,1990 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jdbc.datasource;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Savepoint;
+
+import javax.sql.DataSource;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.dao.DataAccessResourceFailureException;
+import org.springframework.jdbc.UncategorizedSQLException;
+import org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor;
+import org.springframework.transaction.CannotCreateTransactionException;
+import org.springframework.transaction.IllegalTransactionStateException;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.TransactionSystemException;
+import org.springframework.transaction.TransactionTimedOutException;
+import org.springframework.transaction.UnexpectedRollbackException;
+import org.springframework.transaction.support.DefaultTransactionDefinition;
+import org.springframework.transaction.support.TransactionCallbackWithoutResult;
+import org.springframework.transaction.support.TransactionSynchronization;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+import org.springframework.transaction.support.TransactionTemplate;
+
+/**
+ * @author Juergen Hoeller
+ * @since 04.07.2003
+ */
+public class DataSourceTransactionManagerTests extends TestCase {
+
+ public void testTransactionCommitWithAutoCommitTrue() throws Exception {
+ doTestTransactionCommitRestoringAutoCommit(true, false, false);
+ }
+
+ public void testTransactionCommitWithAutoCommitFalse() throws Exception {
+ doTestTransactionCommitRestoringAutoCommit(false, false, false);
+ }
+
+ public void testTransactionCommitWithAutoCommitTrueAndLazyConnection() throws Exception {
+ doTestTransactionCommitRestoringAutoCommit(true, true, false);
+ }
+
+ public void testTransactionCommitWithAutoCommitFalseAndLazyConnection() throws Exception {
+ doTestTransactionCommitRestoringAutoCommit(false, true, false);
+ }
+
+ public void testTransactionCommitWithAutoCommitTrueAndLazyConnectionAndStatementCreated() throws Exception {
+ doTestTransactionCommitRestoringAutoCommit(true, true, true);
+ }
+
+ public void testTransactionCommitWithAutoCommitFalseAndLazyConnectionAndStatementCreated() throws Exception {
+ doTestTransactionCommitRestoringAutoCommit(false, true, true);
+ }
+
+ private void doTestTransactionCommitRestoringAutoCommit(
+ boolean autoCommit, boolean lazyConnection, final boolean createStatement)
+ throws Exception {
+
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ final Connection con = (Connection) conControl.getMock();
+
+ if (lazyConnection) {
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ if (createStatement) {
+ con.getMetaData();
+ conControl.setReturnValue(null, 1);
+ }
+ con.getAutoCommit();
+ conControl.setReturnValue(autoCommit, 1);
+ con.getTransactionIsolation();
+ conControl.setReturnValue(Connection.TRANSACTION_READ_COMMITTED, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+ }
+
+ if (!lazyConnection || createStatement) {
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ con.getAutoCommit();
+ conControl.setReturnValue(autoCommit, 1);
+ if (autoCommit) {
+ // Must disable autocommit
+ con.setAutoCommit(false);
+ conControl.setVoidCallable(1);
+ }
+ if (createStatement) {
+ con.createStatement();
+ conControl.setReturnValue(null, 1);
+ }
+ con.commit();
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ if (autoCommit) {
+ // must restore autoCommit
+ con.setAutoCommit(true);
+ conControl.setVoidCallable(1);
+ }
+ con.close();
+ conControl.setVoidCallable(1);
+ }
+
+ conControl.replay();
+ dsControl.replay();
+
+ final DataSource dsToUse = (lazyConnection ? new LazyConnectionDataSourceProxy(ds) : ds);
+ PlatformTransactionManager tm = new DataSourceTransactionManager(dsToUse);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(dsToUse));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(dsToUse));
+ assertTrue("Synchronization active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Is new transaction", status.isNewTransaction());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ Connection tCon = DataSourceUtils.getConnection(dsToUse);
+ try {
+ if (createStatement) {
+ tCon.createStatement();
+ assertEquals(con, new SimpleNativeJdbcExtractor().getNativeConnection(tCon));
+ }
+ }
+ catch (SQLException ex) {
+ throw new UncategorizedSQLException("", "", ex);
+ }
+ }
+ });
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(dsToUse));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ conControl.verify();
+ dsControl.verify();
+ }
+
+ public void testTransactionRollbackWithAutoCommitTrue() throws Exception {
+ doTestTransactionRollbackRestoringAutoCommit(true, false, false);
+ }
+
+ public void testTransactionRollbackWithAutoCommitFalse() throws Exception {
+ doTestTransactionRollbackRestoringAutoCommit(false, false, false);
+ }
+
+ public void testTransactionRollbackWithAutoCommitTrueAndLazyConnection() throws Exception {
+ doTestTransactionRollbackRestoringAutoCommit(true, true, false);
+ }
+
+ public void testTransactionRollbackWithAutoCommitFalseAndLazyConnection() throws Exception {
+ doTestTransactionRollbackRestoringAutoCommit(false, true, false);
+ }
+
+ public void testTransactionRollbackWithAutoCommitTrueAndLazyConnectionAndCreateStatement() throws Exception {
+ doTestTransactionRollbackRestoringAutoCommit(true, true, true);
+ }
+
+ public void testTransactionRollbackWithAutoCommitFalseAndLazyConnectionAndCreateStatement() throws Exception {
+ doTestTransactionRollbackRestoringAutoCommit(false, true, true);
+ }
+
+ private void doTestTransactionRollbackRestoringAutoCommit(
+ boolean autoCommit, boolean lazyConnection, final boolean createStatement) throws Exception {
+
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+
+ if (lazyConnection) {
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ con.getAutoCommit();
+ conControl.setReturnValue(autoCommit, 1);
+ con.getTransactionIsolation();
+ conControl.setReturnValue(Connection.TRANSACTION_READ_COMMITTED, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+ }
+
+ if (!lazyConnection || createStatement) {
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ con.getAutoCommit();
+ conControl.setReturnValue(autoCommit, 1);
+ if (autoCommit) {
+ // Must disable autocommit
+ con.setAutoCommit(false);
+ conControl.setVoidCallable(1);
+ }
+ if (createStatement) {
+ con.createStatement();
+ conControl.setReturnValue(null, 1);
+ }
+ con.rollback();
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ if (autoCommit) {
+ // Must restore autocommit
+ con.setAutoCommit(true);
+ conControl.setVoidCallable(1);
+ }
+ con.close();
+ conControl.setVoidCallable(1);
+ }
+
+ conControl.replay();
+ dsControl.replay();
+
+ final DataSource dsToUse = (lazyConnection ? new LazyConnectionDataSourceProxy(ds) : ds);
+ PlatformTransactionManager tm = new DataSourceTransactionManager(dsToUse);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(dsToUse));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ final RuntimeException ex = new RuntimeException("Application exception");
+ try {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(dsToUse));
+ assertTrue("Synchronization active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Is new transaction", status.isNewTransaction());
+ Connection con = DataSourceUtils.getConnection(dsToUse);
+ if (createStatement) {
+ try {
+ con.createStatement();
+ }
+ catch (SQLException ex) {
+ throw new UncategorizedSQLException("", "", ex);
+ }
+ }
+ throw ex;
+ }
+ });
+ fail("Should have thrown RuntimeException");
+ }
+ catch (RuntimeException ex2) {
+ // expected
+ assertTrue("Correct exception thrown", ex2.equals(ex));
+ }
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ conControl.verify();
+ dsControl.verify();
+ }
+
+ public void testTransactionRollbackOnly() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ conControl.replay();
+ dsControl.replay();
+
+ DataSourceTransactionManager tm = new DataSourceTransactionManager(ds);
+ tm.setTransactionSynchronization(DataSourceTransactionManager.SYNCHRONIZATION_NEVER);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ ConnectionHolder conHolder = new ConnectionHolder(con);
+ conHolder.setTransactionActive(true);
+ TransactionSynchronizationManager.bindResource(ds, conHolder);
+ final RuntimeException ex = new RuntimeException("Application exception");
+ try {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Is existing transaction", !status.isNewTransaction());
+ throw ex;
+ }
+ });
+ fail("Should have thrown RuntimeException");
+ }
+ catch (RuntimeException ex2) {
+ // expected
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ assertEquals("Correct exception thrown", ex, ex2);
+ }
+ finally {
+ TransactionSynchronizationManager.unbindResource(ds);
+ }
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ conControl.verify();
+ dsControl.verify();
+ }
+
+ public void testParticipatingTransactionWithRollbackOnly() throws Exception {
+ doTestParticipatingTransactionWithRollbackOnly(false);
+ }
+
+ public void testParticipatingTransactionWithRollbackOnlyAndFailEarly() throws Exception {
+ doTestParticipatingTransactionWithRollbackOnly(true);
+ }
+
+ private void doTestParticipatingTransactionWithRollbackOnly(boolean failEarly) throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ con.getAutoCommit();
+ conControl.setReturnValue(false, 1);
+ con.rollback();
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ conControl.replay();
+ dsControl.replay();
+
+ DataSourceTransactionManager tm = new DataSourceTransactionManager(ds);
+ if (failEarly) {
+ tm.setFailEarlyOnGlobalRollbackOnly(true);
+ }
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition());
+ TestTransactionSynchronization synch =
+ new TestTransactionSynchronization(ds, TransactionSynchronization.STATUS_ROLLED_BACK);
+ TransactionSynchronizationManager.registerSynchronization(synch);
+
+ boolean outerTransactionBoundaryReached = false;
+ try {
+ assertTrue("Is new transaction", ts.isNewTransaction());
+
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Is existing transaction", !status.isNewTransaction());
+ assertFalse("Is not rollback-only", status.isRollbackOnly());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Is existing transaction", !status.isNewTransaction());
+ status.setRollbackOnly();
+ }
+ });
+ assertTrue("Is existing transaction", !status.isNewTransaction());
+ assertTrue("Is rollback-only", status.isRollbackOnly());
+ }
+ });
+
+ outerTransactionBoundaryReached = true;
+ tm.commit(ts);
+
+ fail("Should have thrown UnexpectedRollbackException");
+ }
+ catch (UnexpectedRollbackException ex) {
+ // expected
+ if (!outerTransactionBoundaryReached) {
+ tm.rollback(ts);
+ }
+ if (failEarly) {
+ assertFalse(outerTransactionBoundaryReached);
+ }
+ else {
+ assertTrue(outerTransactionBoundaryReached);
+ }
+ }
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertFalse(synch.beforeCommitCalled);
+ assertTrue(synch.beforeCompletionCalled);
+ assertFalse(synch.afterCommitCalled);
+ assertTrue(synch.afterCompletionCalled);
+ conControl.verify();
+ dsControl.verify();
+ }
+
+ public void testParticipatingTransactionWithIncompatibleIsolationLevel() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ con.getAutoCommit();
+ conControl.setReturnValue(false, 1);
+ con.rollback();
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ conControl.replay();
+ dsControl.replay();
+
+ DataSourceTransactionManager tm = new DataSourceTransactionManager(ds);
+ tm.setValidateExistingTransaction(true);
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ try {
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ final TransactionTemplate tt2 = new TransactionTemplate(tm);
+ tt2.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertFalse("Is not rollback-only", status.isRollbackOnly());
+ tt2.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ status.setRollbackOnly();
+ }
+ });
+ assertTrue("Is rollback-only", status.isRollbackOnly());
+ }
+ });
+
+ fail("Should have thrown IllegalTransactionStateException");
+ }
+ catch (IllegalTransactionStateException ex) {
+ // expected
+ }
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ conControl.verify();
+ dsControl.verify();
+ }
+
+ public void testParticipatingTransactionWithIncompatibleReadOnly() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ con.getAutoCommit();
+ conControl.setReturnValue(false, 1);
+ con.rollback();
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ conControl.replay();
+ dsControl.replay();
+
+ DataSourceTransactionManager tm = new DataSourceTransactionManager(ds);
+ tm.setValidateExistingTransaction(true);
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ try {
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setReadOnly(true);
+ final TransactionTemplate tt2 = new TransactionTemplate(tm);
+ tt2.setReadOnly(false);
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertFalse("Is not rollback-only", status.isRollbackOnly());
+ tt2.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ status.setRollbackOnly();
+ }
+ });
+ assertTrue("Is rollback-only", status.isRollbackOnly());
+ }
+ });
+
+ fail("Should have thrown IllegalTransactionStateException");
+ }
+ catch (IllegalTransactionStateException ex) {
+ // expected
+ }
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ conControl.verify();
+ dsControl.verify();
+ }
+
+ public void testParticipatingTransactionWithTransactionStartedFromSynch() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ con.getAutoCommit();
+ conControl.setReturnValue(false, 2);
+ con.commit();
+ conControl.setVoidCallable(2);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 2);
+ con.close();
+ conControl.setVoidCallable(2);
+
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 2);
+ conControl.replay();
+ dsControl.replay();
+
+ DataSourceTransactionManager tm = new DataSourceTransactionManager(ds);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+
+ final TestTransactionSynchronization synch =
+ new TestTransactionSynchronization(ds, TransactionSynchronization.STATUS_COMMITTED) {
+ public void afterCompletion(int status) {
+ super.afterCompletion(status);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ }
+ });
+ }
+ };
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ TransactionSynchronizationManager.registerSynchronization(synch);
+ }
+ });
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue(synch.beforeCommitCalled);
+ assertTrue(synch.beforeCompletionCalled);
+ assertTrue(synch.afterCommitCalled);
+ assertTrue(synch.afterCompletionCalled);
+ conControl.verify();
+ dsControl.verify();
+ }
+
+ public void testParticipatingTransactionWithRollbackOnlyAndInnerSynch() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ con.getAutoCommit();
+ conControl.setReturnValue(false, 1);
+ con.rollback();
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ conControl.replay();
+ dsControl.replay();
+
+ DataSourceTransactionManager tm = new DataSourceTransactionManager(ds);
+ tm.setTransactionSynchronization(DataSourceTransactionManager.SYNCHRONIZATION_NEVER);
+ DataSourceTransactionManager tm2 = new DataSourceTransactionManager(ds);
+ // tm has no synch enabled (used at outer level), tm2 has synch enabled (inner level)
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition());
+ final TestTransactionSynchronization synch =
+ new TestTransactionSynchronization(ds, TransactionSynchronization.STATUS_UNKNOWN);
+
+ try {
+ assertTrue("Is new transaction", ts.isNewTransaction());
+
+ final TransactionTemplate tt = new TransactionTemplate(tm2);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Is existing transaction", !status.isNewTransaction());
+ assertFalse("Is not rollback-only", status.isRollbackOnly());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Is existing transaction", !status.isNewTransaction());
+ status.setRollbackOnly();
+ }
+ });
+ assertTrue("Is existing transaction", !status.isNewTransaction());
+ assertTrue("Is rollback-only", status.isRollbackOnly());
+ TransactionSynchronizationManager.registerSynchronization(synch);
+ }
+ });
+
+ tm.commit(ts);
+
+ fail("Should have thrown UnexpectedRollbackException");
+ }
+ catch (UnexpectedRollbackException ex) {
+ // expected
+ }
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertFalse(synch.beforeCommitCalled);
+ assertTrue(synch.beforeCompletionCalled);
+ assertFalse(synch.afterCommitCalled);
+ assertTrue(synch.afterCompletionCalled);
+ conControl.verify();
+ dsControl.verify();
+ }
+
+ public void testPropagationRequiresNewWithExistingTransaction() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ con.getAutoCommit();
+ conControl.setReturnValue(false, 2);
+ con.rollback();
+ conControl.setVoidCallable(1);
+ con.commit();
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 2);
+ con.close();
+ conControl.setVoidCallable(2);
+
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 2);
+ conControl.replay();
+ dsControl.replay();
+
+ PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Is new transaction", status.isNewTransaction());
+ assertTrue("Synchronization active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Is new transaction", status.isNewTransaction());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ status.setRollbackOnly();
+ }
+ });
+ assertTrue("Is new transaction", status.isNewTransaction());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ }
+ });
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ conControl.verify();
+ dsControl.verify();
+ }
+
+ public void testPropagationRequiresNewWithExistingTransactionAndUnrelatedDataSource() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ con.getAutoCommit();
+ conControl.setReturnValue(false, 1);
+ con.commit();
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ conControl.replay();
+ dsControl.replay();
+
+ MockControl con2Control = MockControl.createControl(Connection.class);
+ Connection con2 = (Connection) con2Control.getMock();
+ con2.getAutoCommit();
+ con2Control.setReturnValue(false, 1);
+ con2.rollback();
+ con2Control.setVoidCallable(1);
+ con2.isReadOnly();
+ con2Control.setReturnValue(false, 1);
+ con2.close();
+ con2Control.setVoidCallable(1);
+
+ MockControl ds2Control = MockControl.createControl(DataSource.class);
+ final DataSource ds2 = (DataSource) ds2Control.getMock();
+ ds2.getConnection();
+ ds2Control.setReturnValue(con2, 1);
+ con2Control.replay();
+ ds2Control.replay();
+
+ PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+
+ PlatformTransactionManager tm2 = new DataSourceTransactionManager(ds2);
+ final TransactionTemplate tt2 = new TransactionTemplate(tm2);
+ tt2.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds2));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Is new transaction", status.isNewTransaction());
+ assertTrue("Synchronization active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ tt2.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Is new transaction", status.isNewTransaction());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ status.setRollbackOnly();
+ }
+ });
+ assertTrue("Is new transaction", status.isNewTransaction());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ }
+ });
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds2));
+ conControl.verify();
+ dsControl.verify();
+ con2Control.verify();
+ ds2Control.verify();
+ }
+
+ public void testPropagationRequiresNewWithExistingTransactionAndUnrelatedFailingDataSource() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ con.getAutoCommit();
+ conControl.setReturnValue(false, 1);
+ con.rollback();
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ conControl.replay();
+ dsControl.replay();
+
+ MockControl ds2Control = MockControl.createControl(DataSource.class);
+ final DataSource ds2 = (DataSource) ds2Control.getMock();
+ SQLException failure = new SQLException();
+ ds2.getConnection();
+ ds2Control.setThrowable(failure);
+ ds2Control.replay();
+
+ DataSourceTransactionManager tm = new DataSourceTransactionManager(ds);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+
+ DataSourceTransactionManager tm2 = new DataSourceTransactionManager(ds2);
+ tm2.setTransactionSynchronization(DataSourceTransactionManager.SYNCHRONIZATION_NEVER);
+ final TransactionTemplate tt2 = new TransactionTemplate(tm2);
+ tt2.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds2));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ try {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Is new transaction", status.isNewTransaction());
+ assertTrue("Synchronization active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ tt2.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ status.setRollbackOnly();
+ }
+ });
+ }
+ });
+ fail("Should have thrown CannotCreateTransactionException");
+ }
+ catch (CannotCreateTransactionException ex) {
+ assertSame(failure, ex.getCause());
+ }
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds2));
+ conControl.verify();
+ dsControl.verify();
+ ds2Control.verify();
+ }
+
+ public void testPropagationNotSupportedWithExistingTransaction() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ con.getAutoCommit();
+ conControl.setReturnValue(false, 1);
+ con.commit();
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ conControl.replay();
+ dsControl.replay();
+
+ PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Is new transaction", status.isNewTransaction());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Isn't new transaction", !status.isNewTransaction());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ status.setRollbackOnly();
+ }
+ });
+ assertTrue("Is new transaction", status.isNewTransaction());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ }
+ });
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ conControl.verify();
+ dsControl.verify();
+ }
+
+ public void testPropagationNeverWithExistingTransaction() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ con.getAutoCommit();
+ conControl.setReturnValue(false, 1);
+ con.rollback();
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ conControl.replay();
+ dsControl.replay();
+
+ PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ try {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Is new transaction", status.isNewTransaction());
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NEVER);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ fail("Should have thrown IllegalTransactionStateException");
+ }
+ });
+ fail("Should have thrown IllegalTransactionStateException");
+ }
+ });
+ }
+ catch (IllegalTransactionStateException ex) {
+ // expected
+ }
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ conControl.verify();
+ dsControl.verify();
+ }
+
+ public void testPropagationSupportsAndRequiresNew() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ final Connection con = (Connection) conControl.getMock();
+ con.getAutoCommit();
+ conControl.setReturnValue(false, 1);
+ con.commit();
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+
+ dsControl.replay();
+ conControl.replay();
+
+ final PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Synchronization active", TransactionSynchronizationManager.isSynchronizationActive());
+ TransactionTemplate tt2 = new TransactionTemplate(tm);
+ tt2.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ tt2.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Is new transaction", status.isNewTransaction());
+ assertSame(con, DataSourceUtils.getConnection(ds));
+ assertSame(con, DataSourceUtils.getConnection(ds));
+ }
+ });
+ }
+ });
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ dsControl.verify();
+ conControl.verify();
+ }
+
+ public void testPropagationSupportsAndRequiresNewWithEarlyAccess() throws Exception {
+ MockControl con1Control = MockControl.createControl(Connection.class);
+ final Connection con1 = (Connection) con1Control.getMock();
+ con1.close();
+ con1Control.setVoidCallable(1);
+
+ MockControl con2Control = MockControl.createControl(Connection.class);
+ final Connection con2 = (Connection) con2Control.getMock();
+ con2.getAutoCommit();
+ con2Control.setReturnValue(false, 1);
+ con2.commit();
+ con2Control.setVoidCallable(1);
+ con2.isReadOnly();
+ con2Control.setReturnValue(false, 1);
+ con2.close();
+ con2Control.setVoidCallable(1);
+
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con1, 1);
+ ds.getConnection();
+ dsControl.setReturnValue(con2, 1);
+
+ dsControl.replay();
+ con1Control.replay();
+ con2Control.replay();
+
+ final PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Synchronization active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertSame(con1, DataSourceUtils.getConnection(ds));
+ assertSame(con1, DataSourceUtils.getConnection(ds));
+ TransactionTemplate tt2 = new TransactionTemplate(tm);
+ tt2.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ tt2.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Is new transaction", status.isNewTransaction());
+ assertSame(con2, DataSourceUtils.getConnection(ds));
+ assertSame(con2, DataSourceUtils.getConnection(ds));
+ }
+ });
+ assertSame(con1, DataSourceUtils.getConnection(ds));
+ }
+ });
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ dsControl.verify();
+ con1Control.verify();
+ con2Control.verify();
+ }
+
+ public void testTransactionWithIsolationAndReadOnly() throws Exception {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ final Connection con = (Connection) conControl.getMock();
+
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ con.getTransactionIsolation();
+ conControl.setReturnValue(Connection.TRANSACTION_READ_COMMITTED, 1);
+ con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
+ conControl.setVoidCallable(1);
+ con.setReadOnly(true);
+ conControl.setVoidCallable(1);
+ con.getAutoCommit();
+ conControl.setReturnValue(true, 1);
+ con.setAutoCommit(false);
+ conControl.setVoidCallable(1);
+ con.commit();
+ conControl.setVoidCallable(1);
+ con.setAutoCommit(true);
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ con.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
+ conControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ conControl.replay();
+ dsControl.replay();
+
+ PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
+ tt.setReadOnly(true);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ // something transactional
+ }
+ });
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ conControl.verify();
+ dsControl.verify();
+ }
+
+ public void testTransactionWithLongTimeout() throws Exception {
+ doTestTransactionWithTimeout(10);
+ }
+
+ public void testTransactionWithShortTimeout() throws Exception {
+ doTestTransactionWithTimeout(1);
+ }
+
+ private void doTestTransactionWithTimeout(int timeout) throws Exception {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ final Connection con = (Connection) conControl.getMock();
+ MockControl psControl = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement ps = (PreparedStatement) psControl.getMock();
+
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ con.getAutoCommit();
+ conControl.setReturnValue(true, 1);
+ con.setAutoCommit(false);
+ conControl.setVoidCallable(1);
+ con.prepareStatement("some SQL statement");
+ conControl.setReturnValue(ps, 1);
+ if (timeout > 1) {
+ ps.setQueryTimeout(timeout - 1);
+ psControl.setVoidCallable(1);
+ con.commit();
+ }
+ else {
+ con.rollback();
+ }
+ conControl.setVoidCallable(1);
+ con.setAutoCommit(true);
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ psControl.replay();
+ conControl.replay();
+ dsControl.replay();
+
+ PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setTimeout(timeout);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+
+ try {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ try {
+ Thread.sleep(1500);
+ }
+ catch (InterruptedException ex) {
+ }
+ try {
+ Connection con = DataSourceUtils.getConnection(ds);
+ PreparedStatement ps = con.prepareStatement("some SQL statement");
+ DataSourceUtils.applyTransactionTimeout(ps, ds);
+ }
+ catch (SQLException ex) {
+ throw new DataAccessResourceFailureException("", ex);
+ }
+ }
+ });
+ if (timeout <= 1) {
+ fail("Should have thrown TransactionTimedOutException");
+ }
+ }
+ catch (TransactionTimedOutException ex) {
+ if (timeout <= 1) {
+ // expected
+ }
+ else {
+ throw ex;
+ }
+ }
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ conControl.verify();
+ dsControl.verify();
+ psControl.verify();
+ }
+
+ public void testTransactionAwareDataSourceProxy() throws Exception {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ final Connection con = (Connection) conControl.getMock();
+
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ con.getMetaData();
+ conControl.setReturnValue(null, 1);
+ con.getAutoCommit();
+ conControl.setReturnValue(true, 1);
+ con.setAutoCommit(false);
+ conControl.setVoidCallable(1);
+ con.commit();
+ conControl.setVoidCallable(1);
+ con.setAutoCommit(true);
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ conControl.replay();
+ dsControl.replay();
+
+ PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ assertEquals(con, DataSourceUtils.getConnection(ds));
+ TransactionAwareDataSourceProxy dsProxy = new TransactionAwareDataSourceProxy(ds);
+ try {
+ assertEquals(con, ((ConnectionProxy) dsProxy.getConnection()).getTargetConnection());
+ assertEquals(con, new SimpleNativeJdbcExtractor().getNativeConnection(dsProxy.getConnection()));
+ // should be ignored
+ dsProxy.getConnection().close();
+ }
+ catch (SQLException ex) {
+ throw new UncategorizedSQLException("", "", ex);
+ }
+ }
+ });
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ conControl.verify();
+ dsControl.verify();
+ }
+
+ public void testTransactionAwareDataSourceProxyWithSuspension() throws Exception {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ final Connection con = (Connection) conControl.getMock();
+
+ ds.getConnection();
+ dsControl.setReturnValue(con, 2);
+ con.getMetaData();
+ conControl.setReturnValue(null, 2);
+ con.getAutoCommit();
+ conControl.setReturnValue(true, 2);
+ con.setAutoCommit(false);
+ conControl.setVoidCallable(2);
+ con.commit();
+ conControl.setVoidCallable(2);
+ con.setAutoCommit(true);
+ conControl.setVoidCallable(2);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 2);
+ con.close();
+ conControl.setVoidCallable(2);
+
+ conControl.replay();
+ dsControl.replay();
+
+ PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ assertEquals(con, DataSourceUtils.getConnection(ds));
+ final TransactionAwareDataSourceProxy dsProxy = new TransactionAwareDataSourceProxy(ds);
+ try {
+ assertEquals(con, ((ConnectionProxy) dsProxy.getConnection()).getTargetConnection());
+ assertEquals(con, new SimpleNativeJdbcExtractor().getNativeConnection(dsProxy.getConnection()));
+ // should be ignored
+ dsProxy.getConnection().close();
+ }
+ catch (SQLException ex) {
+ throw new UncategorizedSQLException("", "", ex);
+ }
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ assertEquals(con, DataSourceUtils.getConnection(ds));
+ try {
+ assertEquals(con, ((ConnectionProxy) dsProxy.getConnection()).getTargetConnection());
+ assertEquals(con, new SimpleNativeJdbcExtractor().getNativeConnection(dsProxy.getConnection()));
+ // should be ignored
+ dsProxy.getConnection().close();
+ }
+ catch (SQLException ex) {
+ throw new UncategorizedSQLException("", "", ex);
+ }
+ }
+ });
+
+ try {
+ assertEquals(con, ((ConnectionProxy) dsProxy.getConnection()).getTargetConnection());
+ // should be ignored
+ dsProxy.getConnection().close();
+ }
+ catch (SQLException ex) {
+ throw new UncategorizedSQLException("", "", ex);
+ }
+ }
+ });
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ conControl.verify();
+ dsControl.verify();
+ }
+
+ public void testTransactionAwareDataSourceProxyWithSuspensionAndReobtaining() throws Exception {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ final Connection con = (Connection) conControl.getMock();
+
+ ds.getConnection();
+ dsControl.setReturnValue(con, 2);
+ con.getMetaData();
+ conControl.setReturnValue(null, 2);
+ con.getAutoCommit();
+ conControl.setReturnValue(true, 2);
+ con.setAutoCommit(false);
+ conControl.setVoidCallable(2);
+ con.commit();
+ conControl.setVoidCallable(2);
+ con.setAutoCommit(true);
+ conControl.setVoidCallable(2);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 2);
+ con.close();
+ conControl.setVoidCallable(2);
+
+ conControl.replay();
+ dsControl.replay();
+
+ PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ assertEquals(con, DataSourceUtils.getConnection(ds));
+ final TransactionAwareDataSourceProxy dsProxy = new TransactionAwareDataSourceProxy(ds);
+ dsProxy.setReobtainTransactionalConnections(true);
+ try {
+ assertEquals(con, ((ConnectionProxy) dsProxy.getConnection()).getTargetConnection());
+ assertEquals(con, new SimpleNativeJdbcExtractor().getNativeConnection(dsProxy.getConnection()));
+ // should be ignored
+ dsProxy.getConnection().close();
+ }
+ catch (SQLException ex) {
+ throw new UncategorizedSQLException("", "", ex);
+ }
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ assertEquals(con, DataSourceUtils.getConnection(ds));
+ try {
+ assertEquals(con, ((ConnectionProxy) dsProxy.getConnection()).getTargetConnection());
+ assertEquals(con, new SimpleNativeJdbcExtractor().getNativeConnection(dsProxy.getConnection()));
+ // should be ignored
+ dsProxy.getConnection().close();
+ }
+ catch (SQLException ex) {
+ throw new UncategorizedSQLException("", "", ex);
+ }
+ }
+ });
+
+ try {
+ assertEquals(con, ((ConnectionProxy) dsProxy.getConnection()).getTargetConnection());
+ // should be ignored
+ dsProxy.getConnection().close();
+ }
+ catch (SQLException ex) {
+ throw new UncategorizedSQLException("", "", ex);
+ }
+ }
+ });
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ conControl.verify();
+ dsControl.verify();
+ }
+
+ /**
+ * Test behavior if the first operation on a connection (getAutoCommit) throws SQLException.
+ */
+ public void testTransactionWithExceptionOnBegin() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ final Connection con = (Connection) conControl.getMock();
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ DataSource ds = (DataSource) dsControl.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ con.getAutoCommit();
+ conControl.setThrowable(new SQLException("Cannot begin"));
+ con.close();
+ conControl.setVoidCallable();
+ conControl.replay();
+ dsControl.replay();
+
+ PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ try {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ }
+ });
+ fail("Should have thrown CannotCreateTransactionException");
+ }
+ catch (CannotCreateTransactionException ex) {
+ // expected
+ }
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ conControl.verify();
+ }
+
+ public void testTransactionWithExceptionOnCommit() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ final Connection con = (Connection) conControl.getMock();
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ DataSource ds = (DataSource) dsControl.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ con.getAutoCommit();
+ // No need to restore it
+ conControl.setReturnValue(false, 1);
+ con.commit();
+ conControl.setThrowable(new SQLException("Cannot commit"), 1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+ conControl.replay();
+ dsControl.replay();
+
+ PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ try {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ }
+ });
+ fail("Should have thrown TransactionSystemException");
+ }
+ catch (TransactionSystemException ex) {
+ // expected
+ }
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ conControl.verify();
+ }
+
+ public void testTransactionWithExceptionOnCommitAndRollbackOnCommitFailure() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ final Connection con = (Connection) conControl.getMock();
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ DataSource ds = (DataSource) dsControl.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ con.getAutoCommit();
+ // No need to change or restore
+ conControl.setReturnValue(false);
+ con.commit();
+ conControl.setThrowable(new SQLException("Cannot commit"), 1);
+ con.rollback();
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+ conControl.replay();
+ dsControl.replay();
+
+ DataSourceTransactionManager tm = new DataSourceTransactionManager(ds);
+ tm.setRollbackOnCommitFailure(true);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ try {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ }
+ });
+ fail("Should have thrown TransactionSystemException");
+ }
+ catch (TransactionSystemException ex) {
+ // expected
+ }
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ conControl.verify();
+ }
+
+ public void testTransactionWithExceptionOnRollback() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ final Connection con = (Connection) conControl.getMock();
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ DataSource ds = (DataSource) dsControl.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ con.getAutoCommit();
+ conControl.setReturnValue(true, 1);
+ // Must restore
+ con.setAutoCommit(false);
+ conControl.setVoidCallable(1);
+
+ con.rollback();
+ conControl.setThrowable(new SQLException("Cannot rollback"), 1);
+ con.setAutoCommit(true);
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+ conControl.replay();
+ dsControl.replay();
+
+ PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ try {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ status.setRollbackOnly();
+ }
+ });
+ fail("Should have thrown TransactionSystemException");
+ }
+ catch (TransactionSystemException ex) {
+ // expected
+ }
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ conControl.verify();
+ }
+
+ public void testTransactionWithPropagationSupports() throws Exception {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ dsControl.replay();
+
+ PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Is not new transaction", !status.isNewTransaction());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ }
+ });
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ dsControl.verify();
+ }
+
+ public void testTransactionWithPropagationNotSupported() throws Exception {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ dsControl.replay();
+
+ PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Is not new transaction", !status.isNewTransaction());
+ }
+ });
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ dsControl.verify();
+ }
+
+ public void testTransactionWithPropagationNever() throws Exception {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ dsControl.replay();
+
+ PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NEVER);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Is not new transaction", !status.isNewTransaction());
+ }
+ });
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ dsControl.verify();
+ }
+
+ public void testExistingTransactionWithPropagationNested() throws Exception {
+ doTestExistingTransactionWithPropagationNested(1);
+ }
+
+ public void testExistingTransactionWithPropagationNestedTwice() throws Exception {
+ doTestExistingTransactionWithPropagationNested(2);
+ }
+
+ private void doTestExistingTransactionWithPropagationNested(final int count) throws Exception {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl mdControl = MockControl.createControl(DatabaseMetaData.class);
+ DatabaseMetaData md = (DatabaseMetaData) mdControl.getMock();
+ MockControl spControl = MockControl.createControl(Savepoint.class);
+ Savepoint sp = (Savepoint) spControl.getMock();
+
+ con.getAutoCommit();
+ conControl.setReturnValue(false, 1);
+ md.supportsSavepoints();
+ mdControl.setReturnValue(true, 1);
+ con.getMetaData();
+ conControl.setReturnValue(md, 1);
+ for (int i = 1; i <= count; i++) {
+ con.setSavepoint(ConnectionHolder.SAVEPOINT_NAME_PREFIX + i);
+ conControl.setReturnValue(sp, 1);
+ con.releaseSavepoint(sp);
+ conControl.setVoidCallable(1);
+ }
+ con.commit();
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+
+ spControl.replay();
+ mdControl.replay();
+ conControl.replay();
+ dsControl.replay();
+
+ PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Is new transaction", status.isNewTransaction());
+ assertTrue("Isn't nested transaction", !status.hasSavepoint());
+ for (int i = 0; i < count; i++) {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Isn't new transaction", !status.isNewTransaction());
+ assertTrue("Is nested transaction", status.hasSavepoint());
+ }
+ });
+ }
+ assertTrue("Is new transaction", status.isNewTransaction());
+ assertTrue("Isn't nested transaction", !status.hasSavepoint());
+ }
+ });
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ spControl.verify();
+ mdControl.verify();
+ conControl.verify();
+ dsControl.verify();
+ }
+
+ public void testExistingTransactionWithPropagationNestedAndRollback() throws Exception {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl mdControl = MockControl.createControl(DatabaseMetaData.class);
+ DatabaseMetaData md = (DatabaseMetaData) mdControl.getMock();
+ MockControl spControl = MockControl.createControl(Savepoint.class);
+ Savepoint sp = (Savepoint) spControl.getMock();
+
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ con.getAutoCommit();
+ conControl.setReturnValue(false, 1);
+ md.supportsSavepoints();
+ mdControl.setReturnValue(true, 1);
+ con.getMetaData();
+ conControl.setReturnValue(md, 1);
+ con.setSavepoint("SAVEPOINT_1");
+ conControl.setReturnValue(sp, 1);
+ con.rollback(sp);
+ conControl.setVoidCallable(1);
+ con.commit();
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ spControl.replay();
+ mdControl.replay();
+ conControl.replay();
+ dsControl.replay();
+
+ PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Is new transaction", status.isNewTransaction());
+ assertTrue("Isn't nested transaction", !status.hasSavepoint());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Isn't new transaction", !status.isNewTransaction());
+ assertTrue("Is nested transaction", status.hasSavepoint());
+ status.setRollbackOnly();
+ }
+ });
+ assertTrue("Is new transaction", status.isNewTransaction());
+ assertTrue("Isn't nested transaction", !status.hasSavepoint());
+ }
+ });
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ spControl.verify();
+ mdControl.verify();
+ conControl.verify();
+ dsControl.verify();
+ }
+
+ public void testExistingTransactionWithManualSavepoint() throws Exception {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl mdControl = MockControl.createControl(DatabaseMetaData.class);
+ DatabaseMetaData md = (DatabaseMetaData) mdControl.getMock();
+ MockControl spControl = MockControl.createControl(Savepoint.class);
+ Savepoint sp = (Savepoint) spControl.getMock();
+
+ con.getAutoCommit();
+ conControl.setReturnValue(false, 1);
+ md.supportsSavepoints();
+ mdControl.setReturnValue(true, 1);
+ con.getMetaData();
+ conControl.setReturnValue(md, 1);
+ con.setSavepoint("SAVEPOINT_1");
+ conControl.setReturnValue(sp, 1);
+ con.releaseSavepoint(sp);
+ conControl.setVoidCallable(1);
+ con.commit();
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+
+ spControl.replay();
+ mdControl.replay();
+ conControl.replay();
+ dsControl.replay();
+
+ PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Is new transaction", status.isNewTransaction());
+ Object savepoint = status.createSavepoint();
+ status.releaseSavepoint(savepoint);
+ assertTrue("Is new transaction", status.isNewTransaction());
+ }
+ });
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ spControl.verify();
+ mdControl.verify();
+ conControl.verify();
+ dsControl.verify();
+ }
+
+ public void testExistingTransactionWithManualSavepointAndRollback() throws Exception {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl mdControl = MockControl.createControl(DatabaseMetaData.class);
+ DatabaseMetaData md = (DatabaseMetaData) mdControl.getMock();
+ MockControl spControl = MockControl.createControl(Savepoint.class);
+ Savepoint sp = (Savepoint) spControl.getMock();
+
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ con.getAutoCommit();
+ conControl.setReturnValue(false, 1);
+ md.supportsSavepoints();
+ mdControl.setReturnValue(true, 1);
+ con.getMetaData();
+ conControl.setReturnValue(md, 1);
+ con.setSavepoint("SAVEPOINT_1");
+ conControl.setReturnValue(sp, 1);
+ con.rollback(sp);
+ conControl.setVoidCallable(1);
+ con.commit();
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ spControl.replay();
+ mdControl.replay();
+ conControl.replay();
+ dsControl.replay();
+
+ PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Is new transaction", status.isNewTransaction());
+ Object savepoint = status.createSavepoint();
+ status.rollbackToSavepoint(savepoint);
+ assertTrue("Is new transaction", status.isNewTransaction());
+ }
+ });
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ spControl.verify();
+ mdControl.verify();
+ conControl.verify();
+ dsControl.verify();
+ }
+
+ public void testTransactionWithPropagationNested() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ con.getAutoCommit();
+ conControl.setReturnValue(false, 1);
+ con.commit();
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ conControl.replay();
+ dsControl.replay();
+
+ PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Is new transaction", status.isNewTransaction());
+ }
+ });
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ conControl.verify();
+ dsControl.verify();
+ }
+
+ public void testTransactionWithPropagationNestedAndRollback() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ con.getAutoCommit();
+ conControl.setReturnValue(false, 1);
+ con.rollback();
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con, 1);
+ conControl.replay();
+ dsControl.replay();
+
+ PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) throws RuntimeException {
+ assertTrue("Is new transaction", status.isNewTransaction());
+ status.setRollbackOnly();
+ }
+ });
+
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ conControl.verify();
+ dsControl.verify();
+ }
+
+ protected void tearDown() {
+ assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ }
+
+
+ private static class TestTransactionSynchronization implements TransactionSynchronization {
+
+ private DataSource dataSource;
+ private int status;
+
+ public boolean beforeCommitCalled;
+ public boolean beforeCompletionCalled;
+ public boolean afterCommitCalled;
+ public boolean afterCompletionCalled;
+
+ public TestTransactionSynchronization(DataSource dataSource, int status) {
+ this.dataSource = dataSource;
+ this.status = status;
+ }
+
+ public void suspend() {
+ }
+
+ public void resume() {
+ }
+
+ public void beforeCommit(boolean readOnly) {
+ if (this.status != TransactionSynchronization.STATUS_COMMITTED) {
+ fail("Should never be called");
+ }
+ assertFalse(this.beforeCommitCalled);
+ this.beforeCommitCalled = true;
+ }
+
+ public void beforeCompletion() {
+ assertFalse(this.beforeCompletionCalled);
+ this.beforeCompletionCalled = true;
+ }
+
+ public void afterCommit() {
+ if (this.status != TransactionSynchronization.STATUS_COMMITTED) {
+ fail("Should never be called");
+ }
+ assertFalse(this.afterCommitCalled);
+ this.afterCommitCalled = true;
+ }
+
+ public void afterCompletion(int status) {
+ assertFalse(this.afterCompletionCalled);
+ this.afterCompletionCalled = true;
+ assertTrue(status == this.status);
+ assertTrue(TransactionSynchronizationManager.hasResource(this.dataSource));
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/DriverManagerDataSourceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/DriverManagerDataSourceTests.java
new file mode 100644
index 00000000000..8696edf257d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/DriverManagerDataSourceTests.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.datasource;
+
+import java.sql.Connection;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+/**
+ * @author Rod Johnson
+ */
+public class DriverManagerDataSourceTests extends TestCase {
+
+ public void testStandardUsage() throws Exception {
+ final String jdbcUrl = "url";
+ final String uname = "uname";
+ final String pwd = "pwd";
+
+ MockControl ctrlConnection =
+ MockControl.createControl(Connection.class);
+ final Connection mockConnection = (Connection) ctrlConnection.getMock();
+ ctrlConnection.replay();
+
+ class TestDriverManagerDataSource extends DriverManagerDataSource {
+ protected Connection getConnectionFromDriverManager(String url, Properties props) {
+ assertEquals(jdbcUrl, url);
+ assertEquals(uname, props.getProperty("user"));
+ assertEquals(pwd, props.getProperty("password"));
+ return mockConnection;
+ }
+ }
+
+ DriverManagerDataSource ds = new TestDriverManagerDataSource();
+ //ds.setDriverClassName("foobar");
+ ds.setUrl(jdbcUrl);
+ ds.setUsername(uname);
+ ds.setPassword(pwd);
+
+ Connection actualCon = ds.getConnection();
+ assertTrue(actualCon == mockConnection);
+
+ assertTrue(ds.getUrl().equals(jdbcUrl));
+ assertTrue(ds.getPassword().equals(pwd));
+ assertTrue(ds.getUsername().equals(uname));
+
+ ctrlConnection.verify();
+ }
+
+ public void testUsageWithConnectionProperties() throws Exception {
+ final String jdbcUrl = "url";
+
+ final Properties connProps = new Properties();
+ connProps.setProperty("myProp", "myValue");
+ connProps.setProperty("yourProp", "yourValue");
+ connProps.setProperty("user", "uname");
+ connProps.setProperty("password", "pwd");
+
+ MockControl ctrlConnection =
+ MockControl.createControl(Connection.class);
+ final Connection mockConnection = (Connection) ctrlConnection.getMock();
+ ctrlConnection.replay();
+
+ class TestDriverManagerDataSource extends DriverManagerDataSource {
+ protected Connection getConnectionFromDriverManager(String url, Properties props) {
+ assertEquals(jdbcUrl, url);
+ assertEquals("uname", props.getProperty("user"));
+ assertEquals("pwd", props.getProperty("password"));
+ assertEquals("myValue", props.getProperty("myProp"));
+ assertEquals("yourValue", props.getProperty("yourProp"));
+ return mockConnection;
+ }
+ }
+
+ DriverManagerDataSource ds = new TestDriverManagerDataSource();
+ //ds.setDriverClassName("foobar");
+ ds.setUrl(jdbcUrl);
+ ds.setConnectionProperties(connProps);
+
+ Connection actualCon = ds.getConnection();
+ assertTrue(actualCon == mockConnection);
+
+ assertTrue(ds.getUrl().equals(jdbcUrl));
+
+ ctrlConnection.verify();
+ }
+
+ public void testUsageWithConnectionPropertiesAndUserCredentials() throws Exception {
+ final String jdbcUrl = "url";
+ final String uname = "uname";
+ final String pwd = "pwd";
+
+ final Properties connProps = new Properties();
+ connProps.setProperty("myProp", "myValue");
+ connProps.setProperty("yourProp", "yourValue");
+ connProps.setProperty("user", "uname2");
+ connProps.setProperty("password", "pwd2");
+
+ MockControl ctrlConnection =
+ MockControl.createControl(Connection.class);
+ final Connection mockConnection = (Connection) ctrlConnection.getMock();
+ ctrlConnection.replay();
+
+ class TestDriverManagerDataSource extends DriverManagerDataSource {
+ protected Connection getConnectionFromDriverManager(String url, Properties props) {
+ assertEquals(jdbcUrl, url);
+ assertEquals(uname, props.getProperty("user"));
+ assertEquals(pwd, props.getProperty("password"));
+ assertEquals("myValue", props.getProperty("myProp"));
+ assertEquals("yourValue", props.getProperty("yourProp"));
+ return mockConnection;
+ }
+ }
+
+ DriverManagerDataSource ds = new TestDriverManagerDataSource();
+ //ds.setDriverClassName("foobar");
+ ds.setUrl(jdbcUrl);
+ ds.setUsername(uname);
+ ds.setPassword(pwd);
+ ds.setConnectionProperties(connProps);
+
+ Connection actualCon = ds.getConnection();
+ assertTrue(actualCon == mockConnection);
+
+ assertTrue(ds.getUrl().equals(jdbcUrl));
+ assertTrue(ds.getPassword().equals(pwd));
+ assertTrue(ds.getUsername().equals(uname));
+
+ ctrlConnection.verify();
+ }
+
+ public void testInvalidClassName() throws Exception {
+ String bogusClassName = "foobar";
+ DriverManagerDataSource ds = new DriverManagerDataSource();
+ try {
+ ds.setDriverClassName(bogusClassName);
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // OK
+ assertTrue(ex.getCause() instanceof ClassNotFoundException);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/UserCredentialsDataSourceAdapterTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/UserCredentialsDataSourceAdapterTests.java
new file mode 100644
index 00000000000..d020c2113cc
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/UserCredentialsDataSourceAdapterTests.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jdbc.datasource;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import javax.sql.DataSource;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+/**
+ * @author Juergen Hoeller
+ * @since 28.05.2004
+ */
+public class UserCredentialsDataSourceAdapterTests extends TestCase {
+
+ public void testStaticCredentials() throws SQLException {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ ds.getConnection("user", "pw");
+ dsControl.setReturnValue(con);
+ dsControl.replay();
+ conControl.replay();
+
+ UserCredentialsDataSourceAdapter adapter = new UserCredentialsDataSourceAdapter();
+ adapter.setTargetDataSource(ds);
+ adapter.setUsername("user");
+ adapter.setPassword("pw");
+ assertEquals(con, adapter.getConnection());
+ }
+
+ public void testNoCredentials() throws SQLException {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ ds.getConnection();
+ dsControl.setReturnValue(con);
+ dsControl.replay();
+ conControl.replay();
+
+ UserCredentialsDataSourceAdapter adapter = new UserCredentialsDataSourceAdapter();
+ adapter.setTargetDataSource(ds);
+ assertEquals(con, adapter.getConnection());
+ }
+
+ public void testThreadBoundCredentials() throws SQLException {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ ds.getConnection("user", "pw");
+ dsControl.setReturnValue(con);
+ dsControl.replay();
+ conControl.replay();
+
+ UserCredentialsDataSourceAdapter adapter = new UserCredentialsDataSourceAdapter();
+ adapter.setTargetDataSource(ds);
+
+ adapter.setCredentialsForCurrentThread("user", "pw");
+ try {
+ assertEquals(con, adapter.getConnection());
+ }
+ finally {
+ adapter.removeCredentialsFromCurrentThread();
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/lookup/BeanFactoryDataSourceLookupTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/lookup/BeanFactoryDataSourceLookupTests.java
new file mode 100644
index 00000000000..30b78b33e54
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/lookup/BeanFactoryDataSourceLookupTests.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jdbc.datasource.lookup;
+
+import javax.sql.DataSource;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class BeanFactoryDataSourceLookupTests extends TestCase {
+
+ private static final String DATASOURCE_BEAN_NAME = "dataSource";
+
+
+ public void testLookupSunnyDay() throws Exception {
+ MockControl mockBeanFactory = MockControl.createControl(BeanFactory.class);
+ BeanFactory beanFactory = (BeanFactory) mockBeanFactory.getMock();
+
+ beanFactory.getBean(DATASOURCE_BEAN_NAME, DataSource.class);
+ StubDataSource expectedDataSource = new StubDataSource();
+ mockBeanFactory.setReturnValue(expectedDataSource);
+
+ mockBeanFactory.replay();
+
+ BeanFactoryDataSourceLookup lookup = new BeanFactoryDataSourceLookup();
+ lookup.setBeanFactory(beanFactory);
+ DataSource dataSource = lookup.getDataSource(DATASOURCE_BEAN_NAME);
+ assertNotNull("A DataSourceLookup implementation must *never* return null from getDataSource(): this one obviously (and incorrectly) is", dataSource);
+ assertSame(expectedDataSource, dataSource);
+
+ mockBeanFactory.verify();
+ }
+
+ public void testLookupWhereBeanFactoryYieldsNonDataSourceType() throws Exception {
+ MockControl mockBeanFactory = MockControl.createControl(BeanFactory.class);
+ final BeanFactory beanFactory = (BeanFactory) mockBeanFactory.getMock();
+
+ beanFactory.getBean(DATASOURCE_BEAN_NAME, DataSource.class);
+ mockBeanFactory.setThrowable(new BeanNotOfRequiredTypeException(DATASOURCE_BEAN_NAME, DataSource.class, String.class));
+
+ mockBeanFactory.replay();
+
+ new AssertThrows(DataSourceLookupFailureException.class) {
+ public void test() throws Exception {
+ BeanFactoryDataSourceLookup lookup = new BeanFactoryDataSourceLookup(beanFactory);
+ lookup.getDataSource(DATASOURCE_BEAN_NAME);
+ }
+ }.runTest();
+
+ mockBeanFactory.verify();
+ }
+
+ public void testLookupWhereBeanFactoryHasNotBeenSupplied() throws Exception {
+ new AssertThrows(IllegalStateException.class) {
+ public void test() throws Exception {
+ BeanFactoryDataSourceLookup lookup = new BeanFactoryDataSourceLookup();
+ lookup.getDataSource(DATASOURCE_BEAN_NAME);
+ }
+ }.runTest();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/lookup/JndiDataSourceLookupTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/lookup/JndiDataSourceLookupTests.java
new file mode 100644
index 00000000000..eebfac250b9
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/lookup/JndiDataSourceLookupTests.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jdbc.datasource.lookup;
+
+import javax.naming.NamingException;
+import javax.sql.DataSource;
+
+import junit.framework.TestCase;
+
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Rick Evans
+ */
+public final class JndiDataSourceLookupTests extends TestCase {
+
+ private static final String DATA_SOURCE_NAME = "Love is like a stove, burns you when it's hot";
+
+
+ public void testSunnyDay() throws Exception {
+ final DataSource expectedDataSource = new StubDataSource();
+ JndiDataSourceLookup lookup = new JndiDataSourceLookup() {
+ protected Object lookup(String jndiName, Class requiredType) {
+ assertEquals(DATA_SOURCE_NAME, jndiName);
+ return expectedDataSource;
+ }
+ };
+ DataSource dataSource = lookup.getDataSource(DATA_SOURCE_NAME);
+ assertNotNull("A DataSourceLookup implementation must *never* return null from getDataSource(): this one obviously (and incorrectly) is", dataSource);
+ assertSame(expectedDataSource, dataSource);
+ }
+
+ public void testNoDataSourceAtJndiLocation() throws Exception {
+ new AssertThrows(DataSourceLookupFailureException.class) {
+ public void test() throws Exception {
+ JndiDataSourceLookup lookup = new JndiDataSourceLookup() {
+ protected Object lookup(String jndiName, Class requiredType) throws NamingException {
+ assertEquals(DATA_SOURCE_NAME, jndiName);
+ throw new NamingException();
+ }
+ };
+ lookup.getDataSource(DATA_SOURCE_NAME);
+ }
+ }.runTest();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/lookup/MapDataSourceLookupTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/lookup/MapDataSourceLookupTests.java
new file mode 100644
index 00000000000..284c380a315
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/lookup/MapDataSourceLookupTests.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jdbc.datasource.lookup;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.sql.DataSource;
+
+import junit.framework.TestCase;
+
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Rick Evans
+ */
+public final class MapDataSourceLookupTests extends TestCase {
+
+ private static final String DATA_SOURCE_NAME = "dataSource";
+
+
+ public void testGetDataSourcesReturnsUnmodifiableMap() throws Exception {
+ new AssertThrows(UnsupportedOperationException.class, "The Map returned from getDataSources() *must* be unmodifiable") {
+ public void test() throws Exception {
+ MapDataSourceLookup lookup = new MapDataSourceLookup(new HashMap());
+ Map dataSources = lookup.getDataSources();
+ dataSources.put("", "");
+ }
+ }.runTest();
+ }
+
+ public void testLookupSunnyDay() throws Exception {
+ Map dataSources = new HashMap();
+ StubDataSource expectedDataSource = new StubDataSource();
+ dataSources.put(DATA_SOURCE_NAME, expectedDataSource);
+ MapDataSourceLookup lookup = new MapDataSourceLookup();
+ lookup.setDataSources(dataSources);
+ DataSource dataSource = lookup.getDataSource(DATA_SOURCE_NAME);
+ assertNotNull("A DataSourceLookup implementation must *never* return null from getDataSource(): this one obviously (and incorrectly) is", dataSource);
+ assertSame(expectedDataSource, dataSource);
+ }
+
+ public void testSettingDataSourceMapToNullIsAnIdempotentOperation() throws Exception {
+ Map dataSources = new HashMap();
+ StubDataSource expectedDataSource = new StubDataSource();
+ dataSources.put(DATA_SOURCE_NAME, expectedDataSource);
+ MapDataSourceLookup lookup = new MapDataSourceLookup();
+ lookup.setDataSources(dataSources);
+ lookup.setDataSources(null); // must be idempotent (i.e. the following lookup must still work);
+ DataSource dataSource = lookup.getDataSource(DATA_SOURCE_NAME);
+ assertNotNull("A DataSourceLookup implementation must *never* return null from getDataSource(): this one obviously (and incorrectly) is", dataSource);
+ assertSame(expectedDataSource, dataSource);
+ }
+
+ public void testAddingDataSourcePermitsOverride() throws Exception {
+ Map dataSources = new HashMap();
+ StubDataSource overridenDataSource = new StubDataSource();
+ StubDataSource expectedDataSource = new StubDataSource();
+ dataSources.put(DATA_SOURCE_NAME, overridenDataSource);
+ MapDataSourceLookup lookup = new MapDataSourceLookup();
+ lookup.setDataSources(dataSources);
+ lookup.addDataSource(DATA_SOURCE_NAME, expectedDataSource); // must override existing entry
+ DataSource dataSource = lookup.getDataSource(DATA_SOURCE_NAME);
+ assertNotNull("A DataSourceLookup implementation must *never* return null from getDataSource(): this one obviously (and incorrectly) is", dataSource);
+ assertSame(expectedDataSource, dataSource);
+ }
+
+ public void testGetDataSourceWhereSuppliedMapHasNonDataSourceTypeUnderSpecifiedKey() throws Exception {
+ new AssertThrows(DataSourceLookupFailureException.class) {
+ public void test() throws Exception {
+ Map dataSources = new HashMap();
+ dataSources.put(DATA_SOURCE_NAME, new Object());
+ MapDataSourceLookup lookup = new MapDataSourceLookup();
+ lookup.setDataSources(dataSources);
+ lookup.getDataSource(DATA_SOURCE_NAME);
+ }
+ }.runTest();
+ }
+
+ public void testGetDataSourceWhereSuppliedMapHasNoEntryForSpecifiedKey() throws Exception {
+ new AssertThrows(DataSourceLookupFailureException.class) {
+ public void test() throws Exception {
+ MapDataSourceLookup lookup = new MapDataSourceLookup();
+ lookup.getDataSource(DATA_SOURCE_NAME);
+ }
+ }.runTest();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/lookup/StubDataSource.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/lookup/StubDataSource.java
new file mode 100644
index 00000000000..22904830666
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/datasource/lookup/StubDataSource.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jdbc.datasource.lookup;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import org.springframework.jdbc.datasource.AbstractDataSource;
+
+/**
+ * Stub, do-nothing DataSource implementation.
+ *
+ *
All methods throw {@link UnsupportedOperationException}.
+ *
+ * @author Rick Evans
+ */
+class StubDataSource extends AbstractDataSource {
+
+ public Connection getConnection() throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+ public Connection getConnection(String username, String password) throws SQLException {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/object/BatchSqlUpdateTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/object/BatchSqlUpdateTests.java
new file mode 100644
index 00000000000..b635c3a0cbe
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/object/BatchSqlUpdateTests.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.object;
+
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.Types;
+
+import org.easymock.MockControl;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.jdbc.AbstractJdbcTests;
+import org.springframework.jdbc.core.SqlParameter;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+/**
+ * @author Juergen Hoeller
+ * @since 22.02.2005
+ */
+public class BatchSqlUpdateTests extends AbstractJdbcTests {
+
+ private final boolean debugEnabled = LogFactory.getLog(JdbcTemplate.class).isDebugEnabled();
+
+
+ public void testBatchUpdateWithExplicitFlush() throws Exception {
+ doTestBatchUpdate(false);
+ }
+
+ public void testBatchUpdateWithFlushThroughBatchSize() throws Exception {
+ doTestBatchUpdate(true);
+ }
+
+ private void doTestBatchUpdate(boolean flushThroughBatchSize) throws Exception {
+ final String sql = "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = ?";
+ final int[] ids = new int[] { 100, 200 };
+ final int[] rowsAffected = new int[] { 1, 2 };
+
+ MockControl ctrlPreparedStatement = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement mockPreparedStatement = (PreparedStatement) ctrlPreparedStatement.getMock();
+ mockPreparedStatement.getConnection();
+ ctrlPreparedStatement.setReturnValue(mockConnection);
+ mockPreparedStatement.setObject(1, new Integer(ids[0]), Types.INTEGER);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.addBatch();
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setObject(1, new Integer(ids[1]), Types.INTEGER);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.addBatch();
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeBatch();
+ ctrlPreparedStatement.setReturnValue(rowsAffected);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ MockControl ctrlDatabaseMetaData = MockControl.createControl(DatabaseMetaData.class);
+ DatabaseMetaData mockDatabaseMetaData = (DatabaseMetaData) ctrlDatabaseMetaData.getMock();
+ mockDatabaseMetaData.supportsBatchUpdates();
+ ctrlDatabaseMetaData.setReturnValue(true);
+
+ mockConnection.prepareStatement(sql);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+ mockConnection.getMetaData();
+ ctrlConnection.setReturnValue(mockDatabaseMetaData, 1);
+
+ ctrlPreparedStatement.replay();
+ ctrlDatabaseMetaData.replay();
+ replay();
+
+ BatchSqlUpdate update = new BatchSqlUpdate(mockDataSource, sql);
+ update.declareParameter(new SqlParameter(Types.INTEGER));
+ if (flushThroughBatchSize) {
+ update.setBatchSize(2);
+ }
+
+ update.update(ids[0]);
+ update.update(ids[1]);
+
+ if (flushThroughBatchSize) {
+ assertEquals(0, update.getQueueCount());
+ assertEquals(2, update.getRowsAffected().length);
+ }
+ else {
+ assertEquals(2, update.getQueueCount());
+ assertEquals(0, update.getRowsAffected().length);
+ }
+
+ int[] actualRowsAffected = update.flush();
+ assertEquals(0, update.getQueueCount());
+
+ if (flushThroughBatchSize) {
+ assertTrue("flush did not execute updates", actualRowsAffected.length == 0);
+ }
+ else {
+ assertTrue("executed 2 updates", actualRowsAffected.length == 2);
+ assertEquals(rowsAffected[0], actualRowsAffected[0]);
+ assertEquals(rowsAffected[1], actualRowsAffected[1]);
+ }
+
+ actualRowsAffected = update.getRowsAffected();
+ assertTrue("executed 2 updates", actualRowsAffected.length == 2);
+ assertEquals(rowsAffected[0], actualRowsAffected[0]);
+ assertEquals(rowsAffected[1], actualRowsAffected[1]);
+
+ update.reset();
+ assertEquals(0, update.getRowsAffected().length);
+
+ ctrlPreparedStatement.verify();
+ ctrlDatabaseMetaData.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/object/RdbmsOperationTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/object/RdbmsOperationTests.java
new file mode 100644
index 00000000000..e94bcc37293
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/object/RdbmsOperationTests.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jdbc.object;
+
+import java.sql.Types;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+
+import javax.sql.DataSource;
+
+import junit.framework.TestCase;
+
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.SqlInOutParameter;
+import org.springframework.jdbc.core.SqlOutParameter;
+import org.springframework.jdbc.core.SqlParameter;
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+
+/**
+ * @author Trevor Cook
+ * @author Juergen Hoeller
+ */
+public class RdbmsOperationTests extends TestCase {
+
+ public void testEmptySql() {
+ TestRdbmsOperation operation = new TestRdbmsOperation();
+ try {
+ operation.compile();
+ fail("Shouldn't allow compiling without sql statement");
+ }
+ catch (InvalidDataAccessApiUsageException idaauex) {
+ // OK
+ }
+ }
+
+ public void testSetTypeAfterCompile() {
+ TestRdbmsOperation operation = new TestRdbmsOperation();
+ operation.setDataSource(new DriverManagerDataSource());
+ operation.setSql("select * from mytable");
+ operation.compile();
+ try {
+ operation.setTypes(new int[] {Types.INTEGER });
+ fail("Shouldn't allow setting parameters after compile");
+ }
+ catch (InvalidDataAccessApiUsageException idaauex) {
+ // OK
+ }
+ }
+
+ public void testDeclareParameterAfterCompile() {
+ TestRdbmsOperation operation = new TestRdbmsOperation();
+ operation.setDataSource(new DriverManagerDataSource());
+ operation.setSql("select * from mytable");
+ operation.compile();
+ try {
+ operation.declareParameter(new SqlParameter(Types.INTEGER));
+ fail("Shouldn't allow setting parameters after compile");
+ }
+ catch (InvalidDataAccessApiUsageException idaauex) {
+ // OK
+ }
+ }
+
+ public void testTooFewParameters() {
+ TestRdbmsOperation operation = new TestRdbmsOperation();
+ operation.setSql("select * from mytable");
+ operation.setTypes(new int[] { Types.INTEGER });
+ try {
+ operation.validateParameters((Object[]) null);
+ fail("Shouldn't validate without enough parameters");
+ }
+ catch (InvalidDataAccessApiUsageException idaauex) {
+ // OK
+ }
+ }
+
+ public void testTooFewMapParameters() {
+ TestRdbmsOperation operation = new TestRdbmsOperation();
+ operation.setSql("select * from mytable");
+ operation.setTypes(new int[] { Types.INTEGER });
+ try {
+ operation.validateNamedParameters((Map) null);
+ fail("Shouldn't validate without enough parameters");
+ }
+ catch (InvalidDataAccessApiUsageException idaauex) {
+ // OK
+ }
+ }
+
+ public void testOperationConfiguredViaJdbcTemplateMustGetDataSource() throws Exception {
+ try {
+ TestRdbmsOperation operation = new TestRdbmsOperation();
+ operation.setSql("foo");
+ operation.compile();
+ fail("Can't compile without providing a DataSource for the JdbcTemplate");
+ }
+ catch (InvalidDataAccessApiUsageException ex) {
+ // Check for helpful error message. Omit leading character
+ // so as not to be fussy about case
+ assertTrue(ex.getMessage().indexOf("ataSource") != -1);
+ }
+ }
+
+ public void testTooManyParameters() {
+ TestRdbmsOperation operation = new TestRdbmsOperation();
+ operation.setSql("select * from mytable");
+ try {
+ operation.validateParameters(new Object[] {new Integer(1), new Integer(2)});
+ fail("Shouldn't validate with too many parameters");
+ }
+ catch (InvalidDataAccessApiUsageException idaauex) {
+ // OK
+ }
+ }
+
+ public void testUnspecifiedMapParameters() {
+ TestRdbmsOperation operation = new TestRdbmsOperation();
+ operation.setSql("select * from mytable");
+ try {
+ Map params = new HashMap();
+ params.put("col1", "value");
+ operation.validateNamedParameters(params);
+ fail("Shouldn't validate with unspecified parameters");
+ }
+ catch (InvalidDataAccessApiUsageException idaauex) {
+ // OK
+ }
+ }
+
+ public void testCompileTwice() {
+ TestRdbmsOperation operation = new TestRdbmsOperation();
+ operation.setDataSource(new DriverManagerDataSource());
+ operation.setSql("select * from mytable");
+ operation.setTypes(null);
+ operation.compile();
+ operation.compile();
+ }
+
+ public void testEmptyDataSource() {
+ SqlOperation operation = new SqlOperation() {
+ };
+ operation.setSql("select * from mytable");
+ try {
+ operation.compile();
+ fail("Shouldn't allow compiling without data source");
+ }
+ catch (InvalidDataAccessApiUsageException idaauex) {
+ // OK
+ }
+ }
+
+ public void testParameterPropagation() {
+ SqlOperation operation = new SqlOperation() {
+ };
+ DataSource ds = new DriverManagerDataSource();
+ operation.setDataSource(ds);
+ operation.setFetchSize(10);
+ operation.setMaxRows(20);
+ JdbcTemplate jt = operation.getJdbcTemplate();
+ assertEquals(ds, jt.getDataSource());
+ assertEquals(10, jt.getFetchSize());
+ assertEquals(20, jt.getMaxRows());
+ }
+
+ public void testValidateInOutParameter() {
+ TestRdbmsOperation operation = new TestRdbmsOperation();
+ operation.setDataSource(new DriverManagerDataSource());
+ operation.setSql("DUMMY_PROC");
+ operation.declareParameter(new SqlOutParameter("DUMMY_OUT_PARAM", Types.VARCHAR));
+ operation.declareParameter(new SqlInOutParameter("DUMMY_IN_OUT_PARAM", Types.VARCHAR));
+ operation.validateParameters(new Object[] {"DUMMY_VALUE1", "DUMMY_VALUE2"});
+ }
+
+ public void testParametersSetWithList() {
+ TestRdbmsOperation operation = new TestRdbmsOperation();
+ DataSource ds = new DriverManagerDataSource();
+ operation.setDataSource(ds);
+ operation.setSql("select * from mytable where one = ? and two = ?");
+ List l = new ArrayList();
+ l.add(new SqlParameter("one", Types.NUMERIC));
+ l.add(new SqlParameter("two", Types.VARCHAR));
+ operation.setParameters(new SqlParameter[] {
+ new SqlParameter("one", Types.NUMERIC),
+ new SqlParameter("two", Types.NUMERIC)});
+ operation.afterPropertiesSet();
+ try {
+ operation.validateParameters(new Object[] {new Integer(1), new String("2")});
+ assertEquals(2, operation.getDeclaredParameters().size());
+ // OK
+ }
+ catch (InvalidDataAccessApiUsageException idaauex) {
+ fail("Should have validated with parameters set using List: " + idaauex.getMessage());
+ }
+ }
+
+
+ private static class TestRdbmsOperation extends RdbmsOperation {
+
+ protected void compileInternal() {
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/object/SqlFunctionTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/object/SqlFunctionTests.java
new file mode 100644
index 00000000000..0def0f4f925
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/object/SqlFunctionTests.java
@@ -0,0 +1,339 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.object;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Types;
+
+import org.apache.commons.logging.LogFactory;
+import org.easymock.MockControl;
+
+import org.springframework.dao.IncorrectResultSizeDataAccessException;
+import org.springframework.jdbc.AbstractJdbcTests;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+/**
+ * @author Trevor Cook
+ */
+public class SqlFunctionTests extends AbstractJdbcTests {
+
+ private static final String FUNCTION = "select count(id) from mytable";
+ private static final String FUNCTION_INT =
+ "select count(id) from mytable where myparam = ?";
+ private static final String FUNCTION_MIXED =
+ "select count(id) from mytable where myparam = ? and mystring = ?";
+
+ private final boolean debugEnabled = LogFactory.getLog(JdbcTemplate.class).isDebugEnabled();
+
+ private MockControl ctrlPreparedStatement;
+ private PreparedStatement mockPreparedStatement;
+ private MockControl ctrlResultSet;
+ private ResultSet mockResultSet;
+ private MockControl ctrlResultSetMetaData;
+ private ResultSetMetaData mockResultSetMetaData;
+
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ ctrlPreparedStatement = MockControl.createControl(PreparedStatement.class);
+ mockPreparedStatement = (PreparedStatement) ctrlPreparedStatement.getMock();
+ ctrlResultSet = MockControl.createControl(ResultSet.class);
+ mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ ctrlResultSetMetaData = MockControl.createControl(ResultSetMetaData.class);
+ mockResultSetMetaData = (ResultSetMetaData) ctrlResultSetMetaData.getMock();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ if (shouldVerify()) {
+ ctrlPreparedStatement.verify();
+ ctrlResultSet.verify();
+ ctrlResultSetMetaData.verify();
+ }
+ }
+
+ protected void replay() {
+ super.replay();
+ ctrlPreparedStatement.replay();
+ ctrlResultSet.replay();
+ ctrlResultSetMetaData.replay();
+ }
+
+
+ public void testFunction() throws SQLException {
+ ctrlResultSetMetaData = MockControl.createControl(ResultSetMetaData.class);
+ mockResultSetMetaData = (ResultSetMetaData) ctrlResultSetMetaData.getMock();
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData, 1);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getObject(1);
+ ctrlResultSet.setReturnValue(new Integer(14));
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(FUNCTION);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ SqlFunction function = new SqlFunction();
+ function.setDataSource(mockDataSource);
+ function.setSql(FUNCTION);
+ function.compile();
+
+ int count = function.run();
+ assertTrue("Function returned value 14", count == 14);
+ }
+
+ public void testTooManyRows() throws SQLException {
+ ctrlResultSetMetaData = MockControl.createControl(ResultSetMetaData.class);
+ mockResultSetMetaData = (ResultSetMetaData) ctrlResultSetMetaData.getMock();
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1, 2);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData, 2);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getObject(1);
+ ctrlResultSet.setReturnValue(new Integer(14), 1);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getObject(1);
+ ctrlResultSet.setReturnValue(new Integer(15), 1);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(FUNCTION);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ SqlFunction function = new SqlFunction(mockDataSource, FUNCTION);
+ function.compile();
+
+ try {
+ int count = function.run();
+ fail("Shouldn't continue when too many rows returned");
+ }
+ catch (IncorrectResultSizeDataAccessException idaauex) {
+ // OK
+ }
+ }
+
+ public void testFunctionInt() throws SQLException {
+ ctrlResultSetMetaData = MockControl.createControl(ResultSetMetaData.class);
+ mockResultSetMetaData = (ResultSetMetaData) ctrlResultSetMetaData.getMock();
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData, 1);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getObject(1);
+ ctrlResultSet.setReturnValue(new Integer(14));
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(1), Types.INTEGER);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(FUNCTION_INT);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ SqlFunction function = new SqlFunction(mockDataSource, FUNCTION_INT);
+ function.setTypes(new int[] { Types.INTEGER });
+ function.compile();
+
+ int count = function.run(1);
+ assertTrue("Function returned value 14", count == 14);
+ }
+
+ public void testFunctionMixed() throws SQLException {
+ ctrlResultSetMetaData = MockControl.createControl(ResultSetMetaData.class);
+ mockResultSetMetaData = (ResultSetMetaData) ctrlResultSetMetaData.getMock();
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData, 1);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getObject(1);
+ ctrlResultSet.setReturnValue(new Integer(14));
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(1), Types.INTEGER);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setString(2, "rod");
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(FUNCTION_MIXED);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ SqlFunction function = new SqlFunction(
+ mockDataSource, FUNCTION_MIXED, new int[] { Types.INTEGER, Types.VARCHAR });
+ function.compile();
+
+ int count = function.run(new Object[] { new Integer(1), "rod" });
+ assertTrue("Function returned value 14", count == 14);
+ }
+
+ public void testFunctionWithStringResult() throws SQLException {
+ ctrlResultSetMetaData = MockControl.createControl(ResultSetMetaData.class);
+ mockResultSetMetaData = (ResultSetMetaData) ctrlResultSetMetaData.getMock();
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData, 1);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getObject(1);
+ ctrlResultSet.setReturnValue("14");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(1), Types.INTEGER);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setString(2, "rod");
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(FUNCTION_MIXED);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ SqlFunction function = new SqlFunction( mockDataSource, FUNCTION_MIXED);
+ function.setTypes(new int[] { Types.INTEGER, Types.VARCHAR });
+ function.compile();
+
+ String result = (String) function.runGeneric(new Object[] { new Integer(1), "rod" });
+ assertTrue("Function returned value 14", "14".equals(result));
+ }
+
+ public void testFunctionWithStringConvertedResult() throws SQLException {
+ ctrlResultSetMetaData = MockControl.createControl(ResultSetMetaData.class);
+ mockResultSetMetaData = (ResultSetMetaData) ctrlResultSetMetaData.getMock();
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData, 1);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getString(1);
+ ctrlResultSet.setReturnValue("14");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(1), Types.INTEGER);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setString(2, "rod");
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(FUNCTION_MIXED);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ SqlFunction function = new SqlFunction( mockDataSource, FUNCTION_MIXED);
+ function.setTypes(new int[] { Types.INTEGER, Types.VARCHAR });
+ function.setResultType(String.class);
+ function.compile();
+
+ String result = (String) function.runGeneric(new Object[] { new Integer(1), "rod" });
+ assertTrue("Function returned value 14", "14".equals(result));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/object/SqlQueryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/object/SqlQueryTests.java
new file mode 100644
index 00000000000..ba33117361f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/object/SqlQueryTests.java
@@ -0,0 +1,1160 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.object;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.sql.DataSource;
+
+import org.easymock.MockControl;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.dao.IncorrectResultSizeDataAccessException;
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+import org.springframework.jdbc.AbstractJdbcTests;
+import org.springframework.jdbc.Customer;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.SqlParameter;
+
+/**
+ * @author Trevor Cook
+ * @author Thomas Risberg
+ * @author Juergen Hoeller
+ */
+public class SqlQueryTests extends AbstractJdbcTests {
+
+ private static final String SELECT_ID = "select id from custmr";
+ private static final String SELECT_ID_WHERE =
+ "select id from custmr where forename = ? and id = ?";
+ private static final String SELECT_FORENAME = "select forename from custmr";
+ private static final String SELECT_FORENAME_EMPTY =
+ "select forename from custmr WHERE 1 = 2";
+ private static final String SELECT_ID_FORENAME_WHERE =
+ "select id, forename from prefix:custmr where forename = ?";
+ private static final String SELECT_ID_FORENAME_NAMED_PARAMETERS =
+ "select id, forename from custmr where id = :id and country = :country";
+ private static final String SELECT_ID_FORENAME_NAMED_PARAMETERS_PARSED =
+ "select id, forename from custmr where id = ? and country = ?";
+ private static final String SELECT_ID_FORENAME_WHERE_ID_IN_LIST_1 =
+ "select id, forename from custmr where id in (?, ?)";
+ private static final String SELECT_ID_FORENAME_WHERE_ID_IN_LIST_2 =
+ "select id, forename from custmr where id in (:ids)";
+ private static final String SELECT_ID_FORENAME_WHERE_ID_REUSED_1 =
+ "select id, forename from custmr where id = ? or id = ?)";
+ private static final String SELECT_ID_FORENAME_WHERE_ID_REUSED_2 =
+ "select id, forename from custmr where id = :id1 or id = :id1)";
+ private static final String SELECT_ID_FORENAME_WHERE_ID =
+ "select id, forename from custmr where id <= ?";
+
+ private static final String[] COLUMN_NAMES = new String[] {"id", "forename"};
+ private static final int[] COLUMN_TYPES = new int[] {Types.INTEGER, Types.VARCHAR};
+
+ private final boolean debugEnabled = LogFactory.getLog(JdbcTemplate.class).isDebugEnabled();
+
+ private MockControl ctrlPreparedStatement;
+ private PreparedStatement mockPreparedStatement;
+ private MockControl ctrlResultSet;
+ private ResultSet mockResultSet;
+
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ ctrlPreparedStatement = MockControl.createControl(PreparedStatement.class);
+ mockPreparedStatement = (PreparedStatement) ctrlPreparedStatement.getMock();
+ ctrlResultSet = MockControl.createControl(ResultSet.class);
+ mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ if (shouldVerify()) {
+ ctrlPreparedStatement.verify();
+ ctrlResultSet.verify();
+ }
+ }
+
+ protected void replay() {
+ super.replay();
+ ctrlPreparedStatement.replay();
+ ctrlResultSet.replay();
+ }
+
+
+ public void testQueryWithoutParams() throws SQLException {
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt(1);
+ ctrlResultSet.setReturnValue(1);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(SELECT_ID);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ SqlQuery query = new MappingSqlQueryWithParameters() {
+ protected Object mapRow(ResultSet rs, int rownum, Object[] params, Map context) throws SQLException {
+ assertTrue("params were null", params == null);
+ assertTrue("context was null", context == null);
+ return new Integer(rs.getInt(1));
+ }
+ };
+
+ query.setDataSource(mockDataSource);
+ query.setSql(SELECT_ID);
+ query.compile();
+ List list = query.execute();
+ assertTrue("Found customers", list.size() != 0);
+ for (Iterator itr = list.iterator(); itr.hasNext();) {
+ Integer id = (Integer) itr.next();
+ assertTrue(
+ "Customer id was assigned correctly",
+ id.intValue() == 1);
+ }
+ }
+
+ public void testQueryWithoutEnoughParams() {
+ replay();
+
+ MappingSqlQuery query = new MappingSqlQuery() {
+ protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
+ return new Integer(rs.getInt(1));
+ }
+
+ };
+ query.setDataSource(mockDataSource);
+ query.setSql(SELECT_ID_WHERE);
+ query.declareParameter(
+ new SqlParameter(COLUMN_NAMES[0], COLUMN_TYPES[0]));
+ query.declareParameter(
+ new SqlParameter(COLUMN_NAMES[1], COLUMN_TYPES[1]));
+ query.compile();
+
+ try {
+ List list = query.execute();
+ fail("Shouldn't succeed in running query without enough params");
+ }
+ catch (InvalidDataAccessApiUsageException ex) {
+ // OK
+ }
+ }
+
+ public void testQueryWithMissingMapParams() {
+ replay();
+
+ MappingSqlQuery query = new MappingSqlQuery() {
+ protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
+ return new Integer(rs.getInt(1));
+ }
+ };
+ query.setDataSource(mockDataSource);
+ query.setSql(SELECT_ID_WHERE);
+ query.declareParameter(
+ new SqlParameter(COLUMN_NAMES[0], COLUMN_TYPES[0]));
+ query.declareParameter(
+ new SqlParameter(COLUMN_NAMES[1], COLUMN_TYPES[1]));
+ query.compile();
+
+ try {
+ Map params = new HashMap();
+ params.put(COLUMN_NAMES[0], "Value");
+ List list = query.executeByNamedParam(params);
+ fail("Shouldn't succeed in running query with missing params");
+ }
+ catch (InvalidDataAccessApiUsageException ex) {
+ // OK
+ }
+ }
+
+ public void testStringQueryWithResults() throws Exception {
+ String[] dbResults = new String[] { "alpha", "beta", "charlie" };
+
+ MockControl[] ctrlCountResultSetMetaData = new MockControl[3];
+ ResultSetMetaData[] mockCountResultSetMetaData = new ResultSetMetaData[3];
+ MockControl[] ctrlCountResultSet = new MockControl[3];
+ ResultSet[] mockCountResultSet = new ResultSet[3];
+ MockControl[] ctrlCountPreparedStatement = new MockControl[3];
+ PreparedStatement[] mockCountPreparedStatement = new PreparedStatement[3];
+
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getString(1);
+ ctrlResultSet.setReturnValue(dbResults[0]);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getString(1);
+ ctrlResultSet.setReturnValue(dbResults[1]);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getString(1);
+ ctrlResultSet.setReturnValue(dbResults[2]);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(SELECT_FORENAME);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ for (int i = 0; i < dbResults.length; i++) {
+ ctrlCountResultSetMetaData[i] = MockControl.createControl(ResultSetMetaData.class);
+ mockCountResultSetMetaData[i] = (ResultSetMetaData) ctrlCountResultSetMetaData[i].getMock();
+ mockCountResultSetMetaData[i].getColumnCount();
+ ctrlCountResultSetMetaData[i].setReturnValue(1);
+
+ ctrlCountResultSet[i] = MockControl.createControl(ResultSet.class);
+ mockCountResultSet[i] = (ResultSet) ctrlCountResultSet[i].getMock();
+ mockCountResultSet[i].getMetaData();
+ ctrlCountResultSet[i].setReturnValue(mockCountResultSetMetaData[i]);
+ mockCountResultSet[i].next();
+ ctrlCountResultSet[i].setReturnValue(true);
+ mockCountResultSet[i].getInt(1);
+ ctrlCountResultSet[i].setReturnValue(1);
+ mockCountResultSet[i].wasNull();
+ ctrlCountResultSet[i].setReturnValue(false);
+ mockCountResultSet[i].next();
+ ctrlCountResultSet[i].setReturnValue(false);
+ mockCountResultSet[i].close();
+ ctrlCountResultSet[i].setVoidCallable();
+
+ ctrlCountPreparedStatement[i] = MockControl.createControl(PreparedStatement.class);
+ mockCountPreparedStatement[i] = (PreparedStatement) ctrlCountPreparedStatement[i].getMock();
+ mockCountPreparedStatement[i].executeQuery();
+ ctrlCountPreparedStatement[i].setReturnValue(mockCountResultSet[i]);
+ if (debugEnabled) {
+ mockCountPreparedStatement[i].getWarnings();
+ ctrlCountPreparedStatement[i].setReturnValue(null);
+ }
+ mockCountPreparedStatement[i].close();
+ ctrlCountPreparedStatement[i].setVoidCallable();
+
+ mockConnection.prepareStatement(
+ "SELECT COUNT(FORENAME) FROM CUSTMR WHERE FORENAME='" + dbResults[i] + "'");
+ ctrlConnection.setReturnValue(mockCountPreparedStatement[i]);
+
+ ctrlCountResultSetMetaData[i].replay();
+ ctrlCountResultSet[i].replay();
+ ctrlCountPreparedStatement[i].replay();
+ }
+
+ replay();
+
+ StringQuery query = new StringQuery(mockDataSource, SELECT_FORENAME);
+ query.setRowsExpected(3);
+ String[] results = query.run();
+ assertTrue("Array is non null", results != null);
+ assertTrue("Found results", results.length > 0);
+ assertTrue(
+ "Found expected number of results",
+ query.getRowsExpected() == 3);
+
+ JdbcTemplate helper = new JdbcTemplate(mockDataSource);
+ for (int i = 0; i < results.length; i++) {
+ // BREAKS ON ' in name
+ int dbCount = helper.queryForInt(
+ "SELECT COUNT(FORENAME) FROM CUSTMR WHERE FORENAME='" + results[i] + "'", (Object[]) null);
+ assertTrue("found in db", dbCount == 1);
+ }
+
+ for (int i = 0; i < dbResults.length; i++) {
+ ctrlCountResultSetMetaData[i].verify();
+ ctrlCountResultSet[i].verify();
+ ctrlCountPreparedStatement[i].verify();
+ }
+ }
+
+ public void testStringQueryWithoutResults() throws SQLException {
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(SELECT_FORENAME_EMPTY);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ StringQuery query = new StringQuery(mockDataSource, SELECT_FORENAME_EMPTY);
+ String[] results = query.run();
+ assertTrue("Array is non null", results != null);
+ assertTrue("Found 0 results", results.length == 0);
+ }
+
+ public void testFindCustomerIntInt() throws SQLException {
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt("id");
+ ctrlResultSet.setReturnValue(1);
+ mockResultSet.getString("forename");
+ ctrlResultSet.setReturnValue("rod");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(1), Types.NUMERIC);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setObject(2, new Integer(1), Types.NUMERIC);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(SELECT_ID_WHERE);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ class CustomerQuery extends MappingSqlQuery {
+
+ public CustomerQuery(DataSource ds) {
+ super(ds, SELECT_ID_WHERE);
+ declareParameter(new SqlParameter(Types.NUMERIC));
+ declareParameter(new SqlParameter(Types.NUMERIC));
+ compile();
+ }
+
+ protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
+ Customer cust = new Customer();
+ cust.setId(rs.getInt(COLUMN_NAMES[0]));
+ cust.setForename(rs.getString(COLUMN_NAMES[1]));
+ return cust;
+ }
+
+ public Customer findCustomer(int id, int otherNum) {
+ return (Customer) findObject(id, otherNum);
+ }
+ }
+
+ CustomerQuery query = new CustomerQuery(mockDataSource);
+ Customer cust = query.findCustomer(1, 1);
+
+ assertTrue("Customer id was assigned correctly", cust.getId() == 1);
+ assertTrue(
+ "Customer forename was assigned correctly",
+ cust.getForename().equals("rod"));
+ }
+
+ public void testFindCustomerString() throws SQLException {
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt("id");
+ ctrlResultSet.setReturnValue(1);
+ mockResultSet.getString("forename");
+ ctrlResultSet.setReturnValue("rod");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setString(1, "rod");
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(SELECT_ID_FORENAME_WHERE);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ class CustomerQuery extends MappingSqlQuery {
+
+ public CustomerQuery(DataSource ds) {
+ super(ds, SELECT_ID_FORENAME_WHERE);
+ declareParameter(new SqlParameter(Types.VARCHAR));
+ compile();
+ }
+
+ protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
+ Customer cust = new Customer();
+ cust.setId(rs.getInt(COLUMN_NAMES[0]));
+ cust.setForename(rs.getString(COLUMN_NAMES[1]));
+ return cust;
+ }
+
+ public Customer findCustomer(String id) {
+ return (Customer) findObject(id);
+ }
+ }
+
+ CustomerQuery query = new CustomerQuery(mockDataSource);
+ Customer cust = query.findCustomer("rod");
+
+ assertTrue("Customer id was assigned correctly", cust.getId() == 1);
+ assertTrue("Customer forename was assigned correctly", cust.getForename().equals("rod"));
+ }
+
+ public void testFindCustomerMixed() throws SQLException {
+ MockControl ctrlResultSet2;
+ ResultSet mockResultSet2;
+ MockControl ctrlPreparedStatement2;
+ PreparedStatement mockPreparedStatement2;
+
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt("id");
+ ctrlResultSet.setReturnValue(1);
+ mockResultSet.getString("forename");
+ ctrlResultSet.setReturnValue("rod");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(1), Types.INTEGER);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setString(2, "rod");
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ ctrlResultSet2 = MockControl.createControl(ResultSet.class);
+ mockResultSet2 = (ResultSet) ctrlResultSet2.getMock();
+ mockResultSet2.next();
+ ctrlResultSet2.setReturnValue(false);
+ mockResultSet2.close();
+ ctrlResultSet2.setVoidCallable();
+
+ ctrlPreparedStatement2 = MockControl.createControl(PreparedStatement.class);
+ mockPreparedStatement2 = (PreparedStatement) ctrlPreparedStatement2.getMock();
+ mockPreparedStatement2.setObject(1, new Integer(1), Types.INTEGER);
+ ctrlPreparedStatement2.setVoidCallable();
+ mockPreparedStatement2.setString(2, "Roger");
+ ctrlPreparedStatement2.setVoidCallable();
+ mockPreparedStatement2.executeQuery();
+ ctrlPreparedStatement2.setReturnValue(mockResultSet2);
+ if (debugEnabled) {
+ mockPreparedStatement2.getWarnings();
+ ctrlPreparedStatement2.setReturnValue(null);
+ }
+ mockPreparedStatement2.close();
+ ctrlPreparedStatement2.setVoidCallable();
+
+ mockConnection.prepareStatement(SELECT_ID_WHERE);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+ mockConnection.prepareStatement(SELECT_ID_WHERE);
+ ctrlConnection.setReturnValue(mockPreparedStatement2);
+
+ ctrlResultSet2.replay();
+ ctrlPreparedStatement2.replay();
+ replay();
+
+ class CustomerQuery extends MappingSqlQuery {
+
+ public CustomerQuery(DataSource ds) {
+ super(ds, SELECT_ID_WHERE);
+ declareParameter(
+ new SqlParameter(COLUMN_NAMES[0], COLUMN_TYPES[0]));
+ declareParameter(
+ new SqlParameter(COLUMN_NAMES[1], COLUMN_TYPES[1]));
+ compile();
+ }
+
+ protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
+ Customer cust = new Customer();
+ cust.setId(rs.getInt(COLUMN_NAMES[0]));
+ cust.setForename(rs.getString(COLUMN_NAMES[1]));
+ return cust;
+ }
+
+ public Customer findCustomer(int id, String name) {
+ return (Customer) findObject(
+ new Object[] { new Integer(id), name });
+ }
+ }
+
+ CustomerQuery query = new CustomerQuery(mockDataSource);
+
+ Customer cust1 = query.findCustomer(1, "rod");
+ assertTrue("Found customer", cust1 != null);
+ assertTrue("Customer id was assigned correctly", cust1.getId() == 1);
+
+ Customer cust2 = query.findCustomer(1, "Roger");
+ assertTrue("No customer found", cust2 == null);
+ }
+
+ public void testFindTooManyCustomers() throws SQLException {
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt("id");
+ ctrlResultSet.setReturnValue(1);
+ mockResultSet.getString("forename");
+ ctrlResultSet.setReturnValue("rod");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt("id");
+ ctrlResultSet.setReturnValue(2);
+ mockResultSet.getString("forename");
+ ctrlResultSet.setReturnValue("rod");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setString(1, "rod");
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(SELECT_ID_FORENAME_WHERE);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ class CustomerQuery extends MappingSqlQuery {
+
+ public CustomerQuery(DataSource ds) {
+ super(ds, SELECT_ID_FORENAME_WHERE);
+ declareParameter(new SqlParameter(Types.VARCHAR));
+ compile();
+ }
+
+ protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
+ Customer cust = new Customer();
+ cust.setId(rs.getInt(COLUMN_NAMES[0]));
+ cust.setForename(rs.getString(COLUMN_NAMES[1]));
+ return cust;
+ }
+
+ public Customer findCustomer(String id) {
+ return (Customer) findObject(id);
+ }
+ }
+
+ CustomerQuery query = new CustomerQuery(mockDataSource);
+ try {
+ Customer cust = query.findCustomer("rod");
+ fail("Should fail if more than one row found");
+ }
+ catch (IncorrectResultSizeDataAccessException ex) {
+ // OK
+ }
+ }
+
+ public void testListCustomersIntInt() throws SQLException {
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt("id");
+ ctrlResultSet.setReturnValue(1);
+ mockResultSet.getString("forename");
+ ctrlResultSet.setReturnValue("rod");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt("id");
+ ctrlResultSet.setReturnValue(2);
+ mockResultSet.getString("forename");
+ ctrlResultSet.setReturnValue("dave");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(1), Types.NUMERIC);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setObject(2, new Integer(1), Types.NUMERIC);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(SELECT_ID_WHERE);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ class CustomerQuery extends MappingSqlQuery {
+
+ public CustomerQuery(DataSource ds) {
+ super(ds, SELECT_ID_WHERE);
+ declareParameter(new SqlParameter(Types.NUMERIC));
+ declareParameter(new SqlParameter(Types.NUMERIC));
+ compile();
+ }
+
+ protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
+ Customer cust = new Customer();
+ cust.setId(rs.getInt(COLUMN_NAMES[0]));
+ cust.setForename(rs.getString(COLUMN_NAMES[1]));
+ return cust;
+ }
+ }
+
+ CustomerQuery query = new CustomerQuery(mockDataSource);
+ List list = query.execute(1, 1);
+ assertTrue("2 results in list", list.size() == 2);
+ for (Iterator itr = list.iterator(); itr.hasNext();) {
+ Customer cust = (Customer) itr.next();
+ }
+ }
+
+ public void testListCustomersString() throws SQLException {
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt("id");
+ ctrlResultSet.setReturnValue(1);
+ mockResultSet.getString("forename");
+ ctrlResultSet.setReturnValue("rod");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt("id");
+ ctrlResultSet.setReturnValue(2);
+ mockResultSet.getString("forename");
+ ctrlResultSet.setReturnValue("dave");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setString(1, "one");
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(SELECT_ID_FORENAME_WHERE);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ class CustomerQuery extends MappingSqlQuery {
+
+ public CustomerQuery(DataSource ds) {
+ super(ds, SELECT_ID_FORENAME_WHERE);
+ declareParameter(new SqlParameter(Types.VARCHAR));
+ compile();
+ }
+
+ protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
+ Customer cust = new Customer();
+ cust.setId(rs.getInt(COLUMN_NAMES[0]));
+ cust.setForename(rs.getString(COLUMN_NAMES[1]));
+ return cust;
+ }
+
+ }
+
+ CustomerQuery query = new CustomerQuery(mockDataSource);
+ List list = query.execute("one");
+ assertTrue("2 results in list", list.size() == 2);
+ for (Iterator itr = list.iterator(); itr.hasNext();) {
+ Customer cust = (Customer) itr.next();
+ }
+ }
+
+ public void testFancyCustomerQuery() throws SQLException {
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt("id");
+ ctrlResultSet.setReturnValue(1);
+ mockResultSet.getString("forename");
+ ctrlResultSet.setReturnValue("rod");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(1), Types.NUMERIC);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(
+ SELECT_ID_FORENAME_WHERE, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ class CustomerQuery extends MappingSqlQuery {
+
+ public CustomerQuery(DataSource ds) {
+ super(ds, SELECT_ID_FORENAME_WHERE);
+ setResultSetType(ResultSet.TYPE_SCROLL_SENSITIVE);
+ declareParameter(new SqlParameter(Types.NUMERIC));
+ compile();
+ }
+
+ protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
+ Customer cust = new Customer();
+ cust.setId(rs.getInt(COLUMN_NAMES[0]));
+ cust.setForename(rs.getString(COLUMN_NAMES[1]));
+ return cust;
+ }
+
+ public Customer findCustomer(int id) {
+ return (Customer) findObject(id);
+ }
+ }
+
+ CustomerQuery query = new CustomerQuery(mockDataSource);
+ Customer cust = query.findCustomer(1);
+ assertTrue("Customer id was assigned correctly", cust.getId() == 1);
+ assertTrue("Customer forename was assigned correctly", cust.getForename().equals("rod"));
+ }
+
+ public void testUnnamedParameterDeclarationWithNamedParameterQuery() throws SQLException {
+ replay();
+
+ class CustomerQuery extends MappingSqlQuery {
+
+ public CustomerQuery(DataSource ds) {
+ super(ds, SELECT_ID_FORENAME_WHERE);
+ setResultSetType(ResultSet.TYPE_SCROLL_SENSITIVE);
+ declareParameter(new SqlParameter(Types.NUMERIC));
+ compile();
+ }
+
+ protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
+ Customer cust = new Customer();
+ cust.setId(rs.getInt(COLUMN_NAMES[0]));
+ cust.setForename(rs.getString(COLUMN_NAMES[1]));
+ return cust;
+ }
+
+ public Customer findCustomer(int id) {
+ Map params = new HashMap();
+ params.put("id", new Integer(id));
+ return (Customer) executeByNamedParam(params).get(0);
+ }
+ }
+
+ CustomerQuery query = new CustomerQuery(mockDataSource);
+ try {
+ Customer cust = query.findCustomer(1);
+ fail("Query should not succeed since parameter declaration did not specify parameter name");
+ }
+ catch (InvalidDataAccessApiUsageException ex) {
+ // OK - it worked
+ }
+ }
+
+ public void testNamedParameterCustomerQueryWithUnnamedDeclarations() throws SQLException {
+ doTestNamedParameterCustomerQuery(false);
+ }
+
+ public void testNamedParameterCustomerQueryWithNamedDeclarations() throws SQLException {
+ doTestNamedParameterCustomerQuery(true);
+ }
+
+ private void doTestNamedParameterCustomerQuery(final boolean namedDeclarations) throws SQLException {
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt("id");
+ ctrlResultSet.setReturnValue(1);
+ mockResultSet.getString("forename");
+ ctrlResultSet.setReturnValue("rod");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(1), Types.NUMERIC);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setString(2, "UK");
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(
+ SELECT_ID_FORENAME_NAMED_PARAMETERS_PARSED, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ class CustomerQuery extends MappingSqlQuery {
+
+ public CustomerQuery(DataSource ds) {
+ super(ds, SELECT_ID_FORENAME_NAMED_PARAMETERS);
+ setResultSetType(ResultSet.TYPE_SCROLL_SENSITIVE);
+ if (namedDeclarations) {
+ declareParameter(new SqlParameter("country", Types.VARCHAR));
+ declareParameter(new SqlParameter("id", Types.NUMERIC));
+ }
+ else {
+ declareParameter(new SqlParameter(Types.NUMERIC));
+ declareParameter(new SqlParameter(Types.VARCHAR));
+ }
+ compile();
+ }
+
+ protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
+ Customer cust = new Customer();
+ cust.setId(rs.getInt(COLUMN_NAMES[0]));
+ cust.setForename(rs.getString(COLUMN_NAMES[1]));
+ return cust;
+ }
+
+ public Customer findCustomer(int id, String country) {
+ Map params = new HashMap();
+ params.put("id", new Integer(id));
+ params.put("country", country);
+ return (Customer) executeByNamedParam(params).get(0);
+ }
+ }
+
+ CustomerQuery query = new CustomerQuery(mockDataSource);
+ Customer cust = query.findCustomer(1, "UK");
+ assertTrue("Customer id was assigned correctly", cust.getId() == 1);
+ assertTrue("Customer forename was assigned correctly", cust.getForename().equals("rod"));
+ }
+
+ public void testNamedParameterInListQuery() throws SQLException {
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt("id");
+ ctrlResultSet.setReturnValue(1);
+ mockResultSet.getString("forename");
+ ctrlResultSet.setReturnValue("rod");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt("id");
+ ctrlResultSet.setReturnValue(2);
+ mockResultSet.getString("forename");
+ ctrlResultSet.setReturnValue("juergen");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(1), Types.NUMERIC);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setObject(2, new Integer(2), Types.NUMERIC);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(
+ SELECT_ID_FORENAME_WHERE_ID_IN_LIST_1, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ class CustomerQuery extends MappingSqlQuery {
+
+ public CustomerQuery(DataSource ds) {
+ super(ds, SELECT_ID_FORENAME_WHERE_ID_IN_LIST_2);
+ setResultSetType(ResultSet.TYPE_SCROLL_SENSITIVE);
+ declareParameter(new SqlParameter("ids", Types.NUMERIC));
+ compile();
+ }
+
+ protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
+ Customer cust = new Customer();
+ cust.setId(rs.getInt(COLUMN_NAMES[0]));
+ cust.setForename(rs.getString(COLUMN_NAMES[1]));
+ return cust;
+ }
+
+ public List findCustomers(List ids) {
+ Map params = new HashMap();
+ params.put("ids", ids);
+ return (List) executeByNamedParam(params);
+ }
+ }
+
+ CustomerQuery query = new CustomerQuery(mockDataSource);
+ List ids = new ArrayList();
+ ids.add(new Integer(1));
+ ids.add(new Integer(2));
+ List cust = query.findCustomers(ids);
+
+ assertEquals("We got two customers back", cust.size(), 2);
+ assertEquals("First customer id was assigned correctly", ((Customer)cust.get(0)).getId(), 1);
+ assertEquals("First customer forename was assigned correctly", ((Customer)cust.get(0)).getForename(), "rod");
+ assertEquals("Second customer id was assigned correctly", ((Customer)cust.get(1)).getId(), 2);
+ assertEquals("Second customer forename was assigned correctly", ((Customer)cust.get(1)).getForename(), "juergen");
+ }
+
+ public void testNamedParameterQueryReusingParameter() throws SQLException {
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt("id");
+ ctrlResultSet.setReturnValue(1);
+ mockResultSet.getString("forename");
+ ctrlResultSet.setReturnValue("rod");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt("id");
+ ctrlResultSet.setReturnValue(2);
+ mockResultSet.getString("forename");
+ ctrlResultSet.setReturnValue("juergen");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(1), Types.NUMERIC);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.setObject(2, new Integer(1), Types.NUMERIC);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(
+ SELECT_ID_FORENAME_WHERE_ID_REUSED_1, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ class CustomerQuery extends MappingSqlQuery {
+
+ public CustomerQuery(DataSource ds) {
+ super(ds, SELECT_ID_FORENAME_WHERE_ID_REUSED_2);
+ setResultSetType(ResultSet.TYPE_SCROLL_SENSITIVE);
+ declareParameter(new SqlParameter("id1", Types.NUMERIC));
+ compile();
+ }
+
+ protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
+ Customer cust = new Customer();
+ cust.setId(rs.getInt(COLUMN_NAMES[0]));
+ cust.setForename(rs.getString(COLUMN_NAMES[1]));
+ return cust;
+ }
+
+ public List findCustomers(Integer id) {
+ Map params = new HashMap();
+ params.put("id1", id);
+ return (List) executeByNamedParam(params);
+ }
+ }
+
+ CustomerQuery query = new CustomerQuery(mockDataSource);
+ List cust = query.findCustomers(new Integer(1));
+
+ assertEquals("We got two customers back", cust.size(), 2);
+ assertEquals("First customer id was assigned correctly", ((Customer)cust.get(0)).getId(), 1);
+ assertEquals("First customer forename was assigned correctly", ((Customer)cust.get(0)).getForename(), "rod");
+ assertEquals("Second customer id was assigned correctly", ((Customer)cust.get(1)).getId(), 2);
+ assertEquals("Second customer forename was assigned correctly", ((Customer)cust.get(1)).getForename(), "juergen");
+ }
+
+ public void testNamedParameterUsingInvalidQuestionMarkPlaceHolders() throws SQLException {
+
+ mockConnection.prepareStatement(
+ SELECT_ID_FORENAME_WHERE_ID_REUSED_1, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ class CustomerQuery extends MappingSqlQuery {
+
+ public CustomerQuery(DataSource ds) {
+ super(ds, SELECT_ID_FORENAME_WHERE_ID_REUSED_1);
+ setResultSetType(ResultSet.TYPE_SCROLL_SENSITIVE);
+ declareParameter(new SqlParameter("id1", Types.NUMERIC));
+ compile();
+ }
+
+ protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
+ Customer cust = new Customer();
+ cust.setId(rs.getInt(COLUMN_NAMES[0]));
+ cust.setForename(rs.getString(COLUMN_NAMES[1]));
+ return cust;
+ }
+
+ public List findCustomers(Integer id1) {
+ Map params = new HashMap();
+ params.put("id1", id1);
+ return (List) executeByNamedParam(params);
+ }
+ }
+
+ CustomerQuery query = new CustomerQuery(mockDataSource);
+ try {
+ List cust = query.findCustomers(new Integer(1));
+ fail("Should have caused an InvalidDataAccessApiUsageException");
+ }
+ catch (InvalidDataAccessApiUsageException e){
+ }
+
+ }
+
+ public void testUpdateCustomers() throws SQLException {
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt("id");
+ ctrlResultSet.setReturnValue(1);
+ mockResultSet.updateString(2, "Rod");
+ ctrlResultSet.setVoidCallable();
+ mockResultSet.updateRow();
+ ctrlResultSet.setVoidCallable();
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getInt("id");
+ ctrlResultSet.setReturnValue(2);
+ mockResultSet.updateString(2, "Thomas");
+ ctrlResultSet.setVoidCallable();
+ mockResultSet.updateRow();
+ ctrlResultSet.setVoidCallable();
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setObject(1, new Integer(2), Types.NUMERIC);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeQuery();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(
+ SELECT_ID_FORENAME_WHERE_ID, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ class CustomerUpdateQuery extends UpdatableSqlQuery {
+
+ public CustomerUpdateQuery(DataSource ds) {
+ super(ds, SELECT_ID_FORENAME_WHERE_ID);
+ declareParameter(new SqlParameter(Types.NUMERIC));
+ compile();
+ }
+
+ protected Object updateRow(ResultSet rs, int rownum, Map context) throws SQLException {
+ rs.updateString(2, "" + context.get(new Integer(rs.getInt(COLUMN_NAMES[0]))));
+ return null;
+ }
+ }
+ CustomerUpdateQuery query = new CustomerUpdateQuery(mockDataSource);
+ Map values = new HashMap(2);
+ values.put(new Integer(1), "Rod");
+ values.put(new Integer(2), "Thomas");
+ List customers = query.execute(2, values);
+ }
+
+
+ private static class StringQuery extends MappingSqlQuery {
+
+ public StringQuery(DataSource ds, String sql) {
+ super(ds, sql);
+ compile();
+ }
+
+ protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
+ return rs.getString(1);
+ }
+
+ public String[] run() {
+ List list = execute();
+ String[] results = (String[]) list.toArray(new String[list.size()]);
+ return results;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/object/SqlUpdateTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/object/SqlUpdateTests.java
new file mode 100644
index 00000000000..9493b5fbbf8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/object/SqlUpdateTests.java
@@ -0,0 +1,585 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.object;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.easymock.MockControl;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.core.JdkVersion;
+import org.springframework.jdbc.AbstractJdbcTests;
+import org.springframework.jdbc.JdbcUpdateAffectedIncorrectNumberOfRowsException;
+import org.springframework.jdbc.core.SqlParameter;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.support.GeneratedKeyHolder;
+import org.springframework.jdbc.support.KeyHolder;
+
+/**
+ * @author Trevor Cook
+ * @author Thomas Risberg
+ * @author Juergen Hoeller
+ */
+public class SqlUpdateTests extends AbstractJdbcTests {
+
+ private static final String UPDATE =
+ "update seat_status set booking_id = null";
+ private static final String UPDATE_INT =
+ "update seat_status set booking_id = null where performance_id = ?";
+ private static final String UPDATE_INT_INT =
+ "update seat_status set booking_id = null where performance_id = ? and price_band_id = ?";
+ private static final String UPDATE_NAMED_PARAMETERS =
+ "update seat_status set booking_id = null where performance_id = :perfId and price_band_id = :priceId";
+ private static final String UPDATE_STRING =
+ "update seat_status set booking_id = null where name = ?";
+ private static final String UPDATE_OBJECTS =
+ "update seat_status set booking_id = null where performance_id = ? and price_band_id = ? and name = ? and confirmed = ?";
+ private static final String INSERT_GENERATE_KEYS =
+ "insert into show (name) values(?)";
+
+ private final boolean debugEnabled = LogFactory.getLog(JdbcTemplate.class).isDebugEnabled();
+
+ private MockControl ctrlPreparedStatement;
+ private PreparedStatement mockPreparedStatement;
+ private MockControl ctrlResultSet;
+ private ResultSet mockResultSet;
+ private MockControl ctrlResultSetMetaData;
+ private ResultSetMetaData mockResultSetMetaData;
+
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ ctrlPreparedStatement = MockControl.createControl(PreparedStatement.class);
+ mockPreparedStatement = (PreparedStatement) ctrlPreparedStatement.getMock();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ if (shouldVerify()) {
+ ctrlPreparedStatement.verify();
+ }
+ }
+
+ protected void replay() {
+ super.replay();
+ ctrlPreparedStatement.replay();
+ }
+
+
+ public void testUpdate() throws SQLException {
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(1);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(UPDATE);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ Updater pc = new Updater();
+ int rowsAffected = pc.run();
+ assertEquals(1, rowsAffected);
+ }
+
+ public void testUpdateInt() throws SQLException {
+ mockPreparedStatement.setObject(1, new Integer(1), Types.NUMERIC);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(1);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(UPDATE_INT);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ IntUpdater pc = new IntUpdater();
+ int rowsAffected = pc.run(1);
+ assertEquals(1, rowsAffected);
+ }
+
+ public void testUpdateIntInt() throws SQLException {
+ mockPreparedStatement.setObject(1, new Integer(1), Types.NUMERIC);
+ mockPreparedStatement.setObject(2, new Integer(1), Types.NUMERIC);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(1);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(UPDATE_INT_INT);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ IntIntUpdater pc = new IntIntUpdater();
+ int rowsAffected = pc.run(1, 1);
+ assertEquals(1, rowsAffected);
+ }
+
+ public void testNamedParameterUpdateWithUnnamedDeclarations() throws SQLException {
+ doTestNamedParameterUpdate(false);
+ }
+
+ public void testNamedParameterUpdateWithNamedDeclarations() throws SQLException {
+ doTestNamedParameterUpdate(true);
+ }
+
+ private void doTestNamedParameterUpdate(final boolean namedDeclarations) throws SQLException {
+ mockPreparedStatement.setObject(1, new Integer(1), Types.NUMERIC);
+ mockPreparedStatement.setObject(2, new Integer(1), Types.DECIMAL);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(1);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(UPDATE_INT_INT);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ class NamedParameterUpdater extends SqlUpdate {
+
+ public NamedParameterUpdater() {
+ setSql(UPDATE_NAMED_PARAMETERS);
+ setDataSource(mockDataSource);
+ if (namedDeclarations) {
+ declareParameter(new SqlParameter("priceId", Types.DECIMAL));
+ declareParameter(new SqlParameter("perfId", Types.NUMERIC));
+ }
+ else {
+ declareParameter(new SqlParameter(Types.NUMERIC));
+ declareParameter(new SqlParameter(Types.DECIMAL));
+ }
+ compile();
+ }
+
+ public int run(int performanceId, int type) {
+ Map params = new HashMap();
+ params.put("perfId", new Integer(performanceId));
+ params.put("priceId", new Integer(type));
+ return updateByNamedParam(params);
+ }
+ }
+
+ NamedParameterUpdater pc = new NamedParameterUpdater();
+ int rowsAffected = pc.run(1, 1);
+ assertEquals(1, rowsAffected);
+ }
+
+ public void testUpdateString() throws SQLException {
+ mockPreparedStatement.setString(1, "rod");
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(1);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(UPDATE_STRING);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ StringUpdater pc = new StringUpdater();
+ int rowsAffected = pc.run("rod");
+ assertEquals(1, rowsAffected);
+ }
+
+ public void testUpdateMixed() throws SQLException {
+ mockPreparedStatement.setObject(1, new Integer(1), Types.NUMERIC);
+ mockPreparedStatement.setObject(2, new Integer(1), Types.NUMERIC, 2);
+ mockPreparedStatement.setString(3, "rod");
+ mockPreparedStatement.setObject(4, Boolean.TRUE, Types.BOOLEAN);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(1);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(UPDATE_OBJECTS);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ MixedUpdater pc = new MixedUpdater();
+ int rowsAffected = pc.run(1, 1, "rod", true);
+ assertEquals(1, rowsAffected);
+ }
+
+ public void testUpdateAndGeneratedKeys() throws SQLException {
+ ctrlResultSetMetaData = MockControl.createControl(ResultSetMetaData.class);
+ mockResultSetMetaData = (ResultSetMetaData) ctrlResultSetMetaData.getMock();
+ mockResultSetMetaData.getColumnCount();
+ ctrlResultSetMetaData.setReturnValue(1);
+ mockResultSetMetaData.getColumnLabel(1);
+ ctrlResultSetMetaData.setReturnValue("1", 2);
+
+ ctrlResultSet = MockControl.createControl(ResultSet.class);
+ mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ mockResultSet.getMetaData();
+ ctrlResultSet.setReturnValue(mockResultSetMetaData);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getObject(1);
+ ctrlResultSet.setReturnValue(new Integer(11));
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockPreparedStatement.setString(1, "rod");
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(1);
+ mockPreparedStatement.getGeneratedKeys();
+ ctrlPreparedStatement.setReturnValue(mockResultSet);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(INSERT_GENERATE_KEYS, PreparedStatement.RETURN_GENERATED_KEYS);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+ ctrlResultSet.replay();
+ ctrlResultSetMetaData.replay();
+
+ GeneratedKeysUpdater pc = new GeneratedKeysUpdater();
+ KeyHolder generatedKeyHolder = new GeneratedKeyHolder();
+ int rowsAffected = pc.run("rod", generatedKeyHolder);
+ assertEquals(1, rowsAffected);
+ assertEquals(1, generatedKeyHolder.getKeyList().size());
+ assertEquals(11, generatedKeyHolder.getKey().intValue());
+ }
+
+ public void testUpdateConstructor() throws SQLException {
+ mockPreparedStatement.setObject(1, new Integer(1), Types.NUMERIC);
+ mockPreparedStatement.setObject(2, new Integer(1), Types.NUMERIC);
+ mockPreparedStatement.setString(3, "rod");
+ mockPreparedStatement.setObject(4, Boolean.TRUE, Types.BOOLEAN);
+ ctrlPreparedStatement.setVoidCallable();
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(1);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(UPDATE_OBJECTS);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ ConstructorUpdater pc = new ConstructorUpdater();
+ int rowsAffected = pc.run(1, 1, "rod", true);
+ assertEquals(1, rowsAffected);
+ }
+
+ public void testUnderMaxRows() throws SQLException {
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(3);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(UPDATE);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ MaxRowsUpdater pc = new MaxRowsUpdater();
+ int rowsAffected = pc.run();
+ assertEquals(3, rowsAffected);
+ }
+
+ public void testMaxRows() throws SQLException {
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(5);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(UPDATE);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ MaxRowsUpdater pc = new MaxRowsUpdater();
+ int rowsAffected = pc.run();
+ assertEquals(5, rowsAffected);
+ }
+
+ public void testOverMaxRows() throws SQLException {
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(8);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(UPDATE);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ MaxRowsUpdater pc = new MaxRowsUpdater();
+ try {
+ int rowsAffected = pc.run();
+ fail("Shouldn't continue when too many rows affected");
+ }
+ catch (JdbcUpdateAffectedIncorrectNumberOfRowsException juaicrex) {
+ // OK
+ }
+ }
+
+ public void testRequiredRows() throws SQLException {
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(3);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(UPDATE);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ RequiredRowsUpdater pc = new RequiredRowsUpdater();
+ int rowsAffected = pc.run();
+ assertEquals(3, rowsAffected);
+ }
+
+ public void testNotRequiredRows() throws SQLException {
+ mockPreparedStatement.executeUpdate();
+ ctrlPreparedStatement.setReturnValue(2);
+ if (debugEnabled) {
+ mockPreparedStatement.getWarnings();
+ ctrlPreparedStatement.setReturnValue(null);
+ }
+ mockPreparedStatement.close();
+ ctrlPreparedStatement.setVoidCallable();
+
+ mockConnection.prepareStatement(UPDATE);
+ ctrlConnection.setReturnValue(mockPreparedStatement);
+
+ replay();
+
+ RequiredRowsUpdater pc = new RequiredRowsUpdater();
+ try {
+ int rowsAffected = pc.run();
+ fail("Shouldn't continue when too many rows affected");
+ }
+ catch (JdbcUpdateAffectedIncorrectNumberOfRowsException juaicrex) {
+ // OK
+ }
+ }
+
+
+ private class Updater extends SqlUpdate {
+
+ public Updater() {
+ setSql(UPDATE);
+ setDataSource(mockDataSource);
+ compile();
+ }
+
+ public int run() {
+ return update();
+ }
+ }
+
+
+ private class IntUpdater extends SqlUpdate {
+
+ public IntUpdater() {
+ setSql(UPDATE_INT);
+ setDataSource(mockDataSource);
+ declareParameter(new SqlParameter(Types.NUMERIC));
+ compile();
+ }
+
+ public int run(int performanceId) {
+ return update(performanceId);
+ }
+ }
+
+
+ private class IntIntUpdater extends SqlUpdate {
+
+ public IntIntUpdater() {
+ setSql(UPDATE_INT_INT);
+ setDataSource(mockDataSource);
+ declareParameter(new SqlParameter(Types.NUMERIC));
+ declareParameter(new SqlParameter(Types.NUMERIC));
+ compile();
+ }
+
+ public int run(int performanceId, int type) {
+ return update(performanceId, type);
+ }
+ }
+
+
+ private class StringUpdater extends SqlUpdate {
+
+ public StringUpdater() {
+ setSql(UPDATE_STRING);
+ setDataSource(mockDataSource);
+ declareParameter(new SqlParameter(Types.VARCHAR));
+ compile();
+ }
+
+ public int run(String name) {
+ return update(name);
+ }
+ }
+
+
+ private class MixedUpdater extends SqlUpdate {
+
+ public MixedUpdater() {
+ setSql(UPDATE_OBJECTS);
+ setDataSource(mockDataSource);
+ declareParameter(new SqlParameter(Types.NUMERIC));
+ declareParameter(new SqlParameter(Types.NUMERIC, 2));
+ declareParameter(new SqlParameter(Types.VARCHAR));
+ declareParameter(new SqlParameter(Types.BOOLEAN));
+ compile();
+ }
+
+ public int run(int performanceId, int type, String name, boolean confirmed) {
+ Object[] params =
+ new Object[] {new Integer(performanceId), new Integer(type), name,
+ new Boolean(confirmed)};
+ return update(params);
+ }
+ }
+
+
+ private class GeneratedKeysUpdater extends SqlUpdate {
+
+ public GeneratedKeysUpdater() {
+ setSql(INSERT_GENERATE_KEYS);
+ setDataSource(mockDataSource);
+ declareParameter(new SqlParameter(Types.VARCHAR));
+ setReturnGeneratedKeys(true);
+ compile();
+ }
+
+ public int run(String name, KeyHolder generatedKeyHolder) {
+ Object[] params = new Object[] {name};
+ return update(params, generatedKeyHolder);
+ }
+ }
+
+
+ private class ConstructorUpdater extends SqlUpdate {
+
+ public ConstructorUpdater() {
+ super(mockDataSource, UPDATE_OBJECTS,
+ new int[] {Types.NUMERIC, Types.NUMERIC, Types.VARCHAR, Types.BOOLEAN });
+ compile();
+ }
+
+ public int run(int performanceId, int type, String name, boolean confirmed) {
+ Object[] params =
+ new Object[] {
+ new Integer(performanceId), new Integer(type), name, new Boolean(confirmed)};
+ return update(params);
+ }
+ }
+
+
+ private class MaxRowsUpdater extends SqlUpdate {
+
+ public MaxRowsUpdater() {
+ setSql(UPDATE);
+ setDataSource(mockDataSource);
+ setMaxRowsAffected(5);
+ compile();
+ }
+
+ public int run() {
+ return update();
+ }
+ }
+
+
+ private class RequiredRowsUpdater extends SqlUpdate {
+
+ public RequiredRowsUpdater() {
+ setSql(UPDATE);
+ setDataSource(mockDataSource);
+ setRequiredRowsAffected(3);
+ compile();
+ }
+
+ public int run() {
+ return update();
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/object/StoredProcedureTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/object/StoredProcedureTests.java
new file mode 100644
index 00000000000..29d4a751876
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/object/StoredProcedureTests.java
@@ -0,0 +1,1005 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.object;
+
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.sql.ResultSetMetaData;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.math.BigDecimal;
+
+import javax.sql.DataSource;
+
+import org.easymock.MockControl;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+import org.springframework.jdbc.AbstractJdbcTests;
+import org.springframework.jdbc.BadSqlGrammarException;
+import org.springframework.jdbc.core.CallableStatementCreator;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.ParameterMapper;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.SimpleRowCountCallbackHandler;
+import org.springframework.jdbc.core.SqlOutParameter;
+import org.springframework.jdbc.core.SqlParameter;
+import org.springframework.jdbc.core.SqlReturnResultSet;
+import org.springframework.jdbc.core.support.AbstractSqlTypeValue;
+import org.springframework.jdbc.datasource.ConnectionHolder;
+import org.springframework.jdbc.support.SQLExceptionTranslator;
+import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+
+/**
+ * @author Thomas Risberg
+ * @author Trevor Cook
+ * @author Rod Johnson
+ */
+public class StoredProcedureTests extends AbstractJdbcTests {
+
+ private final boolean debugEnabled = LogFactory.getLog(JdbcTemplate.class).isDebugEnabled();
+
+ private MockControl ctrlCallable;
+ private CallableStatement mockCallable;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ ctrlCallable = MockControl.createControl(CallableStatement.class);
+ mockCallable = (CallableStatement) ctrlCallable.getMock();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ if (shouldVerify()) {
+ ctrlCallable.verify();
+ }
+ }
+
+ protected void replay() {
+ super.replay();
+ ctrlCallable.replay();
+ }
+
+ public void testNoSuchStoredProcedure() throws Exception {
+ SQLException sex =
+ new SQLException(
+ "Syntax error or access violation exception",
+ "42000");
+ mockCallable.execute();
+ ctrlCallable.setThrowable(sex);
+ mockCallable.close();
+ ctrlCallable.setVoidCallable();
+
+ mockConnection.prepareCall(
+ "{call " + NoSuchStoredProcedure.SQL + "()}");
+ ctrlConnection.setReturnValue(mockCallable);
+
+ replay();
+
+ NoSuchStoredProcedure sproc = new NoSuchStoredProcedure(mockDataSource);
+ try {
+ sproc.execute();
+ fail("Shouldn't succeed in running stored procedure which doesn't exist");
+ } catch (BadSqlGrammarException ex) {
+ // OK
+ }
+ }
+
+ private void testAddInvoice(final int amount, final int custid)
+ throws Exception {
+ AddInvoice adder = new AddInvoice(mockDataSource);
+ int id = adder.execute(amount, custid);
+ assertEquals(4, id);
+ }
+
+ public void testAddInvoices() throws Exception {
+ mockCallable.setObject(1, new Integer(1106), Types.INTEGER);
+ ctrlCallable.setVoidCallable();
+ mockCallable.setObject(2, new Integer(3), Types.INTEGER);
+ ctrlCallable.setVoidCallable();
+ mockCallable.registerOutParameter(3, Types.INTEGER);
+ ctrlCallable.setVoidCallable();
+ mockCallable.execute();
+ ctrlCallable.setReturnValue(false);
+ mockCallable.getUpdateCount();
+ ctrlCallable.setReturnValue(-1);
+ mockCallable.getObject(3);
+ ctrlCallable.setReturnValue(new Integer(4));
+ if (debugEnabled) {
+ mockCallable.getWarnings();
+ ctrlCallable.setReturnValue(null);
+ }
+ mockCallable.close();
+ ctrlCallable.setVoidCallable();
+
+ mockConnection.prepareCall("{call " + AddInvoice.SQL + "(?, ?, ?)}");
+ ctrlConnection.setReturnValue(mockCallable);
+
+ replay();
+
+ testAddInvoice(1106, 3);
+ }
+
+ public void testAddInvoicesWithinTransaction() throws Exception {
+ mockCallable.setObject(1, new Integer(1106), Types.INTEGER);
+ ctrlCallable.setVoidCallable();
+ mockCallable.setObject(2, new Integer(3), Types.INTEGER);
+ ctrlCallable.setVoidCallable();
+ mockCallable.registerOutParameter(3, Types.INTEGER);
+ ctrlCallable.setVoidCallable();
+ mockCallable.execute();
+ ctrlCallable.setReturnValue(false);
+ mockCallable.getUpdateCount();
+ ctrlCallable.setReturnValue(-1);
+ mockCallable.getObject(3);
+ ctrlCallable.setReturnValue(new Integer(4));
+ if (debugEnabled) {
+ mockCallable.getWarnings();
+ ctrlCallable.setReturnValue(null);
+ }
+ mockCallable.close();
+ ctrlCallable.setVoidCallable();
+
+ mockConnection.prepareCall("{call " + AddInvoice.SQL + "(?, ?, ?)}");
+ ctrlConnection.setReturnValue(mockCallable);
+
+ replay();
+
+ TransactionSynchronizationManager.bindResource(
+ mockDataSource,
+ new ConnectionHolder(mockConnection));
+
+ try {
+ testAddInvoice(1106, 3);
+ }
+ finally {
+ TransactionSynchronizationManager.unbindResource(mockDataSource);
+ }
+ }
+
+
+ /**
+ * Confirm no connection was used to get metadata.
+ * Does not use superclass replay mechanism.
+ * @throws Exception
+ */
+ public void testStoredProcedureConfiguredViaJdbcTemplateWithCustomExceptionTranslator() throws Exception {
+ mockCallable.setObject(1, new Integer(11), Types.INTEGER);
+ ctrlCallable.setVoidCallable(1);
+ mockCallable.registerOutParameter(2, Types.INTEGER);
+ ctrlCallable.setVoidCallable(1);
+ mockCallable.execute();
+ ctrlCallable.setReturnValue(false, 1);
+ mockCallable.getUpdateCount();
+ ctrlCallable.setReturnValue(-1);
+ mockCallable.getObject(2);
+ ctrlCallable.setReturnValue(new Integer(5), 1);
+ if (debugEnabled) {
+ mockCallable.getWarnings();
+ ctrlCallable.setReturnValue(null);
+ }
+ mockCallable.close();
+ ctrlCallable.setVoidCallable(1);
+ // Must call this here as we're not using setUp()/tearDown() mechanism
+ ctrlCallable.replay();
+
+ ctrlConnection = MockControl.createControl(Connection.class);
+ mockConnection = (Connection) ctrlConnection.getMock();
+ mockConnection.prepareCall("{call " + StoredProcedureConfiguredViaJdbcTemplate.SQL + "(?, ?)}");
+ ctrlConnection.setReturnValue(mockCallable, 1);
+ mockConnection.close();
+ ctrlConnection.setVoidCallable(1);
+ ctrlConnection.replay();
+
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ DataSource localDs = (DataSource) dsControl.getMock();
+ localDs.getConnection();
+ dsControl.setReturnValue(mockConnection, 1);
+ dsControl.replay();
+
+ class TestJdbcTemplate extends JdbcTemplate {
+ int calls;
+ public Map call(CallableStatementCreator csc, List declaredParameters) throws DataAccessException {
+ calls++;
+ return super.call(csc, declaredParameters);
+ }
+
+ }
+ TestJdbcTemplate t = new TestJdbcTemplate();
+ t.setDataSource(localDs);
+ // Will fail without the following, because we're not able to get a connection from the
+ // DataSource here if we need to to create an ExceptionTranslator
+ t.setExceptionTranslator(new SQLStateSQLExceptionTranslator());
+ StoredProcedureConfiguredViaJdbcTemplate sp = new StoredProcedureConfiguredViaJdbcTemplate(t);
+
+ assertEquals(sp.execute(11), 5);
+ assertEquals(1, t.calls);
+
+ dsControl.verify();
+ ctrlCallable.verify();
+ ctrlConnection.verify();
+ }
+
+ /**
+ * Confirm our JdbcTemplate is used
+ * @throws Exception
+ */
+ public void testStoredProcedureConfiguredViaJdbcTemplate() throws Exception {
+ mockCallable.setObject(1, new Integer(1106), Types.INTEGER);
+ ctrlCallable.setVoidCallable();
+ mockCallable.registerOutParameter(2, Types.INTEGER);
+ ctrlCallable.setVoidCallable();
+ mockCallable.execute();
+ ctrlCallable.setReturnValue(false);
+ mockCallable.getUpdateCount();
+ ctrlCallable.setReturnValue(-1);
+ mockCallable.getObject(2);
+ ctrlCallable.setReturnValue(new Integer(4));
+ if (debugEnabled) {
+ mockCallable.getWarnings();
+ ctrlCallable.setReturnValue(null);
+ }
+ mockCallable.close();
+ ctrlCallable.setVoidCallable();
+
+ mockConnection.prepareCall("{call " + StoredProcedureConfiguredViaJdbcTemplate.SQL + "(?, ?)}");
+ ctrlConnection.setReturnValue(mockCallable);
+
+ replay();
+ JdbcTemplate t = new JdbcTemplate();
+ t.setDataSource(mockDataSource);
+ StoredProcedureConfiguredViaJdbcTemplate sp = new StoredProcedureConfiguredViaJdbcTemplate(t);
+
+ assertEquals(sp.execute(1106), 4);
+ }
+
+ public void testNullArg() throws Exception {
+ MockControl ctrlResultSet = MockControl.createControl(ResultSet.class);
+ ResultSet mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+
+ mockCallable.setNull(1, Types.VARCHAR);
+ ctrlCallable.setVoidCallable();
+ mockCallable.execute();
+ ctrlCallable.setReturnValue(false);
+ mockCallable.getUpdateCount();
+ ctrlCallable.setReturnValue(-1);
+ if (debugEnabled) {
+ mockCallable.getWarnings();
+ ctrlCallable.setReturnValue(null);
+ }
+ mockCallable.close();
+ ctrlCallable.setVoidCallable();
+
+ mockConnection.prepareCall("{call " + NullArg.SQL + "(?)}");
+ ctrlConnection.setReturnValue(mockCallable);
+
+ replay();
+ ctrlResultSet.replay();
+
+ NullArg na = new NullArg(mockDataSource);
+ na.execute((String) null);
+ }
+
+ public void testUnnamedParameter() throws Exception {
+ replay();
+ try {
+ UnnamedParameterStoredProcedure unp =
+ new UnnamedParameterStoredProcedure(mockDataSource);
+ fail("Shouldn't succeed in creating stored procedure with unnamed parameter");
+ } catch (InvalidDataAccessApiUsageException idaauex) {
+ // OK
+ }
+ }
+
+ public void testMissingParameter() throws Exception {
+ replay();
+
+ try {
+ MissingParameterStoredProcedure mp =
+ new MissingParameterStoredProcedure(mockDataSource);
+ mp.execute();
+ fail("Shouldn't succeed in running stored procedure with missing required parameter");
+ } catch (InvalidDataAccessApiUsageException idaauex) {
+ // OK
+ }
+ }
+
+ public void testStoredProcedureExceptionTranslator() throws Exception {
+ SQLException sex =
+ new SQLException(
+ "Syntax error or access violation exception",
+ "42000");
+ mockCallable.execute();
+ ctrlCallable.setThrowable(sex);
+ mockCallable.close();
+ ctrlCallable.setVoidCallable();
+
+ mockConnection.prepareCall(
+ "{call " + StoredProcedureExceptionTranslator.SQL + "()}");
+ ctrlConnection.setReturnValue(mockCallable);
+
+ replay();
+
+ StoredProcedureExceptionTranslator sproc =
+ new StoredProcedureExceptionTranslator(mockDataSource);
+ try {
+ sproc.execute();
+ fail("Custom exception should be thrown");
+ } catch (CustomDataException ex) {
+ // OK
+ }
+ }
+
+ public void testStoredProcedureWithResultSet() throws Exception {
+ MockControl ctrlResultSet = MockControl.createControl(ResultSet.class);
+ ResultSet mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ if (debugEnabled) {
+ mockCallable.getWarnings();
+ ctrlCallable.setReturnValue(null);
+ }
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockCallable.execute();
+ ctrlCallable.setReturnValue(true);
+ mockCallable.getUpdateCount();
+ ctrlCallable.setReturnValue(-1);
+ mockCallable.getResultSet();
+ ctrlCallable.setReturnValue(mockResultSet);
+ mockCallable.getMoreResults();
+ ctrlCallable.setReturnValue(false);
+ mockCallable.getUpdateCount();
+ ctrlCallable.setReturnValue(-1);
+ mockCallable.close();
+ ctrlCallable.setVoidCallable();
+
+ mockConnection.prepareCall("{call " + StoredProcedureWithResultSet.SQL + "()}");
+ ctrlConnection.setReturnValue(mockCallable);
+
+ replay();
+ ctrlResultSet.replay();
+
+ StoredProcedureWithResultSet sproc = new StoredProcedureWithResultSet(mockDataSource);
+ sproc.execute();
+
+ ctrlResultSet.verify();
+ assertEquals(2, sproc.getCount());
+ }
+
+ public void testStoredProcedureWithResultSetMapped() throws Exception {
+ MockControl ctrlResultSet = MockControl.createControl(ResultSet.class);
+ ResultSet mockResultSet = (ResultSet) ctrlResultSet.getMock();
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getString(2);
+ ctrlResultSet.setReturnValue("Foo");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(true);
+ mockResultSet.getString(2);
+ ctrlResultSet.setReturnValue("Bar");
+ mockResultSet.next();
+ ctrlResultSet.setReturnValue(false);
+ mockResultSet.close();
+ ctrlResultSet.setVoidCallable();
+
+ mockCallable.execute();
+ ctrlCallable.setReturnValue(true);
+ mockCallable.getUpdateCount();
+ ctrlCallable.setReturnValue(-1);
+ mockCallable.getResultSet();
+ ctrlCallable.setReturnValue(mockResultSet);
+ mockCallable.getMoreResults();
+ ctrlCallable.setReturnValue(false);
+ mockCallable.getUpdateCount();
+ ctrlCallable.setReturnValue(-1);
+ if (debugEnabled) {
+ mockCallable.getWarnings();
+ ctrlCallable.setReturnValue(null);
+ }
+ mockCallable.close();
+ ctrlCallable.setVoidCallable();
+
+ mockConnection.prepareCall("{call " + StoredProcedureWithResultSetMapped.SQL + "()}");
+ ctrlConnection.setReturnValue(mockCallable);
+
+ replay();
+ ctrlResultSet.replay();
+
+ StoredProcedureWithResultSetMapped sproc = new StoredProcedureWithResultSetMapped(mockDataSource);
+ Map res = sproc.execute();
+
+ ctrlResultSet.verify();
+
+ List rs = (List) res.get("rs");
+ assertEquals(2, rs.size());
+ assertEquals("Foo", rs.get(0));
+ assertEquals("Bar", rs.get(1));
+
+ }
+
+ public void testStoredProcedureWithUndeclaredResults() throws Exception {
+ MockControl ctrlResultSet1 = MockControl.createControl(ResultSet.class);
+ ResultSet mockResultSet1 = (ResultSet) ctrlResultSet1.getMock();
+ mockResultSet1.next();
+ ctrlResultSet1.setReturnValue(true);
+ mockResultSet1.getString(2);
+ ctrlResultSet1.setReturnValue("Foo");
+ mockResultSet1.next();
+ ctrlResultSet1.setReturnValue(true);
+ mockResultSet1.getString(2);
+ ctrlResultSet1.setReturnValue("Bar");
+ mockResultSet1.next();
+ ctrlResultSet1.setReturnValue(false);
+ mockResultSet1.close();
+ ctrlResultSet1.setVoidCallable();
+
+ MockControl ctrlMetaData = MockControl.createControl(ResultSetMetaData.class);
+ ResultSetMetaData mockMetaData = (ResultSetMetaData) ctrlMetaData.getMock();
+ mockMetaData.getColumnCount();
+ ctrlMetaData.setReturnValue(2);
+ mockMetaData.getColumnLabel(1);
+ ctrlMetaData.setReturnValue("spam");
+ mockMetaData.getColumnLabel(2);
+ ctrlMetaData.setReturnValue("eggs");
+
+ MockControl ctrlResultSet2 = MockControl.createControl(ResultSet.class);
+ ResultSet mockResultSet2 = (ResultSet) ctrlResultSet2.getMock();
+ mockResultSet2.getMetaData();
+ ctrlResultSet2.setReturnValue(mockMetaData);
+ mockResultSet2.next();
+ ctrlResultSet2.setReturnValue(true);
+ mockResultSet2.getObject(1);
+ ctrlResultSet2.setReturnValue("Spam");
+ mockResultSet2.getObject(2);
+ ctrlResultSet2.setReturnValue("Eggs");
+ mockResultSet2.next();
+ ctrlResultSet2.setReturnValue(false);
+ mockResultSet2.close();
+ ctrlResultSet2.setVoidCallable();
+
+ mockCallable.execute();
+ ctrlCallable.setReturnValue(true);
+ mockCallable.getUpdateCount();
+ ctrlCallable.setReturnValue(-1);
+ mockCallable.getResultSet();
+ ctrlCallable.setReturnValue(mockResultSet1);
+ mockCallable.getMoreResults();
+ ctrlCallable.setReturnValue(true);
+ mockCallable.getUpdateCount();
+ ctrlCallable.setReturnValue(-1);
+ mockCallable.getResultSet();
+ ctrlCallable.setReturnValue(mockResultSet2);
+ mockCallable.getMoreResults();
+ ctrlCallable.setReturnValue(false);
+ mockCallable.getUpdateCount();
+ ctrlCallable.setReturnValue(0);
+ mockCallable.getMoreResults();
+ ctrlCallable.setReturnValue(false);
+ mockCallable.getUpdateCount();
+ ctrlCallable.setReturnValue(-1);
+ if (debugEnabled) {
+ mockCallable.getWarnings();
+ ctrlCallable.setReturnValue(null);
+ }
+ mockCallable.close();
+ ctrlCallable.setVoidCallable();
+
+ mockConnection.prepareCall("{call " + StoredProcedureWithResultSetMapped.SQL + "()}");
+ ctrlConnection.setReturnValue(mockCallable);
+
+ replay();
+ ctrlResultSet1.replay();
+ ctrlMetaData.replay();
+ ctrlResultSet2.replay();
+
+ StoredProcedureWithResultSetMapped sproc = new StoredProcedureWithResultSetMapped(mockDataSource);
+ Map res = sproc.execute();
+
+ ctrlResultSet1.verify();
+ ctrlResultSet2.verify();
+
+ assertEquals("incorrect number of returns", 3, res.size());
+
+ List rs1 = (List) res.get("rs");
+ assertEquals(2, rs1.size());
+ assertEquals("Foo", rs1.get(0));
+ assertEquals("Bar", rs1.get(1));
+
+ List rs2 = (List) res.get("#result-set-2");
+ assertEquals(1, rs2.size());
+ Object o2 = rs2.get(0);
+ assertTrue("wron type returned for result set 2", o2 instanceof Map);
+ Map m2 = (Map) o2;
+ assertEquals("Spam", m2.get("spam"));
+ assertEquals("Eggs", m2.get("eggs"));
+
+ Number n = (Number) res.get("#update-count-1");
+ assertEquals("wrong update count", 0, n.intValue());
+ }
+
+ public void testStoredProcedureSkippingResultsProcessing() throws Exception {
+ mockCallable.execute();
+ ctrlCallable.setReturnValue(true);
+ mockCallable.getUpdateCount();
+ ctrlCallable.setReturnValue(-1);
+ if (debugEnabled) {
+ mockCallable.getWarnings();
+ ctrlCallable.setReturnValue(null);
+ }
+ mockCallable.close();
+ ctrlCallable.setVoidCallable();
+
+ mockConnection.prepareCall("{call " + StoredProcedureWithResultSetMapped.SQL + "()}");
+ ctrlConnection.setReturnValue(mockCallable);
+
+ replay();
+
+ JdbcTemplate jdbcTemplate = new JdbcTemplate(mockDataSource);
+ jdbcTemplate.setSkipResultsProcessing(true);
+ StoredProcedureWithResultSetMapped sproc = new StoredProcedureWithResultSetMapped(jdbcTemplate);
+ Map res = sproc.execute();
+
+ assertEquals("incorrect number of returns", 0, res.size());
+ }
+
+ public void testStoredProcedureSkippingUndeclaredResults() throws Exception {
+ MockControl ctrlResultSet1 = MockControl.createControl(ResultSet.class);
+ ResultSet mockResultSet1 = (ResultSet) ctrlResultSet1.getMock();
+ mockResultSet1.next();
+ ctrlResultSet1.setReturnValue(true);
+ mockResultSet1.getString(2);
+ ctrlResultSet1.setReturnValue("Foo");
+ mockResultSet1.next();
+ ctrlResultSet1.setReturnValue(true);
+ mockResultSet1.getString(2);
+ ctrlResultSet1.setReturnValue("Bar");
+ mockResultSet1.next();
+ ctrlResultSet1.setReturnValue(false);
+ mockResultSet1.close();
+ ctrlResultSet1.setVoidCallable();
+
+ mockCallable.execute();
+ ctrlCallable.setReturnValue(true);
+ mockCallable.getUpdateCount();
+ ctrlCallable.setReturnValue(-1);
+ mockCallable.getResultSet();
+ ctrlCallable.setReturnValue(mockResultSet1);
+ mockCallable.getMoreResults();
+ ctrlCallable.setReturnValue(true);
+ mockCallable.getUpdateCount();
+ ctrlCallable.setReturnValue(-1);
+ mockCallable.getMoreResults();
+ ctrlCallable.setReturnValue(false);
+ mockCallable.getUpdateCount();
+ ctrlCallable.setReturnValue(-1);
+ if (debugEnabled) {
+ mockCallable.getWarnings();
+ ctrlCallable.setReturnValue(null);
+ }
+ mockCallable.close();
+ ctrlCallable.setVoidCallable();
+
+ mockConnection.prepareCall("{call " + StoredProcedureWithResultSetMapped.SQL + "()}");
+ ctrlConnection.setReturnValue(mockCallable);
+
+ replay();
+ ctrlResultSet1.replay();
+
+ JdbcTemplate jdbcTemplate = new JdbcTemplate(mockDataSource);
+ jdbcTemplate.setSkipUndeclaredResults(true);
+ StoredProcedureWithResultSetMapped sproc = new StoredProcedureWithResultSetMapped(jdbcTemplate);
+ Map res = sproc.execute();
+
+ ctrlResultSet1.verify();
+
+ assertEquals("incorrect number of returns", 1, res.size());
+
+ List rs1 = (List) res.get("rs");
+ assertEquals(2, rs1.size());
+ assertEquals("Foo", rs1.get(0));
+ assertEquals("Bar", rs1.get(1));
+ }
+
+ public void testParameterMapper() throws Exception {
+ mockCallable.setString(1, "EasyMock for interface java.sql.Connection");
+ ctrlCallable.setVoidCallable();
+ mockCallable.registerOutParameter(2, Types.VARCHAR);
+ ctrlCallable.setVoidCallable();
+ mockCallable.execute();
+ ctrlCallable.setReturnValue(false);
+ mockCallable.getUpdateCount();
+ ctrlCallable.setReturnValue(-1);
+ mockCallable.getObject(2);
+ ctrlCallable.setReturnValue("OK");
+ if (debugEnabled) {
+ mockCallable.getWarnings();
+ ctrlCallable.setReturnValue(null);
+ }
+ mockCallable.close();
+ ctrlCallable.setVoidCallable();
+
+ mockConnection.prepareCall(
+ "{call " + ParameterMapperStoredProcedure.SQL + "(?, ?)}");
+ ctrlConnection.setReturnValue(mockCallable);
+
+ replay();
+ ParameterMapperStoredProcedure pmsp = new ParameterMapperStoredProcedure(mockDataSource);
+ Map out = pmsp.executeTest();
+ assertEquals("OK", out.get("out"));
+ }
+
+ public void testSqlTypeValue() throws Exception {
+ int[] testVal = new int[] {1, 2};
+ mockCallable.getConnection();
+ ctrlCallable.setDefaultReturnValue(mockConnection);
+ mockCallable.setObject(1, testVal, Types.ARRAY);
+ ctrlCallable.setVoidCallable();
+ mockCallable.registerOutParameter(2, Types.VARCHAR);
+ ctrlCallable.setVoidCallable();
+ mockCallable.execute();
+ ctrlCallable.setReturnValue(false);
+ mockCallable.getUpdateCount();
+ ctrlCallable.setReturnValue(-1);
+ mockCallable.getObject(2);
+ ctrlCallable.setReturnValue("OK");
+ if (debugEnabled) {
+ mockCallable.getWarnings();
+ ctrlCallable.setReturnValue(null);
+ }
+ mockCallable.close();
+ ctrlCallable.setVoidCallable();
+
+ mockConnection.prepareCall(
+ "{call " + SqlTypeValueStoredProcedure.SQL + "(?, ?)}");
+ ctrlConnection.setReturnValue(mockCallable);
+
+ replay();
+ SqlTypeValueStoredProcedure stvsp = new SqlTypeValueStoredProcedure(mockDataSource);
+ Map out = stvsp.executeTest(testVal);
+ assertEquals("OK", out.get("out"));
+ }
+
+ public void testNumericWithScale() throws Exception {
+ mockCallable.getConnection();
+ ctrlCallable.setDefaultReturnValue(mockConnection);
+ mockCallable.registerOutParameter(1, Types.DECIMAL, 4);
+ ctrlCallable.setVoidCallable();
+ mockCallable.execute();
+ ctrlCallable.setReturnValue(false);
+ mockCallable.getUpdateCount();
+ ctrlCallable.setReturnValue(-1);
+ mockCallable.getObject(1);
+ ctrlCallable.setReturnValue(new BigDecimal("12345.6789"));
+ if (debugEnabled) {
+ mockCallable.getWarnings();
+ ctrlCallable.setReturnValue(null);
+ }
+ mockCallable.close();
+ ctrlCallable.setVoidCallable();
+
+ mockConnection.prepareCall(
+ "{call " + NumericWithScaleStoredProcedure.SQL + "(?)}");
+ ctrlConnection.setReturnValue(mockCallable);
+
+ replay();
+ NumericWithScaleStoredProcedure nwssp = new NumericWithScaleStoredProcedure(mockDataSource);
+ Map out = nwssp.executeTest();
+ assertEquals(new BigDecimal("12345.6789"), out.get("out"));
+ }
+
+
+ private static class StoredProcedureConfiguredViaJdbcTemplate extends StoredProcedure {
+
+ public static final String SQL = "configured_via_jt";
+
+ public StoredProcedureConfiguredViaJdbcTemplate(JdbcTemplate t) {
+ setJdbcTemplate(t);
+ setSql(SQL);
+ declareParameter(new SqlParameter("intIn", Types.INTEGER));
+ declareParameter(new SqlOutParameter("intOut", Types.INTEGER));
+ compile();
+ }
+
+ public int execute(int intIn) {
+ Map in = new HashMap();
+ in.put("intIn", new Integer(intIn));
+ Map out = execute(in);
+ Number intOut = (Number) out.get("intOut");
+ return intOut.intValue();
+ }
+ }
+
+
+ private static class AddInvoice extends StoredProcedure {
+
+ public static final String SQL = "add_invoice";
+
+ public AddInvoice(DataSource ds) {
+ setDataSource(ds);
+ setSql(SQL);
+ declareParameter(new SqlParameter("amount", Types.INTEGER));
+ declareParameter(new SqlParameter("custid", Types.INTEGER));
+ declareParameter(new SqlOutParameter("newid", Types.INTEGER));
+ compile();
+ }
+
+ public int execute(int amount, int custid) {
+ Map in = new HashMap();
+ in.put("amount", new Integer(amount));
+ in.put("custid", new Integer(custid));
+ Map out = execute(in);
+ Number id = (Number) out.get("newid");
+ return id.intValue();
+ }
+ }
+
+
+ private static class NullArg extends StoredProcedure {
+
+ public static final String SQL = "takes_null";
+
+ public NullArg(DataSource ds) {
+ setDataSource(ds);
+ setSql(SQL);
+ declareParameter(new SqlParameter("ptest", Types.VARCHAR));
+ compile();
+ }
+
+ public void execute(String s) {
+ Map in = new HashMap();
+ in.put("ptest", s);
+ Map out = execute(in);
+ }
+ }
+
+
+ private static class NoSuchStoredProcedure extends StoredProcedure {
+
+ public static final String SQL = "no_sproc_with_this_name";
+
+ public NoSuchStoredProcedure(DataSource ds) {
+ setDataSource(ds);
+ setSql(SQL);
+ compile();
+ }
+
+ public void execute() {
+ execute(new HashMap());
+ }
+ }
+
+
+ private static class UnnamedParameterStoredProcedure extends StoredProcedure {
+
+ public UnnamedParameterStoredProcedure(DataSource ds) {
+ super(ds, "unnamed_parameter_sp");
+ declareParameter(new SqlParameter(Types.INTEGER));
+ compile();
+ }
+
+ public void execute(int id) {
+ Map in = new HashMap();
+ in.put("id", new Integer(id));
+ Map out = execute(in);
+ }
+ }
+
+
+ private static class MissingParameterStoredProcedure extends StoredProcedure {
+
+ public MissingParameterStoredProcedure(DataSource ds) {
+ setDataSource(ds);
+ setSql("takes_string");
+ declareParameter(new SqlParameter("mystring", Types.VARCHAR));
+ compile();
+ }
+
+ public void execute() {
+ execute(new HashMap());
+ }
+ }
+
+
+ private static class StoredProcedureWithResultSet extends StoredProcedure {
+
+ public static final String SQL = "sproc_with_result_set";
+
+ private final SimpleRowCountCallbackHandler handler = new SimpleRowCountCallbackHandler();
+
+ public StoredProcedureWithResultSet(DataSource ds) {
+ setDataSource(ds);
+ setSql(SQL);
+ declareParameter(new SqlReturnResultSet("rs", this.handler));
+ compile();
+ }
+
+ public void execute() {
+ execute(new HashMap());
+ }
+
+ public int getCount() {
+ return this.handler.getCount();
+ }
+ }
+
+
+ private static class StoredProcedureWithResultSetMapped extends StoredProcedure {
+
+ public static final String SQL = "sproc_with_result_set";
+
+ public StoredProcedureWithResultSetMapped(DataSource ds) {
+ setDataSource(ds);
+ setSql(SQL);
+ declareParameter(
+ new SqlReturnResultSet("rs", new RowMapperImpl()));
+ compile();
+ }
+
+ public StoredProcedureWithResultSetMapped(JdbcTemplate jt) {
+ setJdbcTemplate(jt);
+ setSql(SQL);
+ declareParameter(
+ new SqlReturnResultSet("rs", new RowMapperImpl()));
+ compile();
+ }
+
+ public Map execute() {
+ Map out = execute(new HashMap());
+ return out;
+ }
+
+ private static class RowMapperImpl implements RowMapper {
+ public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
+ return rs.getString(2);
+ }
+ }
+ }
+
+
+ private static class ParameterMapperStoredProcedure extends StoredProcedure {
+
+ public static final String SQL = "parameter_mapper_sp";
+
+ public ParameterMapperStoredProcedure(DataSource ds) {
+ setDataSource(ds);
+ setSql(SQL);
+ declareParameter(new SqlParameter("in", Types.VARCHAR));
+ declareParameter(new SqlOutParameter("out", Types.VARCHAR));
+ compile();
+ }
+
+ public Map executeTest() {
+ Map out = null;
+ out = execute(new TestParameterMapper());
+ return out;
+ }
+
+ private static class TestParameterMapper implements ParameterMapper {
+
+ private TestParameterMapper() {
+ }
+
+ public Map createMap(Connection conn) throws SQLException {
+ Map inParms = new HashMap();
+ String testValue = conn.toString();
+ inParms.put("in", testValue);
+ return inParms;
+ }
+ }
+ }
+
+
+ private static class SqlTypeValueStoredProcedure extends StoredProcedure {
+
+ public static final String SQL = "sql_type_value_sp";
+
+ public SqlTypeValueStoredProcedure(DataSource ds) {
+ setDataSource(ds);
+ setSql(SQL);
+ declareParameter(new SqlParameter("in", Types.ARRAY, "NUMBERS"));
+ declareParameter(new SqlOutParameter("out", Types.VARCHAR));
+ compile();
+ }
+
+ public Map executeTest(final int[] inValue) {
+ Map in = new HashMap(1);
+ in.put("in", new AbstractSqlTypeValue() {
+ public Object createTypeValue(Connection con, int type, String typeName) {
+ //assertEquals(Connection.class, con.getClass());
+ //assertEquals(Types.ARRAY, type);
+ //assertEquals("NUMBER", typeName);
+ return inValue;
+ }
+ });
+ Map out = null;
+ out = execute(in);
+ return out;
+ }
+ }
+
+ private static class NumericWithScaleStoredProcedure extends StoredProcedure {
+
+ public static final String SQL = "numeric_with_scale_sp";
+
+ public NumericWithScaleStoredProcedure(DataSource ds) {
+ setDataSource(ds);
+ setSql(SQL);
+ declareParameter(new SqlOutParameter("out", Types.DECIMAL, 4));
+ compile();
+ }
+
+ public Map executeTest() {
+ Map in = new HashMap(1);
+ Map out = null;
+ out = execute(in);
+ return out;
+ }
+ }
+
+
+ private static class StoredProcedureExceptionTranslator extends StoredProcedure {
+
+ public static final String SQL = "no_sproc_with_this_name";
+
+ public StoredProcedureExceptionTranslator(DataSource ds) {
+ setDataSource(ds);
+ setSql(SQL);
+ getJdbcTemplate().setExceptionTranslator(new SQLExceptionTranslator() {
+ public DataAccessException translate(
+ String task,
+ String sql,
+ SQLException sqlex) {
+ return new CustomDataException(sql, sqlex);
+ }
+
+ });
+ compile();
+ }
+
+ public void execute() {
+ execute(new HashMap());
+ }
+ }
+
+
+ private static class CustomDataException extends DataAccessException {
+
+ public CustomDataException(String s) {
+ super(s);
+ }
+
+ public CustomDataException(String s, Throwable ex) {
+ super(s, ex);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/CustomErrorCodeException.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/CustomErrorCodeException.java
new file mode 100644
index 00000000000..579a91cbb64
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/CustomErrorCodeException.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jdbc.support;
+
+import org.springframework.dao.DataAccessException;
+
+/**
+ * @author Thomas Risberg
+ */
+public class CustomErrorCodeException extends DataAccessException {
+
+ public CustomErrorCodeException(String msg) {
+ super(msg);
+ }
+
+ public CustomErrorCodeException(String msg, Throwable ex) {
+ super(msg, ex);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/DataFieldMaxValueIncrementerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/DataFieldMaxValueIncrementerTests.java
new file mode 100644
index 00000000000..7c63fd5c5c0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/DataFieldMaxValueIncrementerTests.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jdbc.support;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import javax.sql.DataSource;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.jdbc.support.incrementer.HsqlMaxValueIncrementer;
+import org.springframework.jdbc.support.incrementer.MySQLMaxValueIncrementer;
+import org.springframework.jdbc.support.incrementer.OracleSequenceMaxValueIncrementer;
+import org.springframework.jdbc.support.incrementer.PostgreSQLSequenceMaxValueIncrementer;
+
+/**
+ * @author Juergen Hoeller
+ * @since 27.02.2004
+ */
+public class DataFieldMaxValueIncrementerTests extends TestCase {
+
+ public void testHsqlMaxValueIncrementer() throws SQLException {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl stmtControl = MockControl.createControl(Statement.class);
+ Statement stmt = (Statement) stmtControl.getMock();
+ MockControl rsControl = MockControl.createControl(ResultSet.class);
+ ResultSet rs = (ResultSet) rsControl.getMock();
+
+ ds.getConnection();
+ dsControl.setReturnValue(con, 2);
+ con.createStatement();
+ conControl.setReturnValue(stmt, 2);
+ stmt.executeUpdate("insert into myseq values(null)");
+ stmtControl.setReturnValue(1, 6);
+ stmt.executeQuery("select max(identity()) from myseq");
+ stmtControl.setReturnValue(rs, 6);
+ rs.next();
+ rsControl.setReturnValue(true, 6);
+ for (long i = 0; i < 6; i++) {
+ rs.getLong(1);
+ rsControl.setReturnValue(i);
+ }
+ rs.close();
+ rsControl.setVoidCallable(6);
+ stmt.executeUpdate("delete from myseq where seq < 2");
+ stmtControl.setReturnValue(1);
+ stmt.executeUpdate("delete from myseq where seq < 5");
+ stmtControl.setReturnValue(1);
+ stmt.close();
+ stmtControl.setVoidCallable(2);
+ con.close();
+ conControl.setVoidCallable(2);
+
+ dsControl.replay();
+ conControl.replay();
+ stmtControl.replay();
+ rsControl.replay();
+
+ HsqlMaxValueIncrementer incrementer = new HsqlMaxValueIncrementer();
+ incrementer.setDataSource(ds);
+ incrementer.setIncrementerName("myseq");
+ incrementer.setColumnName("seq");
+ incrementer.setCacheSize(3);
+ incrementer.setPaddingLength(3);
+ incrementer.afterPropertiesSet();
+
+ assertEquals(0, incrementer.nextIntValue());
+ assertEquals(1, incrementer.nextLongValue());
+ assertEquals("002", incrementer.nextStringValue());
+ assertEquals(3, incrementer.nextIntValue());
+ assertEquals(4, incrementer.nextLongValue());
+
+ dsControl.verify();
+ conControl.verify();
+ stmtControl.verify();
+ rsControl.verify();
+ }
+
+ public void testMySQLMaxValueIncrementer() throws SQLException {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl stmtControl = MockControl.createControl(Statement.class);
+ Statement stmt = (Statement) stmtControl.getMock();
+ MockControl rsControl = MockControl.createControl(ResultSet.class);
+ ResultSet rs = (ResultSet) rsControl.getMock();
+
+ ds.getConnection();
+ dsControl.setReturnValue(con, 2);
+ con.createStatement();
+ conControl.setReturnValue(stmt, 2);
+ stmt.executeUpdate("update myseq set seq = last_insert_id(seq + 2)");
+ stmtControl.setReturnValue(1, 2);
+ stmt.executeQuery("select last_insert_id()");
+ stmtControl.setReturnValue(rs, 2);
+ rs.next();
+ rsControl.setReturnValue(true, 2);
+ rs.getLong(1);
+ rsControl.setReturnValue(2);
+ rs.getLong(1);
+ rsControl.setReturnValue(4);
+ rs.close();
+ rsControl.setVoidCallable(2);
+ stmt.close();
+ stmtControl.setVoidCallable(2);
+ con.close();
+ conControl.setVoidCallable(2);
+
+ dsControl.replay();
+ conControl.replay();
+ stmtControl.replay();
+ rsControl.replay();
+
+ MySQLMaxValueIncrementer incrementer = new MySQLMaxValueIncrementer();
+ incrementer.setDataSource(ds);
+ incrementer.setIncrementerName("myseq");
+ incrementer.setColumnName("seq");
+ incrementer.setCacheSize(2);
+ incrementer.setPaddingLength(1);
+ incrementer.afterPropertiesSet();
+
+ assertEquals(1, incrementer.nextIntValue());
+ assertEquals(2, incrementer.nextLongValue());
+ assertEquals("3", incrementer.nextStringValue());
+ assertEquals(4, incrementer.nextLongValue());
+
+ dsControl.verify();
+ conControl.verify();
+ stmtControl.verify();
+ rsControl.verify();
+ }
+
+ public void testPostgreSQLSequenceMaxValueIncrementer() throws SQLException {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl stmtControl = MockControl.createControl(Statement.class);
+ Statement stmt = (Statement) stmtControl.getMock();
+ MockControl rsControl = MockControl.createControl(ResultSet.class);
+ ResultSet rs = (ResultSet) rsControl.getMock();
+
+ ds.getConnection();
+ dsControl.setReturnValue(con, 2);
+ con.createStatement();
+ conControl.setReturnValue(stmt, 2);
+ stmt.executeQuery("select nextval('myseq')");
+ stmtControl.setReturnValue(rs, 2);
+ rs.next();
+ rsControl.setReturnValue(true, 2);
+ rs.getLong(1);
+ rsControl.setReturnValue(10);
+ rs.getLong(1);
+ rsControl.setReturnValue(12);
+ rs.close();
+ rsControl.setVoidCallable(2);
+ stmt.close();
+ stmtControl.setVoidCallable(2);
+ con.close();
+ conControl.setVoidCallable(2);
+
+ dsControl.replay();
+ conControl.replay();
+ stmtControl.replay();
+ rsControl.replay();
+
+ PostgreSQLSequenceMaxValueIncrementer incrementer = new PostgreSQLSequenceMaxValueIncrementer();
+ incrementer.setDataSource(ds);
+ incrementer.setIncrementerName("myseq");
+ incrementer.setPaddingLength(5);
+ incrementer.afterPropertiesSet();
+
+ assertEquals("00010", incrementer.nextStringValue());
+ assertEquals(12, incrementer.nextIntValue());
+
+ dsControl.verify();
+ conControl.verify();
+ stmtControl.verify();
+ rsControl.verify();
+ }
+
+ public void testOracleSequenceMaxValueIncrementer() throws SQLException {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl stmtControl = MockControl.createControl(Statement.class);
+ Statement stmt = (Statement) stmtControl.getMock();
+ MockControl rsControl = MockControl.createControl(ResultSet.class);
+ ResultSet rs = (ResultSet) rsControl.getMock();
+
+ ds.getConnection();
+ dsControl.setReturnValue(con, 2);
+ con.createStatement();
+ conControl.setReturnValue(stmt, 2);
+ stmt.executeQuery("select myseq.nextval from dual");
+ stmtControl.setReturnValue(rs, 2);
+ rs.next();
+ rsControl.setReturnValue(true, 2);
+ rs.getLong(1);
+ rsControl.setReturnValue(10);
+ rs.getLong(1);
+ rsControl.setReturnValue(12);
+ rs.close();
+ rsControl.setVoidCallable(2);
+ stmt.close();
+ stmtControl.setVoidCallable(2);
+ con.close();
+ conControl.setVoidCallable(2);
+
+ dsControl.replay();
+ conControl.replay();
+ stmtControl.replay();
+ rsControl.replay();
+
+ OracleSequenceMaxValueIncrementer incrementer = new OracleSequenceMaxValueIncrementer();
+ incrementer.setDataSource(ds);
+ incrementer.setIncrementerName("myseq");
+ incrementer.setPaddingLength(2);
+ incrementer.afterPropertiesSet();
+
+ assertEquals(10, incrementer.nextLongValue());
+ assertEquals("12", incrementer.nextStringValue());
+
+ dsControl.verify();
+ conControl.verify();
+ stmtControl.verify();
+ rsControl.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/DefaultLobHandlerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/DefaultLobHandlerTests.java
new file mode 100644
index 00000000000..933d8089a57
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/DefaultLobHandlerTests.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jdbc.support;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.ResultSet;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.jdbc.support.lob.DefaultLobHandler;
+import org.springframework.jdbc.support.lob.LobCreator;
+import org.springframework.jdbc.support.lob.LobHandler;
+
+/**
+ * @author Juergen Hoeller
+ * @since 17.12.2003
+ */
+public class DefaultLobHandlerTests extends TestCase {
+
+ public void testGetBlobAsBytes() throws SQLException {
+ LobHandler lobHandler = new DefaultLobHandler();
+ MockControl rsControl = MockControl.createControl(ResultSet.class);
+ ResultSet rs = (ResultSet) rsControl.getMock();
+ rs.getBytes(1);
+ rsControl.setReturnValue(null);
+ rsControl.replay();
+ lobHandler.getBlobAsBytes(rs, 1);
+ rsControl.verify();
+ }
+
+ public void testGetBlobAsBinaryStream() throws SQLException {
+ LobHandler lobHandler = new DefaultLobHandler();
+ MockControl rsControl = MockControl.createControl(ResultSet.class);
+ ResultSet rs = (ResultSet) rsControl.getMock();
+ rs.getBinaryStream(1);
+ rsControl.setReturnValue(null);
+ rsControl.replay();
+ lobHandler.getBlobAsBinaryStream(rs, 1);
+ rsControl.verify();
+ }
+
+ public void testGetClobAsString() throws SQLException {
+ LobHandler lobHandler = new DefaultLobHandler();
+ MockControl rsControl = MockControl.createControl(ResultSet.class);
+ ResultSet rs = (ResultSet) rsControl.getMock();
+ rs.getString(1);
+ rsControl.setReturnValue(null);
+ rsControl.replay();
+ lobHandler.getClobAsString(rs, 1);
+ rsControl.verify();
+ }
+
+ public void testGetClobAsAsciiStream() throws SQLException {
+ LobHandler lobHandler = new DefaultLobHandler();
+ MockControl rsControl = MockControl.createControl(ResultSet.class);
+ ResultSet rs = (ResultSet) rsControl.getMock();
+ rs.getAsciiStream(1);
+ rsControl.setReturnValue(null);
+ rsControl.replay();
+ lobHandler.getClobAsAsciiStream(rs, 1);
+ rsControl.verify();
+ }
+
+ public void testGetClobAsCharacterStream() throws SQLException {
+ LobHandler lobHandler = new DefaultLobHandler();
+ MockControl rsControl = MockControl.createControl(ResultSet.class);
+ ResultSet rs = (ResultSet) rsControl.getMock();
+ rs.getCharacterStream(1);
+ rsControl.setReturnValue(null);
+ rsControl.replay();
+ lobHandler.getClobAsCharacterStream(rs, 1);
+ rsControl.verify();
+ }
+
+ public void testSetBlobAsBytes() throws SQLException {
+ LobCreator lobCreator = (new DefaultLobHandler()).getLobCreator();
+ byte[] content = "testContent".getBytes();
+
+ MockControl psControl = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement ps = (PreparedStatement) psControl.getMock();
+ ps.setBytes(1, content);
+ psControl.replay();
+
+ lobCreator.setBlobAsBytes(ps, 1, content);
+ psControl.verify();
+ }
+
+ public void testSetBlobAsBinaryStream() throws SQLException, IOException {
+ LobCreator lobCreator = (new DefaultLobHandler()).getLobCreator();
+ InputStream bis = new ByteArrayInputStream("testContent".getBytes());
+
+ MockControl psControl = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement ps = (PreparedStatement) psControl.getMock();
+ ps.setBinaryStream(1, bis, 11);
+ psControl.replay();
+
+ lobCreator.setBlobAsBinaryStream(ps, 1, bis, 11);
+ psControl.verify();
+ }
+
+ public void testSetClobAsString() throws SQLException, IOException {
+ LobCreator lobCreator = (new DefaultLobHandler()).getLobCreator();
+ String content = "testContent";
+
+ MockControl psControl = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement ps = (PreparedStatement) psControl.getMock();
+ ps.setString(1, content);
+ psControl.replay();
+
+ lobCreator.setClobAsString(ps, 1, content);
+ psControl.verify();
+ }
+
+ public void testSetClobAsAsciiStream() throws SQLException, IOException {
+ LobCreator lobCreator = (new DefaultLobHandler()).getLobCreator();
+ InputStream bis = new ByteArrayInputStream("testContent".getBytes());
+
+ MockControl psControl = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement ps = (PreparedStatement) psControl.getMock();
+ ps.setAsciiStream(1, bis, 11);
+ psControl.replay();
+
+ lobCreator.setClobAsAsciiStream(ps, 1, bis, 11);
+ psControl.verify();
+ }
+
+ public void testSetClobAsCharacterStream() throws SQLException, IOException {
+ LobCreator lobCreator = (new DefaultLobHandler()).getLobCreator();
+ Reader str = new StringReader("testContent");
+
+ MockControl psControl = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement ps = (PreparedStatement) psControl.getMock();
+ ps.setCharacterStream(1, str, 11);
+ psControl.replay();
+
+ lobCreator.setClobAsCharacterStream(ps, 1, str, 11);
+ psControl.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/JdbcUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/JdbcUtilsTests.java
new file mode 100644
index 00000000000..637032c6953
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/JdbcUtilsTests.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jdbc.support;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for JdbcUtils.
+ *
+ * @author Thomas Risberg
+ */
+public class JdbcUtilsTests extends TestCase {
+
+ public void testCommonDatabaseName() {
+ assertEquals("Wrong db name", "Oracle", JdbcUtils.commonDatabaseName("Oracle"));
+ assertEquals("Wrong db name", "DB2", JdbcUtils.commonDatabaseName("DB2-for-Spring"));
+ assertEquals("Wrong db name", "Sybase", JdbcUtils.commonDatabaseName("Sybase SQL Server"));
+ assertEquals("Wrong db name", "Sybase", JdbcUtils.commonDatabaseName("Adaptive Server Enterprise"));
+ assertEquals("Wrong db name", "MySQL", JdbcUtils.commonDatabaseName("MySQL"));
+ }
+
+ public void testConvertUnderscoreNameToPropertyName() {
+ assertEquals("Wrong property name", "myName", JdbcUtils.convertUnderscoreNameToPropertyName("MY_NAME"));
+ assertEquals("Wrong property name", "yourName", JdbcUtils.convertUnderscoreNameToPropertyName("yOUR_nAME"));
+ assertEquals("Wrong property name", "AName", JdbcUtils.convertUnderscoreNameToPropertyName("a_name"));
+ assertEquals("Wrong property name", "someoneElsesName", JdbcUtils.convertUnderscoreNameToPropertyName("someone_elses_name"));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/KeyHolderTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/KeyHolderTests.java
new file mode 100644
index 00000000000..058ce7c3048
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/KeyHolderTests.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jdbc.support;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+
+import org.springframework.dao.DataRetrievalFailureException;
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for the KeyHolder and GeneratedKeyHolder
+ * and it appears that JdbcUtils doesn't work exactly as documented.
+ *
+ * @author trisberg
+ * @since Jul 18, 2004
+ */
+public class KeyHolderTests extends TestCase {
+ private KeyHolder kh;
+
+ public void setUp() {
+ kh = new GeneratedKeyHolder();
+ }
+
+ public void testSingleKey(){
+ LinkedList l = new LinkedList();
+ HashMap m = new HashMap(1);
+ m.put("key", new Integer(1));
+ l.add(m);
+ kh.getKeyList().addAll(l);
+ assertEquals("single key should be returned", 1, kh.getKey().intValue());
+ }
+
+ public void testSingleKeyNonNumeric(){
+ LinkedList l = new LinkedList();
+ HashMap m = new HashMap(1);
+ m.put("key", "1");
+ l.add(m);
+ kh.getKeyList().addAll(l);
+ try {
+ kh.getKey().intValue();
+ }
+ catch (DataRetrievalFailureException e) {
+ assertTrue(e.getMessage().startsWith("The generated key is not of a supported numeric type."));
+ }
+ }
+
+ public void testNoKeyReturnedInMap(){
+ LinkedList l = new LinkedList();
+ HashMap m = new HashMap();
+ l.add(m);
+ kh.getKeyList().addAll(l);
+ try {
+ kh.getKey();
+ }
+ catch (DataRetrievalFailureException e) {
+ assertTrue(e.getMessage().startsWith("Unable to retrieve the generated key."));
+ }
+ }
+
+ public void testMultipleKeys(){
+ LinkedList l = new LinkedList();
+ HashMap m = new HashMap(1);
+ m.put("key", new Integer(1));
+ m.put("seq", new Integer(2));
+ l.add(m);
+ kh.getKeyList().addAll(l);
+ Map keyMap = kh.getKeys();
+ assertEquals("two keys should be in the map", 2, keyMap.size());
+ try {
+ kh.getKey();
+ }
+ catch (InvalidDataAccessApiUsageException e) {
+ assertTrue(e.getMessage().startsWith("The getKey method should only be used when a single key is returned."));
+ }
+ }
+
+ public void testMultipleKeyRows(){
+ LinkedList l = new LinkedList();
+ HashMap m = new HashMap(1);
+ m.put("key", new Integer(1));
+ m.put("seq", new Integer(2));
+ l.add(m);
+ l.add(m);
+ kh.getKeyList().addAll(l);
+
+ assertEquals("two rows should be in the list", 2, kh.getKeyList().size());
+ try {
+ kh.getKeys();
+ }
+ catch (InvalidDataAccessApiUsageException e) {
+ assertTrue(e.getMessage().startsWith("The getKeys method should only be used when keys for a single row are returned."));
+ }
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/NativeJdbcExtractorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/NativeJdbcExtractorTests.java
new file mode 100644
index 00000000000..a5c23af49cc
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/NativeJdbcExtractorTests.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jdbc.support;
+
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor;
+import org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor;
+
+/**
+ * @author Andre Biryukov
+ * @author Juergen Hoeller
+ */
+public class NativeJdbcExtractorTests extends TestCase {
+
+ public void testSimpleNativeJdbcExtractor() throws SQLException {
+ SimpleNativeJdbcExtractor extractor = new SimpleNativeJdbcExtractor();
+
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl dbmdControl = MockControl.createControl(DatabaseMetaData.class);
+ DatabaseMetaData dbmd = (DatabaseMetaData) dbmdControl.getMock();
+ MockControl con2Control = MockControl.createControl(Connection.class);
+ Connection con2 = (Connection) con2Control.getMock();
+ con.getMetaData();
+ conControl.setReturnValue(dbmd, 2);
+ dbmd.getConnection();
+ dbmdControl.setReturnValue(con2, 2);
+ conControl.replay();
+ dbmdControl.replay();
+ con2Control.replay();
+
+ Connection nativeCon = extractor.getNativeConnection(con);
+ assertEquals(con2, nativeCon);
+
+ MockControl stmtControl = MockControl.createControl(Statement.class);
+ Statement stmt = (Statement) stmtControl.getMock();
+ stmt.getConnection();
+ stmtControl.setReturnValue(con);
+ stmtControl.replay();
+
+ nativeCon = extractor.getNativeConnectionFromStatement(stmt);
+ assertEquals(con2, nativeCon);
+
+ Statement nativeStmt = extractor.getNativeStatement(stmt);
+ assertEquals(nativeStmt, stmt);
+
+ MockControl psControl = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement ps = (PreparedStatement) psControl.getMock();
+ psControl.replay();
+
+ PreparedStatement nativePs = extractor.getNativePreparedStatement(ps);
+ assertEquals(ps, nativePs);
+
+ MockControl csControl = MockControl.createControl(CallableStatement.class);
+ CallableStatement cs = (CallableStatement) csControl.getMock();
+ MockControl rsControl = MockControl.createControl(ResultSet.class);
+ ResultSet rs = (ResultSet) rsControl.getMock();
+ cs.getResultSet();
+ csControl.setReturnValue(rs);
+ csControl.replay();
+ rsControl.replay();
+
+ CallableStatement nativeCs = extractor.getNativeCallableStatement(cs);
+ assertEquals(cs, nativeCs);
+
+ ResultSet nativeRs = extractor.getNativeResultSet(cs.getResultSet());
+ assertEquals(nativeRs, rs);
+
+ conControl.verify();
+ dbmdControl.verify();
+ con2Control.verify();
+ stmtControl.verify();
+ psControl.verify();
+ csControl.verify();
+ rsControl.verify();
+ }
+
+ public void testCommonsDbcpNativeJdbcExtractor() throws SQLException {
+ CommonsDbcpNativeJdbcExtractor extractor = new CommonsDbcpNativeJdbcExtractor();
+ assertFalse(extractor.isNativeConnectionNecessaryForNativeStatements());
+
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl stmtControl = MockControl.createControl(Statement.class);
+ Statement stmt = (Statement) stmtControl.getMock();
+ con.getMetaData();
+ conControl.setReturnValue(null, 2);
+ stmt.getConnection();
+ stmtControl.setReturnValue(con, 1);
+ conControl.replay();
+ stmtControl.replay();
+
+ Connection nativeConnection = extractor.getNativeConnection(con);
+ assertEquals(con, nativeConnection);
+
+ nativeConnection = extractor.getNativeConnectionFromStatement(stmt);
+ assertEquals(con, nativeConnection);
+ assertEquals(stmt, extractor.getNativeStatement(stmt));
+
+ MockControl psControl = MockControl.createControl(PreparedStatement.class);
+ PreparedStatement ps = (PreparedStatement) psControl.getMock();
+ psControl.replay();
+ assertEquals(ps, extractor.getNativePreparedStatement(ps));
+
+ MockControl csControl = MockControl.createControl(CallableStatement.class);
+ CallableStatement cs = (CallableStatement) csControl.getMock();
+ csControl.replay();
+ assertEquals(cs, extractor.getNativePreparedStatement(cs));
+
+ MockControl rsControl = MockControl.createControl(ResultSet.class);
+ ResultSet rs = (ResultSet) rsControl.getMock();
+ rsControl.replay();
+ assertEquals(rs, extractor.getNativeResultSet(rs));
+
+ conControl.verify();
+ stmtControl.verify();
+ psControl.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslatorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslatorTests.java
new file mode 100644
index 00000000000..d5ee4e48798
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslatorTests.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jdbc.support;
+
+import java.sql.SQLException;
+import java.sql.BatchUpdateException;
+
+import junit.framework.TestCase;
+
+import org.springframework.dao.CannotAcquireLockException;
+import org.springframework.dao.CannotSerializeTransactionException;
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.DataAccessResourceFailureException;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.dao.DeadlockLoserDataAccessException;
+import org.springframework.jdbc.BadSqlGrammarException;
+import org.springframework.jdbc.InvalidResultSetAccessException;
+
+/**
+ * @author Rod Johnson
+ */
+public class SQLErrorCodeSQLExceptionTranslatorTests extends TestCase {
+
+ private static SQLErrorCodes ERROR_CODES = new SQLErrorCodes();
+ static {
+ ERROR_CODES.setBadSqlGrammarCodes(new String[] { "1", "2" });
+ ERROR_CODES.setInvalidResultSetAccessCodes(new String[] { "3", "4" });
+ ERROR_CODES.setDataAccessResourceFailureCodes(new String[] { "5" });
+ ERROR_CODES.setDataIntegrityViolationCodes(new String[] { "6" });
+ ERROR_CODES.setCannotAcquireLockCodes(new String[] { "7" });
+ ERROR_CODES.setDeadlockLoserCodes(new String[] { "8" });
+ ERROR_CODES.setCannotSerializeTransactionCodes(new String[] { "9" });
+ }
+
+ public void testErrorCodeTranslation() {
+ SQLExceptionTranslator sext = new SQLErrorCodeSQLExceptionTranslator(ERROR_CODES);
+
+ SQLException badSqlEx = new SQLException("", "", 1);
+ BadSqlGrammarException bsgex = (BadSqlGrammarException) sext.translate("task", "SQL", badSqlEx);
+ assertEquals("SQL", bsgex.getSql());
+ assertEquals(badSqlEx, bsgex.getSQLException());
+
+ SQLException invResEx = new SQLException("", "", 4);
+ InvalidResultSetAccessException irsex = (InvalidResultSetAccessException) sext.translate("task", "SQL", invResEx);
+ assertEquals("SQL", irsex.getSql());
+ assertEquals(invResEx, irsex.getSQLException());
+
+ checkTranslation(sext, 5, DataAccessResourceFailureException.class);
+ checkTranslation(sext, 6, DataIntegrityViolationException.class);
+ checkTranslation(sext, 7, CannotAcquireLockException.class);
+ checkTranslation(sext, 8, DeadlockLoserDataAccessException.class);
+ checkTranslation(sext, 9, CannotSerializeTransactionException.class);
+
+ // Test fallback. We assume that no database will ever return this error code,
+ // but 07xxx will be bad grammar picked up by the fallback SQLState translator
+ SQLException sex = new SQLException("", "07xxx", 666666666);
+ BadSqlGrammarException bsgex2 = (BadSqlGrammarException) sext.translate("task", "SQL2", sex);
+ assertEquals("SQL2", bsgex2.getSql());
+ assertEquals(sex, bsgex2.getSQLException());
+ }
+
+ private void checkTranslation(SQLExceptionTranslator sext, int errorCode, Class exClass) {
+ SQLException sex = new SQLException("", "", errorCode);
+ DataAccessException ex = sext.translate("", "", sex);
+ assertTrue(exClass.isInstance(ex));
+ assertTrue(ex.getCause() == sex);
+ }
+
+ public void testBatchExceptionTranslation() {
+ SQLExceptionTranslator sext = new SQLErrorCodeSQLExceptionTranslator(ERROR_CODES);
+
+ SQLException badSqlEx = new SQLException("", "", 1);
+ BatchUpdateException batchUdateEx = new BatchUpdateException();
+ batchUdateEx.setNextException(badSqlEx);
+ BadSqlGrammarException bsgex = (BadSqlGrammarException) sext.translate("task", "SQL", batchUdateEx);
+ assertEquals("SQL", bsgex.getSql());
+ assertEquals(badSqlEx, bsgex.getSQLException());
+ }
+
+
+ public void testCustomTranslateMethodTranslation() {
+ final String TASK = "TASK";
+ final String SQL = "SQL SELECT *";
+ final DataAccessException customDex = new DataAccessException("") {};
+
+ final SQLException badSqlEx = new SQLException("", "", 1);
+ SQLException intVioEx = new SQLException("", "", 6);
+
+ SQLErrorCodeSQLExceptionTranslator sext = new SQLErrorCodeSQLExceptionTranslator() {
+ protected DataAccessException customTranslate(String task, String sql, SQLException sqlex) {
+ assertEquals(TASK, task);
+ assertEquals(SQL, sql);
+ return (sqlex == badSqlEx) ? customDex : null;
+ }
+ };
+ sext.setSqlErrorCodes(ERROR_CODES);
+
+ // Shouldn't custom translate this
+ assertEquals(customDex, sext.translate(TASK, SQL, badSqlEx));
+ DataIntegrityViolationException diex = (DataIntegrityViolationException) sext.translate(TASK, SQL, intVioEx);
+ assertEquals(intVioEx, diex.getCause());
+ }
+
+ public void testCustomExceptionTranslation() {
+ final String TASK = "TASK";
+ final String SQL = "SQL SELECT *";
+ final SQLErrorCodes customErrorCodes = new SQLErrorCodes();
+ final CustomSQLErrorCodesTranslation customTranslation = new CustomSQLErrorCodesTranslation();
+
+ customErrorCodes.setBadSqlGrammarCodes(new String[] {"1", "2"});
+ customErrorCodes.setDataIntegrityViolationCodes(new String[] {"3", "4"});
+ customTranslation.setErrorCodes(new String[] {"1"});
+ customTranslation.setExceptionClass(CustomErrorCodeException.class);
+ customErrorCodes.setCustomTranslations(new CustomSQLErrorCodesTranslation[] {customTranslation});
+
+ SQLErrorCodeSQLExceptionTranslator sext = new SQLErrorCodeSQLExceptionTranslator();
+ sext.setSqlErrorCodes(customErrorCodes);
+
+ // Should custom translate this
+ SQLException badSqlEx = new SQLException("", "", 1);
+ assertEquals(CustomErrorCodeException.class, sext.translate(TASK, SQL, badSqlEx).getClass());
+ assertEquals(badSqlEx, sext.translate(TASK, SQL, badSqlEx).getCause());
+
+ // Shouldn't custom translate this
+ SQLException invResEx = new SQLException("", "", 3);
+ DataIntegrityViolationException diex = (DataIntegrityViolationException) sext.translate(TASK, SQL, invResEx);
+ assertEquals(invResEx, diex.getCause());
+
+ // Shouldn't custom translate this - invalid class
+ try {
+ customTranslation.setExceptionClass(String.class);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/SQLErrorCodesFactoryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/SQLErrorCodesFactoryTests.java
new file mode 100644
index 00000000000..52e1c1baff2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/SQLErrorCodesFactoryTests.java
@@ -0,0 +1,324 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jdbc.support;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+import java.util.Arrays;
+
+import javax.sql.DataSource;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+/**
+ * Tests for SQLErrorCodes loading.
+ *
+ * @author Rod Johnson
+ * @author Thomas Risberg
+ */
+public class SQLErrorCodesFactoryTests extends TestCase {
+
+ /**
+ * Check that a default instance returns empty error codes for an unknown database.
+ */
+ public void testDefaultInstanceWithNoSuchDatabase() {
+ SQLErrorCodes sec = SQLErrorCodesFactory.getInstance().getErrorCodes("xx");
+ assertTrue(sec.getBadSqlGrammarCodes().length == 0);
+ assertTrue(sec.getDataIntegrityViolationCodes().length == 0);
+ }
+
+ /**
+ * Check that a known database produces recognizable codes.
+ */
+ public void testDefaultInstanceWithOracle() {
+ SQLErrorCodes sec = SQLErrorCodesFactory.getInstance().getErrorCodes("Oracle");
+ assertIsOracle(sec);
+ }
+
+ private void assertIsOracle(SQLErrorCodes sec) {
+ assertTrue(sec.getBadSqlGrammarCodes().length > 0);
+ assertTrue(sec.getDataIntegrityViolationCodes().length > 0);
+ // This had better be a Bad SQL Grammar code
+ assertTrue(Arrays.binarySearch(sec.getBadSqlGrammarCodes(), "942") >= 0);
+ // This had better NOT be
+ assertFalse(Arrays.binarySearch(sec.getBadSqlGrammarCodes(), "9xx42") >= 0);
+ }
+
+ private void assertIsHsql(SQLErrorCodes sec) {
+ assertTrue(sec.getBadSqlGrammarCodes().length > 0);
+ assertTrue(sec.getDataIntegrityViolationCodes().length > 0);
+ // This had better be a Bad SQL Grammar code
+ assertTrue(Arrays.binarySearch(sec.getBadSqlGrammarCodes(), "-22") >= 0);
+ // This had better NOT be
+ assertFalse(Arrays.binarySearch(sec.getBadSqlGrammarCodes(), "-9") >= 0);
+ }
+
+ private void assertIsDB2(SQLErrorCodes sec) {
+ assertTrue(sec.getBadSqlGrammarCodes().length > 0);
+ assertTrue(sec.getDataIntegrityViolationCodes().length > 0);
+
+ assertFalse(Arrays.binarySearch(sec.getBadSqlGrammarCodes(), "942") >= 0);
+ // This had better NOT be
+ assertTrue(Arrays.binarySearch(sec.getBadSqlGrammarCodes(), "-204") >= 0);
+ }
+
+ public void testLookupOrder() {
+ class TestSQLErrorCodesFactory extends SQLErrorCodesFactory {
+ private int lookups = 0;
+ protected Resource loadResource(String path) {
+ ++lookups;
+ if (lookups == 1) {
+ assertEquals(SQLErrorCodesFactory.SQL_ERROR_CODE_DEFAULT_PATH, path);
+ return null;
+ }
+ else {
+ // Should have only one more lookup
+ assertEquals(2, lookups);
+ assertEquals(SQLErrorCodesFactory.SQL_ERROR_CODE_OVERRIDE_PATH, path);
+ return null;
+ }
+ }
+ }
+
+ // Should have failed to load without error
+ TestSQLErrorCodesFactory sf = new TestSQLErrorCodesFactory();
+ assertTrue(sf.getErrorCodes("XX").getBadSqlGrammarCodes().length == 0);
+ assertTrue(sf.getErrorCodes("Oracle").getDataIntegrityViolationCodes().length == 0);
+ }
+
+ /**
+ * Check that user defined error codes take precedence.
+ */
+ public void testFindUserDefinedCodes() {
+ class TestSQLErrorCodesFactory extends SQLErrorCodesFactory {
+ protected Resource loadResource(String path) {
+ if (SQLErrorCodesFactory.SQL_ERROR_CODE_OVERRIDE_PATH.equals(path)) {
+ return new ClassPathResource("test-error-codes.xml", SQLErrorCodesFactoryTests.class);
+ }
+ return null;
+ }
+ }
+
+ // Should have loaded without error
+ TestSQLErrorCodesFactory sf = new TestSQLErrorCodesFactory();
+ assertTrue(sf.getErrorCodes("XX").getBadSqlGrammarCodes().length == 0);
+ assertEquals(2, sf.getErrorCodes("Oracle").getBadSqlGrammarCodes().length);
+ assertEquals("1", sf.getErrorCodes("Oracle").getBadSqlGrammarCodes()[0]);
+ assertEquals("2", sf.getErrorCodes("Oracle").getBadSqlGrammarCodes()[1]);
+ }
+
+ public void testInvalidUserDefinedCodeFormat() {
+ class TestSQLErrorCodesFactory extends SQLErrorCodesFactory {
+ protected Resource loadResource(String path) {
+ if (SQLErrorCodesFactory.SQL_ERROR_CODE_OVERRIDE_PATH.equals(path)) {
+ // Guaranteed to be on the classpath, but most certainly NOT XML
+ return new ClassPathResource("SQLExceptionTranslator.class", SQLErrorCodesFactoryTests.class);
+ }
+ return null;
+ }
+ }
+
+ // Should have failed to load without error
+ TestSQLErrorCodesFactory sf = new TestSQLErrorCodesFactory();
+ assertTrue(sf.getErrorCodes("XX").getBadSqlGrammarCodes().length == 0);
+ assertEquals(0, sf.getErrorCodes("Oracle").getBadSqlGrammarCodes().length);
+ }
+
+ /**
+ * Check that custom error codes take precedence.
+ */
+ public void testFindCustomCodes() {
+ class TestSQLErrorCodesFactory extends SQLErrorCodesFactory {
+ protected Resource loadResource(String path) {
+ if (SQLErrorCodesFactory.SQL_ERROR_CODE_OVERRIDE_PATH.equals(path)) {
+ return new ClassPathResource("custom-error-codes.xml", SQLErrorCodesFactoryTests.class);
+ }
+ return null;
+ }
+ }
+
+ // Should have loaded without error
+ TestSQLErrorCodesFactory sf = new TestSQLErrorCodesFactory();
+ assertEquals(1, sf.getErrorCodes("Oracle").getCustomTranslations().length);
+ CustomSQLErrorCodesTranslation translation =
+ (CustomSQLErrorCodesTranslation) sf.getErrorCodes("Oracle").getCustomTranslations()[0];
+ assertEquals(CustomErrorCodeException.class, translation.getExceptionClass());
+ assertEquals(1, translation.getErrorCodes().length);
+ }
+
+ public void testDataSourceWithNullMetadata() throws Exception {
+
+ MockControl ctrlConnection = MockControl.createControl(Connection.class);
+ Connection mockConnection = (Connection) ctrlConnection.getMock();
+ mockConnection.getMetaData();
+ ctrlConnection.setReturnValue(null);
+ mockConnection.close();
+ ctrlConnection.setVoidCallable();
+ ctrlConnection.replay();
+
+ MockControl ctrlDataSource = MockControl.createControl(DataSource.class);
+ DataSource mockDataSource = (DataSource) ctrlDataSource.getMock();
+ mockDataSource.getConnection();
+ ctrlDataSource.setDefaultReturnValue(mockConnection);
+ ctrlDataSource.replay();
+
+ SQLErrorCodes sec = SQLErrorCodesFactory.getInstance().getErrorCodes(mockDataSource);
+ assertIsEmpty(sec);
+
+ ctrlConnection.verify();
+ ctrlDataSource.verify();
+ }
+
+ public void testGetFromDataSourceWithSQLException() throws Exception {
+
+ SQLException expectedSQLException = new SQLException();
+
+ MockControl ctrlDataSource = MockControl.createControl(DataSource.class);
+ DataSource mockDataSource = (DataSource) ctrlDataSource.getMock();
+ mockDataSource.getConnection();
+ ctrlDataSource.setThrowable(expectedSQLException);
+ ctrlDataSource.replay();
+
+ SQLErrorCodes sec = SQLErrorCodesFactory.getInstance().getErrorCodes(mockDataSource);
+ assertIsEmpty(sec);
+
+ ctrlDataSource.verify();
+ }
+
+ private void assertIsEmpty(SQLErrorCodes sec) {
+ // Codes should be empty
+ assertEquals(0, sec.getBadSqlGrammarCodes().length);
+ assertEquals(0, sec.getDataIntegrityViolationCodes().length);
+ }
+
+ private SQLErrorCodes getErrorCodesFromDataSource(String productName, SQLErrorCodesFactory factory) throws Exception {
+ MockControl mdControl = MockControl.createControl(DatabaseMetaData.class);
+ DatabaseMetaData md = (DatabaseMetaData) mdControl.getMock();
+ md.getDatabaseProductName();
+ mdControl.setReturnValue(productName);
+ mdControl.replay();
+
+ MockControl ctrlConnection = MockControl.createControl(Connection.class);
+ Connection mockConnection = (Connection) ctrlConnection.getMock();
+ mockConnection.getMetaData();
+ ctrlConnection.setReturnValue(md);
+ mockConnection.close();
+ ctrlConnection.setVoidCallable();
+ ctrlConnection.replay();
+
+ MockControl ctrlDataSource = MockControl.createControl(DataSource.class);
+ DataSource mockDataSource = (DataSource) ctrlDataSource.getMock();
+ mockDataSource.getConnection();
+ ctrlDataSource.setDefaultReturnValue(mockConnection);
+ ctrlDataSource.replay();
+
+ SQLErrorCodesFactory secf = null;
+ if (factory != null) {
+ secf = factory;
+ }
+ else {
+ secf = SQLErrorCodesFactory.getInstance();
+ }
+
+ SQLErrorCodes sec = secf.getErrorCodes(mockDataSource);
+
+ mdControl.verify();
+ ctrlConnection.verify();
+ ctrlDataSource.verify();
+
+ SQLErrorCodes sec2 = secf.getErrorCodes(mockDataSource);
+ assertSame("Cached per DataSource", sec2, sec);
+
+ return sec;
+ }
+
+ public void testOracleRecognizedFromMetadata() throws Exception {
+ SQLErrorCodes sec = getErrorCodesFromDataSource("Oracle", null);
+ assertIsOracle(sec);
+ }
+
+ public void testHsqlRecognizedFromMetadata() throws Exception {
+ SQLErrorCodes sec = getErrorCodesFromDataSource("HSQL Database Engine", null);
+ assertIsHsql(sec);
+ }
+
+ public void testDB2RecognizedFromMetadata() throws Exception {
+ SQLErrorCodes sec = getErrorCodesFromDataSource("DB2", null);
+ assertIsDB2(sec);
+ sec = getErrorCodesFromDataSource("DB2/", null);
+ assertIsDB2(sec);
+ sec = getErrorCodesFromDataSource("DB-2", null);
+ assertIsEmpty(sec);
+ }
+
+ /**
+ * Check that wild card database name works.
+ */
+ public void testWildCardNameRecognized() throws Exception {
+ class WildcardSQLErrorCodesFactory extends SQLErrorCodesFactory {
+ protected Resource loadResource(String path) {
+ if (SQLErrorCodesFactory.SQL_ERROR_CODE_OVERRIDE_PATH.equals(path)) {
+ return new ClassPathResource("wildcard-error-codes.xml", SQLErrorCodesFactoryTests.class);
+ }
+ return null;
+ }
+ }
+
+ WildcardSQLErrorCodesFactory factory = new WildcardSQLErrorCodesFactory();
+ SQLErrorCodes sec = getErrorCodesFromDataSource("DB2", factory);
+ assertIsDB2(sec);
+ sec = getErrorCodesFromDataSource("DB2 UDB for Xxxxx", factory);
+ assertIsDB2(sec);
+
+ sec = getErrorCodesFromDataSource("DB3", factory);
+ assertIsDB2(sec);
+ sec = getErrorCodesFromDataSource("DB3/", factory);
+ assertIsDB2(sec);
+ sec = getErrorCodesFromDataSource("/DB3", factory);
+ assertIsDB2(sec);
+ sec = getErrorCodesFromDataSource("/DB3", factory);
+ assertIsDB2(sec);
+ sec = getErrorCodesFromDataSource("/DB3/", factory);
+ assertIsDB2(sec);
+ sec = getErrorCodesFromDataSource("DB-3", factory);
+ assertIsEmpty(sec);
+
+ sec = getErrorCodesFromDataSource("DB1", factory);
+ assertIsDB2(sec);
+ sec = getErrorCodesFromDataSource("DB1/", factory);
+ assertIsDB2(sec);
+ sec = getErrorCodesFromDataSource("/DB1", factory);
+ assertIsEmpty(sec);
+ sec = getErrorCodesFromDataSource("/DB1/", factory);
+ assertIsEmpty(sec);
+
+ sec = getErrorCodesFromDataSource("DB0", factory);
+ assertIsDB2(sec);
+ sec = getErrorCodesFromDataSource("/DB0", factory);
+ assertIsDB2(sec);
+ sec = getErrorCodesFromDataSource("DB0/", factory);
+ assertIsEmpty(sec);
+ sec = getErrorCodesFromDataSource("/DB0/", factory);
+ assertIsEmpty(sec);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/SQLExceptionSubclassFactory.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/SQLExceptionSubclassFactory.java
new file mode 100644
index 00000000000..3d6f05949a7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/SQLExceptionSubclassFactory.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.support;
+
+import java.sql.SQLDataException;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.sql.SQLIntegrityConstraintViolationException;
+import java.sql.SQLInvalidAuthorizationSpecException;
+import java.sql.SQLNonTransientConnectionException;
+import java.sql.SQLRecoverableException;
+import java.sql.SQLSyntaxErrorException;
+import java.sql.SQLTimeoutException;
+import java.sql.SQLTransactionRollbackException;
+import java.sql.SQLTransientConnectionException;
+
+/**
+ * Class to generate Java 6 SQLException subclasses for testing purposes.
+ *
+ * @author Thomas Risberg
+ */
+public class SQLExceptionSubclassFactory {
+
+ public static SQLException newSQLDataException(String reason, String SQLState, int vendorCode) {
+ return new SQLDataException(reason, SQLState, vendorCode);
+ }
+
+ public static SQLException newSQLFeatureNotSupportedException(String reason, String SQLState, int vendorCode) {
+ return new SQLFeatureNotSupportedException(reason, SQLState, vendorCode);
+ }
+
+ public static SQLException newSQLIntegrityConstraintViolationException(String reason, String SQLState, int vendorCode) {
+ return new SQLIntegrityConstraintViolationException(reason, SQLState, vendorCode);
+ }
+
+ public static SQLException newSQLInvalidAuthorizationSpecException(String reason, String SQLState, int vendorCode) {
+ return new SQLInvalidAuthorizationSpecException(reason, SQLState, vendorCode);
+ }
+
+ public static SQLException newSQLNonTransientConnectionException(String reason, String SQLState, int vendorCode) {
+ return new SQLNonTransientConnectionException(reason, SQLState, vendorCode);
+ }
+
+ public static SQLException newSQLSyntaxErrorException(String reason, String SQLState, int vendorCode) {
+ return new SQLSyntaxErrorException(reason, SQLState, vendorCode);
+ }
+
+ public static SQLException newSQLTransactionRollbackException(String reason, String SQLState, int vendorCode) {
+ return new SQLTransactionRollbackException(reason, SQLState, vendorCode);
+ }
+
+ public static SQLException newSQLTransientConnectionException(String reason, String SQLState, int vendorCode) {
+ return new SQLTransientConnectionException(reason, SQLState, vendorCode);
+ }
+
+ public static SQLException newSQLTimeoutException(String reason, String SQLState, int vendorCode) {
+ return new SQLTimeoutException(reason, SQLState, vendorCode);
+ }
+
+ public static SQLException newSQLRecoverableException(String reason, String SQLState, int vendorCode) {
+ return new SQLRecoverableException(reason, SQLState, vendorCode);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/SQLExceptionSubclassTranslatorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/SQLExceptionSubclassTranslatorTests.java
new file mode 100644
index 00000000000..4c63040b537
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/SQLExceptionSubclassTranslatorTests.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.support;
+
+import java.sql.SQLException;
+
+import junit.framework.TestCase;
+
+import org.springframework.core.JdkVersion;
+import org.springframework.dao.ConcurrencyFailureException;
+import org.springframework.dao.DataAccessResourceFailureException;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+import org.springframework.dao.PermissionDeniedDataAccessException;
+import org.springframework.dao.RecoverableDataAccessException;
+import org.springframework.dao.TransientDataAccessResourceException;
+import org.springframework.jdbc.BadSqlGrammarException;
+
+/**
+ * @author Thomas Risberg
+ */
+public class SQLExceptionSubclassTranslatorTests extends TestCase {
+
+ private static SQLErrorCodes ERROR_CODES = new SQLErrorCodes();
+
+ static {
+ ERROR_CODES.setBadSqlGrammarCodes(new String[] { "1" });
+ }
+
+
+ public void testErrorCodeTranslation() {
+ if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_16) {
+ return;
+ }
+
+ SQLExceptionTranslator sext = new SQLErrorCodeSQLExceptionTranslator(ERROR_CODES);
+
+ SQLException dataIntegrityViolationEx = SQLExceptionSubclassFactory.newSQLDataException("", "", 0);
+ DataIntegrityViolationException divex = (DataIntegrityViolationException) sext.translate("task", "SQL", dataIntegrityViolationEx);
+ assertEquals(dataIntegrityViolationEx, divex.getCause());
+
+ SQLException featureNotSupEx = SQLExceptionSubclassFactory.newSQLFeatureNotSupportedException("", "", 0);
+ InvalidDataAccessApiUsageException idaex = (InvalidDataAccessApiUsageException) sext.translate("task", "SQL", featureNotSupEx);
+ assertEquals(featureNotSupEx, idaex.getCause());
+
+ SQLException dataIntegrityViolationEx2 = SQLExceptionSubclassFactory.newSQLIntegrityConstraintViolationException("", "", 0);
+ DataIntegrityViolationException divex2 = (DataIntegrityViolationException) sext.translate("task", "SQL", dataIntegrityViolationEx2);
+ assertEquals(dataIntegrityViolationEx2, divex2.getCause());
+
+ SQLException permissionDeniedEx = SQLExceptionSubclassFactory.newSQLInvalidAuthorizationSpecException("", "", 0);
+ PermissionDeniedDataAccessException pdaex = (PermissionDeniedDataAccessException) sext.translate("task", "SQL", permissionDeniedEx);
+ assertEquals(permissionDeniedEx, pdaex.getCause());
+
+ SQLException dataAccessResourceEx = SQLExceptionSubclassFactory.newSQLNonTransientConnectionException("", "", 0);
+ DataAccessResourceFailureException darex = (DataAccessResourceFailureException) sext.translate("task", "SQL", dataAccessResourceEx);
+ assertEquals(dataAccessResourceEx, darex.getCause());
+
+ SQLException badSqlEx2 = SQLExceptionSubclassFactory.newSQLSyntaxErrorException("", "", 0);
+ BadSqlGrammarException bsgex2 = (BadSqlGrammarException) sext.translate("task", "SQL2", badSqlEx2);
+ assertEquals("SQL2", bsgex2.getSql());
+ assertEquals(badSqlEx2, bsgex2.getSQLException());
+
+ SQLException tranRollbackEx = SQLExceptionSubclassFactory.newSQLTransactionRollbackException("", "", 0);
+ ConcurrencyFailureException cfex = (ConcurrencyFailureException) sext.translate("task", "SQL", tranRollbackEx);
+ assertEquals(tranRollbackEx, cfex.getCause());
+
+ SQLException transientConnEx = SQLExceptionSubclassFactory.newSQLTransientConnectionException("", "", 0);
+ TransientDataAccessResourceException tdarex = (TransientDataAccessResourceException) sext.translate("task", "SQL", transientConnEx);
+ assertEquals(transientConnEx, tdarex.getCause());
+
+ SQLException transientConnEx2 = SQLExceptionSubclassFactory.newSQLTimeoutException("", "", 0);
+ TransientDataAccessResourceException tdarex2 = (TransientDataAccessResourceException) sext.translate("task", "SQL", transientConnEx2);
+ assertEquals(transientConnEx2, tdarex2.getCause());
+
+ SQLException recoverableEx = SQLExceptionSubclassFactory.newSQLRecoverableException("", "", 0);
+ RecoverableDataAccessException rdaex2 = (RecoverableDataAccessException) sext.translate("task", "SQL", recoverableEx);
+ assertEquals(recoverableEx, rdaex2.getCause());
+
+ // Test classic error code translation. We should move there next if the exception we pass in is not one
+ // of the new sub-classes.
+ SQLException sexEct = new SQLException("", "", 1);
+ BadSqlGrammarException bsgEct = (BadSqlGrammarException) sext.translate("task", "SQL-ECT", sexEct);
+ assertEquals("SQL-ECT", bsgEct.getSql());
+ assertEquals(sexEct, bsgEct.getSQLException());
+
+ // Test fallback. We assume that no database will ever return this error code,
+ // but 07xxx will be bad grammar picked up by the fallback SQLState translator
+ SQLException sexFbt = new SQLException("", "07xxx", 666666666);
+ BadSqlGrammarException bsgFbt = (BadSqlGrammarException) sext.translate("task", "SQL-FBT", sexFbt);
+ assertEquals("SQL-FBT", bsgFbt.getSql());
+ assertEquals(sexFbt, bsgFbt.getSQLException());
+ // and 08xxx will be data resource failure (non-transient) picked up by the fallback SQLState translator
+ SQLException sexFbt2 = new SQLException("", "08xxx", 666666666);
+ DataAccessResourceFailureException darfFbt = (DataAccessResourceFailureException) sext.translate("task", "SQL-FBT2", sexFbt2);
+ assertEquals(sexFbt2, darfFbt.getCause());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/SQLStateExceptionTranslatorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/SQLStateExceptionTranslatorTests.java
new file mode 100644
index 00000000000..35a66acbf34
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/SQLStateExceptionTranslatorTests.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jdbc.support;
+
+import java.sql.SQLException;
+
+import junit.framework.TestCase;
+
+import org.springframework.jdbc.BadSqlGrammarException;
+import org.springframework.jdbc.UncategorizedSQLException;
+
+/**
+ *
+ * @author Rod Johnson
+ * @since 13-Jan-03
+ */
+public class SQLStateExceptionTranslatorTests extends TestCase {
+
+ private SQLStateSQLExceptionTranslator trans = new SQLStateSQLExceptionTranslator();
+
+ // ALSO CHECK CHAIN of SQLExceptions!?
+ // also allow chain of translators? default if can't do specific?
+
+ public void testBadSqlGrammar() {
+ String sql = "SELECT FOO FROM BAR";
+ SQLException sex = new SQLException("Message", "42001", 1);
+ try {
+ throw this.trans.translate("task", sql, sex);
+ }
+ catch (BadSqlGrammarException ex) {
+ // OK
+ assertTrue("SQL is correct", sql.equals(ex.getSql()));
+ assertTrue("Exception matches", sex.equals(ex.getSQLException()));
+ }
+ }
+
+ public void testInvalidSqlStateCode() {
+ String sql = "SELECT FOO FROM BAR";
+ SQLException sex = new SQLException("Message", "NO SUCH CODE", 1);
+ try {
+ throw this.trans.translate("task", sql, sex);
+ }
+ catch (UncategorizedSQLException ex) {
+ // OK
+ assertTrue("SQL is correct", sql.equals(ex.getSql()));
+ assertTrue("Exception matches", sex.equals(ex.getSQLException()));
+ }
+ }
+
+ /**
+ * PostgreSQL can return null
+ * SAP DB can apparently return empty SQL code
+ * Bug 729170
+ */
+ public void testMalformedSqlStateCodes() {
+ String sql = "SELECT FOO FROM BAR";
+ SQLException sex = new SQLException("Message", null, 1);
+ testMalformedSqlStateCode(sex);
+
+ sex = new SQLException("Message", "", 1);
+ testMalformedSqlStateCode(sex);
+
+ // One char's not allowed
+ sex = new SQLException("Message", "I", 1);
+ testMalformedSqlStateCode(sex);
+ }
+
+
+ private void testMalformedSqlStateCode(SQLException sex) {
+ String sql = "SELECT FOO FROM BAR";
+ try {
+ throw this.trans.translate("task", sql, sex);
+ }
+ catch (UncategorizedSQLException ex) {
+ // OK
+ assertTrue("SQL is correct", sql.equals(ex.getSql()));
+ assertTrue("Exception matches", sex.equals(ex.getSQLException()));
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/SQLStateSQLExceptionTranslatorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/SQLStateSQLExceptionTranslatorTests.java
new file mode 100644
index 00000000000..418c0f8e084
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/SQLStateSQLExceptionTranslatorTests.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jdbc.support;
+
+import java.sql.SQLException;
+
+import junit.framework.TestCase;
+
+import org.springframework.dao.ConcurrencyFailureException;
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.DataAccessResourceFailureException;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.dao.TransientDataAccessResourceException;
+import org.springframework.jdbc.BadSqlGrammarException;
+import org.springframework.jdbc.UncategorizedSQLException;
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class SQLStateSQLExceptionTranslatorTests extends TestCase {
+
+ private static final String REASON = "The game is afoot!";
+
+ private static final String TASK = "Counting sheep... yawn.";
+
+ private static final String SQL = "select count(0) from t_sheep where over_fence = ... yawn... 1";
+
+
+ public void testTranslateNullException() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new SQLStateSQLExceptionTranslator().translate("", "", null);
+ }
+ }.runTest();
+ }
+
+ public void testTranslateBadSqlGrammar() throws Exception {
+ doTest("07", BadSqlGrammarException.class);
+ }
+
+ public void testTranslateDataIntegrityViolation() throws Exception {
+ doTest("23", DataIntegrityViolationException.class);
+ }
+
+ public void testTranslateDataAccessResourceFailure() throws Exception {
+ doTest("53", DataAccessResourceFailureException.class);
+ }
+
+ public void testTranslateTransientDataAccessResourceFailure() throws Exception {
+ doTest("S1", TransientDataAccessResourceException.class);
+ }
+
+ public void testTranslateConcurrencyFailure() throws Exception {
+ doTest("40", ConcurrencyFailureException.class);
+ }
+
+ public void testTranslateUncategorized() throws Exception {
+ doTest("00000000", UncategorizedSQLException.class);
+ }
+
+
+ private void doTest(String sqlState, Class dataAccessExceptionType) {
+ SQLException ex = new SQLException(REASON, sqlState);
+ SQLExceptionTranslator translator = new SQLStateSQLExceptionTranslator();
+ DataAccessException dax = translator.translate(TASK, SQL, ex);
+ assertNotNull("Translation must *never* result in a null DataAccessException being returned.", dax);
+ assertEquals("Wrong DataAccessException type returned as the result of the translation", dataAccessExceptionType, dax.getClass());
+ assertNotNull("The original SQLException must be preserved in the translated DataAccessException", dax.getCause());
+ assertSame("The exact same original SQLException must be preserved in the translated DataAccessException", ex, dax.getCause());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/custom-error-codes.xml b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/custom-error-codes.xml
new file mode 100644
index 00000000000..a2aa1898320
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/custom-error-codes.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+ 1,2
+ 1,1400,1722
+
+
+
+ 999
+
+ org.springframework.jdbc.support.CustomErrorCodeException
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/rowset/ResultSetWrappingRowSetTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/rowset/ResultSetWrappingRowSetTests.java
new file mode 100644
index 00000000000..489daa2ee1b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/rowset/ResultSetWrappingRowSetTests.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jdbc.support.rowset;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+import java.sql.Date;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Time;
+import java.sql.Timestamp;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.jdbc.InvalidResultSetAccessException;
+
+/**
+ * @author Thomas Risberg
+ */
+public class ResultSetWrappingRowSetTests extends TestCase {
+
+ private MockControl rsetControl;
+ private ResultSet rset;
+ private ResultSetWrappingSqlRowSet rowset;
+
+ public void setUp() throws Exception {
+ rsetControl = MockControl.createControl(ResultSet.class);
+ rset = (ResultSet) rsetControl.getMock();
+ rset.getMetaData();
+ rsetControl.setReturnValue(null);
+ }
+
+ public void testGetBigDecimalInt() throws Exception {
+ Method rset = ResultSet.class.getDeclaredMethod("getBigDecimal", new Class[] {int.class});
+ Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getBigDecimal", new Class[] {int.class});
+ doTest(rset, rowset, new Integer(1), BigDecimal.valueOf(1));
+ }
+
+ public void testGetBigDecimalString() throws Exception {
+ Method rset = ResultSet.class.getDeclaredMethod("getBigDecimal", new Class[] {String.class});
+ Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getBigDecimal", new Class[] {String.class});
+ doTest(rset, rowset, "test", BigDecimal.valueOf(1));
+ }
+
+ public void testGetStringInt() throws Exception {
+ Method rset = ResultSet.class.getDeclaredMethod("getString", new Class[] {int.class});
+ Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getString", new Class[] {int.class});
+ doTest(rset, rowset, new Integer(1), "test");
+ }
+
+ public void testGetStringString() throws Exception {
+ Method rset = ResultSet.class.getDeclaredMethod("getString", new Class[] {String.class});
+ Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getString", new Class[] {String.class});
+ doTest(rset, rowset, "test", "test");
+ }
+
+ public void testGetTimestampInt() throws Exception {
+ Method rset = ResultSet.class.getDeclaredMethod("getTimestamp", new Class[] {int.class});
+ Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getTimestamp", new Class[] {int.class});
+ doTest(rset, rowset, new Integer(1), new Timestamp(1234l));
+ }
+
+ public void testGetTimestampString() throws Exception {
+ Method rset = ResultSet.class.getDeclaredMethod("getTimestamp", new Class[] {String.class});
+ Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getTimestamp", new Class[] {String.class});
+ doTest(rset, rowset, "test", new Timestamp(1234l));
+ }
+
+ public void testGetDateInt() throws Exception {
+ Method rset = ResultSet.class.getDeclaredMethod("getDate", new Class[] {int.class});
+ Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getDate", new Class[] {int.class});
+ doTest(rset, rowset, new Integer(1), new Date(1234l));
+ }
+
+ public void testGetDateString() throws Exception {
+ Method rset = ResultSet.class.getDeclaredMethod("getDate", new Class[] {String.class});
+ Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getDate", new Class[] {String.class});
+ doTest(rset, rowset, "test", new Date(1234l));
+ }
+
+ public void testGetTimeInt() throws Exception {
+ Method rset = ResultSet.class.getDeclaredMethod("getTime", new Class[] {int.class});
+ Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getTime", new Class[] {int.class});
+ doTest(rset, rowset, new Integer(1), new Time(1234l));
+ }
+
+ public void testGetTimeString() throws Exception {
+ Method rset = ResultSet.class.getDeclaredMethod("getTime", new Class[] {String.class});
+ Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getTime", new Class[] {String.class});
+ doTest(rset, rowset, "test", new Time(1234l));
+ }
+
+ public void testGetObjectInt() throws Exception {
+ Method rset = ResultSet.class.getDeclaredMethod("getObject", new Class[] {int.class});
+ Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getObject", new Class[] {int.class});
+ doTest(rset, rowset, new Integer(1), new Object());
+ }
+
+ public void testGetObjectString() throws Exception {
+ Method rset = ResultSet.class.getDeclaredMethod("getObject", new Class[] {String.class});
+ Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getObject", new Class[] {String.class});
+ doTest(rset, rowset, "test", new Object());
+ }
+
+ public void testGetIntInt() throws Exception {
+ Method rset = ResultSet.class.getDeclaredMethod("getInt", new Class[] {int.class});
+ Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getInt", new Class[] {int.class});
+ doTest(rset, rowset, new Integer(1), new Integer(1));
+ }
+
+ public void testGetIntString() throws Exception {
+ Method rset = ResultSet.class.getDeclaredMethod("getInt", new Class[] {String.class});
+ Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getInt", new Class[] {String.class});
+ doTest(rset, rowset, "test", new Integer(1));
+ }
+
+ public void testGetFloatInt() throws Exception {
+ Method rset = ResultSet.class.getDeclaredMethod("getFloat", new Class[] {int.class});
+ Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getFloat", new Class[] {int.class});
+ doTest(rset, rowset, new Integer(1), new Float(1));
+ }
+
+ public void testGetFloatString() throws Exception {
+ Method rset = ResultSet.class.getDeclaredMethod("getFloat", new Class[] {String.class});
+ Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getFloat", new Class[] {String.class});
+ doTest(rset, rowset, "test", new Float(1));
+ }
+
+ public void testGetDoubleInt() throws Exception {
+ Method rset = ResultSet.class.getDeclaredMethod("getDouble", new Class[] {int.class});
+ Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getDouble", new Class[] {int.class});
+ doTest(rset, rowset, new Integer(1), new Double(1));
+ }
+
+ public void testGetDoubleString() throws Exception {
+ Method rset = ResultSet.class.getDeclaredMethod("getDouble", new Class[] {String.class});
+ Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getDouble", new Class[] {String.class});
+ doTest(rset, rowset, "test", new Double(1));
+ }
+
+ public void testGetLongInt() throws Exception {
+ Method rset = ResultSet.class.getDeclaredMethod("getLong", new Class[] {int.class});
+ Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getLong", new Class[] {int.class});
+ doTest(rset, rowset, new Integer(1), new Long(1));
+ }
+
+ public void testGetLongString() throws Exception {
+ Method rset = ResultSet.class.getDeclaredMethod("getLong", new Class[] {String.class});
+ Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getLong", new Class[] {String.class});
+ doTest(rset, rowset, "test", new Long(1));
+ }
+
+ public void testGetBooleanInt() throws Exception {
+ Method rset = ResultSet.class.getDeclaredMethod("getBoolean", new Class[] {int.class});
+ Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getBoolean", new Class[] {int.class});
+ doTest(rset, rowset, new Integer(1), new Boolean(true));
+ }
+
+ public void testGetBooleanString() throws Exception {
+ Method rset = ResultSet.class.getDeclaredMethod("getBoolean", new Class[] {String.class});
+ Method rowset = ResultSetWrappingSqlRowSet.class.getDeclaredMethod("getBoolean", new Class[] {String.class});
+ doTest(rset, rowset, "test", new Boolean(true));
+ }
+
+ private void doTest(Method rsetMethod, Method rowsetMethod, Object arg, Object ret) throws Exception {
+ rsetMethod.invoke(rset, new Object[] {arg});
+ if (ret instanceof Double) {
+ rsetControl.setReturnValue(((Double) ret).doubleValue());
+ }
+ else if (ret instanceof Float) {
+ rsetControl.setReturnValue(((Float) ret).floatValue());
+ }
+ else if (ret instanceof Integer) {
+ rsetControl.setReturnValue(((Integer) ret).intValue());
+ }
+ else if (ret instanceof Short) {
+ rsetControl.setReturnValue(((Short) ret).shortValue());
+ }
+ else if (ret instanceof Long) {
+ rsetControl.setReturnValue(((Long) ret).longValue());
+ }
+ else if (ret instanceof Boolean) {
+ rsetControl.setReturnValue(((Boolean) ret).booleanValue());
+ }
+ else if (ret instanceof Byte) {
+ rsetControl.setReturnValue(((Byte) ret).byteValue());
+ }
+ else {
+ rsetControl.setReturnValue(ret);
+ }
+ rsetMethod.invoke(rset, new Object[] {arg});
+ rsetControl.setThrowable(new SQLException("test"));
+
+ rsetControl.replay();
+
+ rowset = new ResultSetWrappingSqlRowSet(rset);
+ rowsetMethod.invoke(rowset, new Object[] {arg});
+ try {
+ rowsetMethod.invoke(rowset, new Object[] {arg});
+ fail("InvalidResultSetAccessException should have been thrown");
+ }
+ catch (InvocationTargetException ex) {
+ assertEquals(InvalidResultSetAccessException.class, ex.getTargetException().getClass());
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/test-error-codes.xml b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/test-error-codes.xml
new file mode 100644
index 00000000000..dd3fc33004b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/test-error-codes.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+ 1,2
+ 1,1400,1722
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/wildcard-error-codes.xml b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/wildcard-error-codes.xml
new file mode 100644
index 00000000000..b44c0a9c1b8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jdbc/support/wildcard-error-codes.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+ 1,2,942
+ 1,1400,1722
+
+
+
+ *DB0
+ -204,1,2
+ 3,4
+
+
+
+ DB1*
+ -204,1,2
+ 3,4
+
+
+
+ *DB2*
+ -204,1,2
+ 3,4
+
+
+
+ *DB3*
+ -204,1,2
+ 3,4
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/StubConnectionFactory.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/StubConnectionFactory.java
new file mode 100644
index 00000000000..dced87b7168
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/StubConnectionFactory.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jms;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+
+/**
+ * A stub implementation of the JMS ConnectionFactory for testing.
+ *
+ * @author Mark Fisher
+ */
+public class StubConnectionFactory implements ConnectionFactory {
+
+ public Connection createConnection() throws JMSException {
+ return null;
+ }
+
+ public Connection createConnection(String username, String password) throws JMSException {
+ return null;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/StubQueue.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/StubQueue.java
new file mode 100644
index 00000000000..20586ae9522
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/StubQueue.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jms;
+
+import javax.jms.Queue;
+
+/**
+ * Stub implementation of the {@link javax.jms.Queue} interface.
+ *
+ * @author Rick Evans
+ */
+public class StubQueue implements Queue {
+
+ public static final String DEFAULT_QUEUE_NAME = "banjo";
+
+
+ private String queueName = DEFAULT_QUEUE_NAME;
+
+
+ public StubQueue() {
+ }
+
+ public StubQueue(String queueName) {
+ this.queueName = queueName;
+ }
+
+
+ public String getQueueName() {
+ return this.queueName;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/StubTopic.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/StubTopic.java
new file mode 100644
index 00000000000..022ecdfbdb7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/StubTopic.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jms;
+
+import javax.jms.Topic;
+
+/**
+ * Stub implementation of the {@link Topic} interface.
+ *
+ * @author Rick Evans
+ */
+public class StubTopic implements Topic {
+
+ public static final String DEFAULT_TOPIC_NAME = "banjo";
+
+
+ private String topicName = DEFAULT_TOPIC_NAME;
+
+
+ public StubTopic() {
+ }
+
+ public StubTopic(String topicName) {
+ this.topicName = topicName;
+ }
+
+
+ public String getTopicName() {
+ return this.topicName;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/config/JmsNamespaceHandlerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/config/JmsNamespaceHandlerTests.java
new file mode 100644
index 00000000000..71ce9404815
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/config/JmsNamespaceHandlerTests.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jms.config;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import javax.jms.ConnectionFactory;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import javax.jms.TextMessage;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.parsing.ComponentDefinition;
+import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
+import org.springframework.beans.factory.parsing.EmptyReaderEventListener;
+import org.springframework.beans.factory.parsing.PassThroughSourceExtractor;
+import org.springframework.beans.factory.parsing.ReaderEventListener;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.jca.endpoint.GenericMessageEndpointManager;
+import org.springframework.jms.listener.DefaultMessageListenerContainer;
+import org.springframework.jms.listener.endpoint.JmsMessageEndpointManager;
+
+/**
+ * @author Mark Fisher
+ * @author Juergen Hoeller
+ * @author Christian Dupuis
+ */
+public class JmsNamespaceHandlerTests extends TestCase {
+
+ private static final String DEFAULT_CONNECTION_FACTORY = "connectionFactory";
+
+ private static final String EXPLICIT_CONNECTION_FACTORY = "testConnectionFactory";
+
+ private ToolingTestApplicationContext context;
+
+
+ protected void setUp() throws Exception {
+ this.context = new ToolingTestApplicationContext("jmsNamespaceHandlerTests.xml", getClass());
+ }
+
+ protected void tearDown() throws Exception {
+ this.context.close();
+ }
+
+
+ public void testBeansCreated() {
+ Map containers = context.getBeansOfType(DefaultMessageListenerContainer.class);
+ assertEquals("Context should contain 3 JMS listener containers", 3, containers.size());
+
+ containers = context.getBeansOfType(GenericMessageEndpointManager.class);
+ assertEquals("Context should contain 3 JCA endpoint containers", 3, containers.size());
+ }
+
+ public void testContainerConfiguration() throws Exception {
+ Map containers = context.getBeansOfType(DefaultMessageListenerContainer.class);
+ ConnectionFactory defaultConnectionFactory = (ConnectionFactory) context.getBean(DEFAULT_CONNECTION_FACTORY);
+ ConnectionFactory explicitConnectionFactory = (ConnectionFactory) context.getBean(EXPLICIT_CONNECTION_FACTORY);
+
+ int defaultConnectionFactoryCount = 0;
+ int explicitConnectionFactoryCount = 0;
+
+ Iterator iter = containers.values().iterator();
+ while (iter.hasNext()) {
+ DefaultMessageListenerContainer container = (DefaultMessageListenerContainer) iter.next();
+ if (container.getConnectionFactory().equals(defaultConnectionFactory)) {
+ defaultConnectionFactoryCount++;
+ }
+ else if (container.getConnectionFactory().equals(explicitConnectionFactory)) {
+ explicitConnectionFactoryCount++;
+ }
+ }
+
+ assertEquals("1 container should have the default connectionFactory", 1, defaultConnectionFactoryCount);
+ assertEquals("2 containers should have the explicit connectionFactory", 2, explicitConnectionFactoryCount);
+ }
+
+ public void testListeners() throws Exception {
+ TestBean testBean1 = (TestBean) context.getBean("testBean1");
+ TestBean testBean2 = (TestBean) context.getBean("testBean2");
+ TestMessageListener testBean3 = (TestMessageListener) context.getBean("testBean3");
+
+ assertNull(testBean1.getName());
+ assertNull(testBean2.getName());
+ assertNull(testBean3.message);
+
+ MockControl control1 = MockControl.createControl(TextMessage.class);
+ TextMessage message1 = (TextMessage) control1.getMock();
+ control1.expectAndReturn(message1.getText(), "Test1");
+ control1.replay();
+
+ MessageListener listener1 = getListener("listener1");
+ listener1.onMessage(message1);
+ assertEquals("Test1", testBean1.getName());
+ control1.verify();
+
+ MockControl control2 = MockControl.createControl(TextMessage.class);
+ TextMessage message2 = (TextMessage) control2.getMock();
+ control2.expectAndReturn(message2.getText(), "Test2");
+ control2.replay();
+
+ MessageListener listener2 = getListener("listener2");
+ listener2.onMessage(message2);
+ assertEquals("Test2", testBean2.getName());
+ control2.verify();
+
+ MockControl control3 = MockControl.createControl(TextMessage.class);
+ TextMessage message3 = (TextMessage) control3.getMock();
+ control3.replay();
+
+ MessageListener listener3 = getListener(DefaultMessageListenerContainer.class.getName() + "#0");
+ listener3.onMessage(message3);
+ assertSame(message3, testBean3.message);
+ control3.verify();
+ }
+
+ private MessageListener getListener(String containerBeanName) {
+ DefaultMessageListenerContainer container = (DefaultMessageListenerContainer) this.context.getBean(containerBeanName);
+ return (MessageListener) container.getMessageListener();
+ }
+
+ public void testComponentRegistration() {
+ assertTrue("Parser should have registered a component named 'listener1'", context.containsComponentDefinition("listener1"));
+ assertTrue("Parser should have registered a component named 'listener2'", context.containsComponentDefinition("listener2"));
+ assertTrue("Parser should have registered a component named 'listener3'", context.containsComponentDefinition("listener3"));
+ assertTrue("Parser should have registered a component named '" + DefaultMessageListenerContainer.class.getName() + "#0'",
+ context.containsComponentDefinition(DefaultMessageListenerContainer.class.getName() + "#0"));
+ assertTrue("Parser should have registered a component named '" + JmsMessageEndpointManager.class.getName() + "#0'",
+ context.containsComponentDefinition(JmsMessageEndpointManager.class.getName() + "#0"));
+ }
+
+ public void testSourceExtraction() {
+ Iterator iterator = context.getRegisteredComponents();
+ while (iterator.hasNext()) {
+ ComponentDefinition compDef = (ComponentDefinition) iterator.next();
+ if (compDef instanceof CompositeComponentDefinition) {
+ assertNotNull("CompositeComponentDefinition '" + compDef.getName()+ "' has no source attachment", ((CompositeComponentDefinition) compDef).getSource());
+ }
+ validateComponentDefinition(compDef);
+ }
+ }
+
+ private void validateComponentDefinition(ComponentDefinition compDef) {
+ BeanDefinition[] beanDefs = compDef.getBeanDefinitions();
+ for (int i = 0; i < beanDefs.length; i++) {
+ if (beanDefs[i] instanceof AbstractBeanDefinition) {
+ assertNotNull("AbstractBeanDefinition has no source attachment", ((AbstractBeanDefinition) beanDefs[i]).getSource());
+ }
+ }
+ }
+
+
+ public static class TestMessageListener implements MessageListener {
+
+ public Message message;
+
+ public void onMessage(Message message) {
+ this.message = message;
+ }
+ }
+
+
+ /**
+ * Internal extension that registers a {@link ReaderEventListener} to store
+ * registered {@link ComponentDefinition}s.
+ */
+ private static class ToolingTestApplicationContext extends ClassPathXmlApplicationContext {
+
+ private static final Set REGISTERED_COMPONENTS = new HashSet();
+
+ public ToolingTestApplicationContext(String path, Class clazz)
+ throws BeansException {
+ super(path, clazz);
+ }
+
+ protected void initBeanDefinitionReader(
+ XmlBeanDefinitionReader beanDefinitionReader) {
+ beanDefinitionReader.setEventListener(new StoringReaderEventListener(REGISTERED_COMPONENTS));
+ beanDefinitionReader.setSourceExtractor(new PassThroughSourceExtractor());
+ }
+
+ public boolean containsComponentDefinition(String name) {
+ Iterator iterator = REGISTERED_COMPONENTS.iterator();
+ while (iterator.hasNext()) {
+ ComponentDefinition cd = (ComponentDefinition) iterator.next();
+ if (cd instanceof CompositeComponentDefinition) {
+ ComponentDefinition[] innerCds = ((CompositeComponentDefinition) cd)
+ .getNestedComponents();
+ for (int i = 0; i < innerCds.length; i++) {
+ if (innerCds[i].getName().equals(name)) {
+ return true;
+ }
+ }
+ }
+ else {
+ if (cd.getName().equals(name)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public Iterator getRegisteredComponents() {
+ return REGISTERED_COMPONENTS.iterator();
+ }
+ }
+
+
+ private static class StoringReaderEventListener extends EmptyReaderEventListener {
+
+ protected Set registeredComponents = null;
+
+ public StoringReaderEventListener(Set registeredComponents) {
+ this.registeredComponents = registeredComponents;
+ this.registeredComponents.clear();
+ }
+
+ public void componentRegistered(ComponentDefinition componentDefinition) {
+ this.registeredComponents.add(componentDefinition);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/config/jmsNamespaceHandlerTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/jms/config/jmsNamespaceHandlerTests.xml
new file mode 100644
index 00000000000..be347db5d2f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/config/jmsNamespaceHandlerTests.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/connection/JmsTransactionManagerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/connection/JmsTransactionManagerTests.java
new file mode 100644
index 00000000000..24211c5fd5c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/connection/JmsTransactionManagerTests.java
@@ -0,0 +1,505 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jms.connection;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageProducer;
+import javax.jms.QueueConnection;
+import javax.jms.QueueConnectionFactory;
+import javax.jms.QueueSession;
+import javax.jms.Session;
+import javax.jms.TopicConnection;
+import javax.jms.TopicConnectionFactory;
+import javax.jms.TopicSession;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.jms.StubQueue;
+import org.springframework.jms.core.JmsTemplate;
+import org.springframework.jms.core.JmsTemplate102;
+import org.springframework.jms.core.MessageCreator;
+import org.springframework.jms.core.SessionCallback;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.UnexpectedRollbackException;
+import org.springframework.transaction.support.DefaultTransactionDefinition;
+import org.springframework.transaction.support.TransactionCallbackWithoutResult;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+import org.springframework.transaction.support.TransactionTemplate;
+
+/**
+ * @author Juergen Hoeller
+ * @since 26.07.2004
+ */
+public class JmsTransactionManagerTests extends TestCase {
+
+ public void testTransactionCommit() throws JMSException {
+ MockControl cfControl = MockControl.createControl(ConnectionFactory.class);
+ ConnectionFactory cf = (ConnectionFactory) cfControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+
+ cf.createConnection();
+ cfControl.setReturnValue(con, 1);
+ con.createSession(true, Session.AUTO_ACKNOWLEDGE);
+ conControl.setReturnValue(session, 1);
+ session.commit();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ sessionControl.replay();
+ conControl.replay();
+ cfControl.replay();
+
+ JmsTransactionManager tm = new JmsTransactionManager(cf);
+ TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition());
+ JmsTemplate jt = new JmsTemplate(cf);
+ jt.execute(new SessionCallback() {
+ public Object doInJms(Session sess) {
+ assertTrue(sess == session);
+ return null;
+ }
+ });
+ tm.commit(ts);
+
+ sessionControl.verify();
+ conControl.verify();
+ cfControl.verify();
+ }
+
+ public void testTransactionRollback() throws JMSException {
+ MockControl cfControl = MockControl.createControl(ConnectionFactory.class);
+ ConnectionFactory cf = (ConnectionFactory) cfControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+
+ cf.createConnection();
+ cfControl.setReturnValue(con, 1);
+ con.createSession(true, Session.AUTO_ACKNOWLEDGE);
+ conControl.setReturnValue(session, 1);
+ session.rollback();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ sessionControl.replay();
+ conControl.replay();
+ cfControl.replay();
+
+ JmsTransactionManager tm = new JmsTransactionManager(cf);
+ TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition());
+ JmsTemplate jt = new JmsTemplate(cf);
+ jt.execute(new SessionCallback() {
+ public Object doInJms(Session sess) {
+ assertTrue(sess == session);
+ return null;
+ }
+ });
+ tm.rollback(ts);
+
+ sessionControl.verify();
+ conControl.verify();
+ cfControl.verify();
+ }
+
+ public void testParticipatingTransactionWithCommit() throws JMSException {
+ MockControl cfControl = MockControl.createControl(ConnectionFactory.class);
+ final ConnectionFactory cf = (ConnectionFactory) cfControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+
+ cf.createConnection();
+ cfControl.setReturnValue(con, 1);
+ con.createSession(true, Session.AUTO_ACKNOWLEDGE);
+ conControl.setReturnValue(session, 1);
+ session.commit();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ sessionControl.replay();
+ conControl.replay();
+ cfControl.replay();
+
+ JmsTransactionManager tm = new JmsTransactionManager(cf);
+ TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition());
+ final JmsTemplate jt = new JmsTemplate(cf);
+ jt.execute(new SessionCallback() {
+ public Object doInJms(Session sess) {
+ assertTrue(sess == session);
+ return null;
+ }
+ });
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ jt.execute(new SessionCallback() {
+ public Object doInJms(Session sess) {
+ assertTrue(sess == session);
+ return null;
+ }
+ });
+ }
+ });
+ tm.commit(ts);
+
+ sessionControl.verify();
+ conControl.verify();
+ cfControl.verify();
+ }
+
+ public void testParticipatingTransactionWithRollbackOnly() throws JMSException {
+ MockControl cfControl = MockControl.createControl(ConnectionFactory.class);
+ final ConnectionFactory cf = (ConnectionFactory) cfControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+
+ cf.createConnection();
+ cfControl.setReturnValue(con, 1);
+ con.createSession(true, Session.AUTO_ACKNOWLEDGE);
+ conControl.setReturnValue(session, 1);
+ session.rollback();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ sessionControl.replay();
+ conControl.replay();
+ cfControl.replay();
+
+ JmsTransactionManager tm = new JmsTransactionManager(cf);
+ TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition());
+ final JmsTemplate jt = new JmsTemplate(cf);
+ jt.execute(new SessionCallback() {
+ public Object doInJms(Session sess) {
+ assertTrue(sess == session);
+ return null;
+ }
+ });
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ jt.execute(new SessionCallback() {
+ public Object doInJms(Session sess) {
+ assertTrue(sess == session);
+ return null;
+ }
+ });
+ status.setRollbackOnly();
+ }
+ });
+ try {
+ tm.commit(ts);
+ fail("Should have thrown UnexpectedRollbackException");
+ }
+ catch (UnexpectedRollbackException ex) {
+ // expected
+ }
+
+ sessionControl.verify();
+ conControl.verify();
+ cfControl.verify();
+ }
+
+ public void testSuspendedTransaction() throws JMSException {
+ MockControl cfControl = MockControl.createControl(ConnectionFactory.class);
+ final ConnectionFactory cf = (ConnectionFactory) cfControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ MockControl session2Control = MockControl.createControl(Session.class);
+ final Session session2 = (Session) session2Control.getMock();
+
+ cf.createConnection();
+ cfControl.setReturnValue(con, 2);
+ con.createSession(true, Session.AUTO_ACKNOWLEDGE);
+ conControl.setReturnValue(session, 1);
+ con.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ conControl.setReturnValue(session2, 1);
+ session.commit();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setVoidCallable(1);
+ session2.close();
+ session2Control.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(2);
+
+ sessionControl.replay();
+ conControl.replay();
+ cfControl.replay();
+
+ JmsTransactionManager tm = new JmsTransactionManager(cf);
+ TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition());
+ final JmsTemplate jt = new JmsTemplate(cf);
+ jt.execute(new SessionCallback() {
+ public Object doInJms(Session sess) {
+ assertTrue(sess == session);
+ return null;
+ }
+ });
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ jt.execute(new SessionCallback() {
+ public Object doInJms(Session sess) {
+ assertTrue(sess != session);
+ return null;
+ }
+ });
+ }
+ });
+ jt.execute(new SessionCallback() {
+ public Object doInJms(Session sess) {
+ assertTrue(sess == session);
+ return null;
+ }
+ });
+ tm.commit(ts);
+
+ sessionControl.verify();
+ conControl.verify();
+ cfControl.verify();
+ }
+
+ public void testTransactionSuspension() throws JMSException {
+ MockControl cfControl = MockControl.createControl(ConnectionFactory.class);
+ final ConnectionFactory cf = (ConnectionFactory) cfControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ MockControl session2Control = MockControl.createControl(Session.class);
+ final Session session2 = (Session) session2Control.getMock();
+
+ cf.createConnection();
+ cfControl.setReturnValue(con, 2);
+ con.createSession(true, Session.AUTO_ACKNOWLEDGE);
+ conControl.setReturnValue(session, 1);
+ con.createSession(true, Session.AUTO_ACKNOWLEDGE);
+ conControl.setReturnValue(session2, 1);
+ session.commit();
+ sessionControl.setVoidCallable(1);
+ session2.commit();
+ session2Control.setVoidCallable(1);
+ session.close();
+ sessionControl.setVoidCallable(1);
+ session2.close();
+ session2Control.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(2);
+
+ sessionControl.replay();
+ conControl.replay();
+ cfControl.replay();
+
+ JmsTransactionManager tm = new JmsTransactionManager(cf);
+ TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition());
+ final JmsTemplate jt = new JmsTemplate(cf);
+ jt.execute(new SessionCallback() {
+ public Object doInJms(Session sess) {
+ assertTrue(sess == session);
+ return null;
+ }
+ });
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ jt.execute(new SessionCallback() {
+ public Object doInJms(Session sess) {
+ assertTrue(sess != session);
+ return null;
+ }
+ });
+ }
+ });
+ jt.execute(new SessionCallback() {
+ public Object doInJms(Session sess) {
+ assertTrue(sess == session);
+ return null;
+ }
+ });
+ tm.commit(ts);
+
+ sessionControl.verify();
+ conControl.verify();
+ cfControl.verify();
+ }
+
+ public void testTransactionCommitWithMessageProducer() throws JMSException {
+ Destination dest = new StubQueue();
+
+ MockControl cfControl = MockControl.createControl(ConnectionFactory.class);
+ ConnectionFactory cf = (ConnectionFactory) cfControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ MockControl producerControl = MockControl.createControl(MessageProducer.class);
+ MessageProducer producer = (MessageProducer) producerControl.getMock();
+ MockControl messageControl = MockControl.createControl(Message.class);
+ final Message message = (Message) messageControl.getMock();
+
+ cf.createConnection();
+ cfControl.setReturnValue(con, 1);
+ con.createSession(true, Session.AUTO_ACKNOWLEDGE);
+ conControl.setReturnValue(session, 1);
+ session.createProducer(dest);
+ sessionControl.setReturnValue(producer, 1);
+ producer.send(message);
+ producerControl.setVoidCallable(1);
+ session.getTransacted();
+ sessionControl.setReturnValue(true, 1);
+ session.commit();
+ sessionControl.setVoidCallable(1);
+ producer.close();
+ producerControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ producerControl.replay();
+ sessionControl.replay();
+ conControl.replay();
+ cfControl.replay();
+
+ JmsTransactionManager tm = new JmsTransactionManager(cf);
+ TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition());
+ JmsTemplate jt = new JmsTemplate(cf);
+ jt.send(dest, new MessageCreator() {
+ public Message createMessage(Session session) throws JMSException {
+ return message;
+ }
+ });
+ tm.commit(ts);
+
+ producerControl.verify();
+ sessionControl.verify();
+ conControl.verify();
+ cfControl.verify();
+ }
+
+ public void testTransactionCommit102WithQueue() throws JMSException {
+ MockControl cfControl = MockControl.createControl(QueueConnectionFactory.class);
+ QueueConnectionFactory cf = (QueueConnectionFactory) cfControl.getMock();
+ MockControl conControl = MockControl.createControl(QueueConnection.class);
+ QueueConnection con = (QueueConnection) conControl.getMock();
+ MockControl sessionControl = MockControl.createControl(QueueSession.class);
+ final QueueSession session = (QueueSession) sessionControl.getMock();
+
+ cf.createQueueConnection();
+ cfControl.setReturnValue(con, 1);
+ con.createQueueSession(true, Session.AUTO_ACKNOWLEDGE);
+ conControl.setReturnValue(session, 1);
+ session.commit();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ sessionControl.replay();
+ conControl.replay();
+ cfControl.replay();
+
+ JmsTransactionManager tm = new JmsTransactionManager102(cf, false);
+ TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition());
+ JmsTemplate jt = new JmsTemplate102(cf, false);
+ jt.execute(new SessionCallback() {
+ public Object doInJms(Session sess) {
+ assertTrue(sess == session);
+ return null;
+ }
+ });
+ tm.commit(ts);
+
+ sessionControl.verify();
+ conControl.verify();
+ cfControl.verify();
+ }
+
+ public void testTransactionCommit102WithTopic() throws JMSException {
+ MockControl cfControl = MockControl.createControl(TopicConnectionFactory.class);
+ TopicConnectionFactory cf = (TopicConnectionFactory) cfControl.getMock();
+ MockControl conControl = MockControl.createControl(TopicConnection.class);
+ TopicConnection con = (TopicConnection) conControl.getMock();
+ MockControl sessionControl = MockControl.createControl(TopicSession.class);
+ final TopicSession session = (TopicSession) sessionControl.getMock();
+
+ cf.createTopicConnection();
+ cfControl.setReturnValue(con, 1);
+ con.createTopicSession(true, Session.AUTO_ACKNOWLEDGE);
+ conControl.setReturnValue(session, 1);
+ session.commit();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ sessionControl.replay();
+ conControl.replay();
+ cfControl.replay();
+
+ JmsTransactionManager tm = new JmsTransactionManager102(cf, true);
+ TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition());
+ JmsTemplate jt = new JmsTemplate102(cf, true);
+ jt.execute(new SessionCallback() {
+ public Object doInJms(Session sess) {
+ assertTrue(sess == session);
+ return null;
+ }
+ });
+ tm.commit(ts);
+
+ sessionControl.verify();
+ conControl.verify();
+ cfControl.verify();
+ }
+
+ protected void tearDown() {
+ assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/connection/SingleConnectionFactoryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/connection/SingleConnectionFactoryTests.java
new file mode 100644
index 00000000000..cf0c87ddf18
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/connection/SingleConnectionFactoryTests.java
@@ -0,0 +1,651 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jms.connection;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.ExceptionListener;
+import javax.jms.JMSException;
+import javax.jms.QueueConnection;
+import javax.jms.QueueConnectionFactory;
+import javax.jms.QueueSession;
+import javax.jms.Session;
+import javax.jms.TopicConnection;
+import javax.jms.TopicConnectionFactory;
+import javax.jms.TopicSession;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+/**
+ * @author Juergen Hoeller
+ * @since 26.07.2004
+ */
+public class SingleConnectionFactoryTests extends TestCase {
+
+ public void testWithConnection() throws JMSException {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+
+ con.start();
+ conControl.setVoidCallable(2);
+ con.stop();
+ conControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ conControl.replay();
+
+ SingleConnectionFactory scf = new SingleConnectionFactory(con);
+ Connection con1 = scf.createConnection();
+ con1.start();
+ con1.stop(); // should be ignored
+ con1.close(); // should be ignored
+ Connection con2 = scf.createConnection();
+ con2.start();
+ con2.stop(); // should be ignored
+ con2.close(); // should be ignored
+ scf.destroy(); // should trigger actual close
+
+ conControl.verify();
+ }
+
+ public void testWithQueueConnection() throws JMSException {
+ MockControl conControl = MockControl.createControl(QueueConnection.class);
+ Connection con = (QueueConnection) conControl.getMock();
+
+ con.start();
+ conControl.setVoidCallable(2);
+ con.stop();
+ conControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ conControl.replay();
+
+ SingleConnectionFactory scf = new SingleConnectionFactory(con);
+ QueueConnection con1 = scf.createQueueConnection();
+ con1.start();
+ con1.stop(); // should be ignored
+ con1.close(); // should be ignored
+ QueueConnection con2 = scf.createQueueConnection();
+ con2.start();
+ con2.stop(); // should be ignored
+ con2.close(); // should be ignored
+ scf.destroy(); // should trigger actual close
+
+ conControl.verify();
+ }
+
+ public void testWithTopicConnection() throws JMSException {
+ MockControl conControl = MockControl.createControl(TopicConnection.class);
+ Connection con = (TopicConnection) conControl.getMock();
+
+ con.start();
+ conControl.setVoidCallable(2);
+ con.stop();
+ conControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ conControl.replay();
+
+ SingleConnectionFactory scf = new SingleConnectionFactory(con);
+ TopicConnection con1 = scf.createTopicConnection();
+ con1.start();
+ con1.stop(); // should be ignored
+ con1.close(); // should be ignored
+ TopicConnection con2 = scf.createTopicConnection();
+ con2.start();
+ con2.stop(); // should be ignored
+ con2.close(); // should be ignored
+ scf.destroy(); // should trigger actual close
+
+ conControl.verify();
+ }
+
+ public void testWithConnectionFactory() throws JMSException {
+ MockControl cfControl = MockControl.createControl(ConnectionFactory.class);
+ ConnectionFactory cf = (ConnectionFactory) cfControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+
+ cf.createConnection();
+ cfControl.setReturnValue(con, 1);
+ con.start();
+ conControl.setVoidCallable(2);
+ con.stop();
+ conControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ cfControl.replay();
+ conControl.replay();
+
+ SingleConnectionFactory scf = new SingleConnectionFactory(cf);
+ Connection con1 = scf.createConnection();
+ con1.start();
+ con1.close(); // should be ignored
+ Connection con2 = scf.createConnection();
+ con2.start();
+ con2.close(); // should be ignored
+ scf.destroy(); // should trigger actual close
+
+ cfControl.verify();
+ conControl.verify();
+ }
+
+ public void testWithQueueConnectionFactoryAndJms11Usage() throws JMSException {
+ MockControl cfControl = MockControl.createControl(QueueConnectionFactory.class);
+ QueueConnectionFactory cf = (QueueConnectionFactory) cfControl.getMock();
+ MockControl conControl = MockControl.createControl(QueueConnection.class);
+ QueueConnection con = (QueueConnection) conControl.getMock();
+
+ cf.createConnection();
+ cfControl.setReturnValue(con, 1);
+ con.start();
+ conControl.setVoidCallable(2);
+ con.stop();
+ conControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ cfControl.replay();
+ conControl.replay();
+
+ SingleConnectionFactory scf = new SingleConnectionFactory(cf);
+ Connection con1 = scf.createConnection();
+ con1.start();
+ con1.close(); // should be ignored
+ Connection con2 = scf.createConnection();
+ con2.start();
+ con2.close(); // should be ignored
+ scf.destroy(); // should trigger actual close
+
+ cfControl.verify();
+ conControl.verify();
+ }
+
+ public void testWithQueueConnectionFactoryAndJms102Usage() throws JMSException {
+ MockControl cfControl = MockControl.createControl(QueueConnectionFactory.class);
+ QueueConnectionFactory cf = (QueueConnectionFactory) cfControl.getMock();
+ MockControl conControl = MockControl.createControl(QueueConnection.class);
+ QueueConnection con = (QueueConnection) conControl.getMock();
+
+ cf.createQueueConnection();
+ cfControl.setReturnValue(con, 1);
+ con.start();
+ conControl.setVoidCallable(2);
+ con.stop();
+ conControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ cfControl.replay();
+ conControl.replay();
+
+ SingleConnectionFactory scf = new SingleConnectionFactory(cf);
+ Connection con1 = scf.createQueueConnection();
+ con1.start();
+ con1.close(); // should be ignored
+ Connection con2 = scf.createQueueConnection();
+ con2.start();
+ con2.close(); // should be ignored
+ scf.destroy(); // should trigger actual close
+
+ cfControl.verify();
+ conControl.verify();
+ }
+
+ public void testWithTopicConnectionFactoryAndJms11Usage() throws JMSException {
+ MockControl cfControl = MockControl.createControl(TopicConnectionFactory.class);
+ TopicConnectionFactory cf = (TopicConnectionFactory) cfControl.getMock();
+ MockControl conControl = MockControl.createControl(TopicConnection.class);
+ TopicConnection con = (TopicConnection) conControl.getMock();
+
+ cf.createConnection();
+ cfControl.setReturnValue(con, 1);
+ con.start();
+ conControl.setVoidCallable(2);
+ con.stop();
+ conControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ cfControl.replay();
+ conControl.replay();
+
+ SingleConnectionFactory scf = new SingleConnectionFactory(cf);
+ Connection con1 = scf.createConnection();
+ con1.start();
+ con1.close(); // should be ignored
+ Connection con2 = scf.createConnection();
+ con2.start();
+ con2.close(); // should be ignored
+ scf.destroy(); // should trigger actual close
+
+ cfControl.verify();
+ conControl.verify();
+ }
+
+ public void testWithTopicConnectionFactoryAndJms102Usage() throws JMSException {
+ MockControl cfControl = MockControl.createControl(TopicConnectionFactory.class);
+ TopicConnectionFactory cf = (TopicConnectionFactory) cfControl.getMock();
+ MockControl conControl = MockControl.createControl(TopicConnection.class);
+ TopicConnection con = (TopicConnection) conControl.getMock();
+
+ cf.createTopicConnection();
+ cfControl.setReturnValue(con, 1);
+ con.start();
+ conControl.setVoidCallable(2);
+ con.stop();
+ conControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ cfControl.replay();
+ conControl.replay();
+
+ SingleConnectionFactory scf = new SingleConnectionFactory(cf);
+ Connection con1 = scf.createTopicConnection();
+ con1.start();
+ con1.close(); // should be ignored
+ Connection con2 = scf.createTopicConnection();
+ con2.start();
+ con2.close(); // should be ignored
+ scf.destroy(); // should trigger actual close
+
+ cfControl.verify();
+ conControl.verify();
+ }
+
+ public void testWithConnectionFactoryAndClientId() throws JMSException {
+ MockControl cfControl = MockControl.createControl(ConnectionFactory.class);
+ ConnectionFactory cf = (ConnectionFactory) cfControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+
+ cf.createConnection();
+ cfControl.setReturnValue(con, 1);
+ con.setClientID("myId");
+ conControl.setVoidCallable(1);
+ con.start();
+ conControl.setVoidCallable(2);
+ con.stop();
+ conControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ cfControl.replay();
+ conControl.replay();
+
+ SingleConnectionFactory scf = new SingleConnectionFactory(cf);
+ scf.setClientId("myId");
+ Connection con1 = scf.createConnection();
+ con1.start();
+ con1.close(); // should be ignored
+ Connection con2 = scf.createConnection();
+ con2.start();
+ con2.close(); // should be ignored
+ scf.destroy(); // should trigger actual close
+
+ cfControl.verify();
+ conControl.verify();
+ }
+
+ public void testWithConnectionFactoryAndExceptionListener() throws JMSException {
+ MockControl cfControl = MockControl.createControl(ConnectionFactory.class);
+ ConnectionFactory cf = (ConnectionFactory) cfControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+
+ ExceptionListener listener = new ChainedExceptionListener();
+ cf.createConnection();
+ cfControl.setReturnValue(con, 1);
+ con.setExceptionListener(listener);
+ conControl.setVoidCallable(1);
+ con.getExceptionListener();
+ conControl.setReturnValue(listener, 1);
+ con.start();
+ conControl.setVoidCallable(2);
+ con.stop();
+ conControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ cfControl.replay();
+ conControl.replay();
+
+ SingleConnectionFactory scf = new SingleConnectionFactory(cf);
+ scf.setExceptionListener(listener);
+ Connection con1 = scf.createConnection();
+ assertEquals(listener, con1.getExceptionListener());
+ con1.start();
+ con1.stop(); // should be ignored
+ con1.close(); // should be ignored
+ Connection con2 = scf.createConnection();
+ con2.start();
+ con2.stop(); // should be ignored
+ con2.close(); // should be ignored
+ scf.destroy(); // should trigger actual close
+
+ cfControl.verify();
+ conControl.verify();
+ }
+
+ public void testWithConnectionFactoryAndReconnectOnException() throws JMSException {
+ MockControl cfControl = MockControl.createControl(ConnectionFactory.class);
+ ConnectionFactory cf = (ConnectionFactory) cfControl.getMock();
+ TestConnection con = new TestConnection();
+
+ cf.createConnection();
+ cfControl.setReturnValue(con, 2);
+ cfControl.replay();
+
+ SingleConnectionFactory scf = new SingleConnectionFactory(cf);
+ scf.setReconnectOnException(true);
+ Connection con1 = scf.createConnection();
+ assertNull(con1.getExceptionListener());
+ con1.start();
+ con.getExceptionListener().onException(new JMSException(""));
+ Connection con2 = scf.createConnection();
+ con2.start();
+ scf.destroy(); // should trigger actual close
+
+ cfControl.verify();
+ assertEquals(2, con.getStartCount());
+ assertEquals(2, con.getCloseCount());
+ }
+
+ public void testWithConnectionFactoryAndExceptionListenerAndReconnectOnException() throws JMSException {
+ MockControl cfControl = MockControl.createControl(ConnectionFactory.class);
+ ConnectionFactory cf = (ConnectionFactory) cfControl.getMock();
+ TestConnection con = new TestConnection();
+
+ TestExceptionListener listener = new TestExceptionListener();
+ cf.createConnection();
+ cfControl.setReturnValue(con, 2);
+ cfControl.replay();
+
+ SingleConnectionFactory scf = new SingleConnectionFactory(cf);
+ scf.setExceptionListener(listener);
+ scf.setReconnectOnException(true);
+ Connection con1 = scf.createConnection();
+ assertSame(listener, con1.getExceptionListener());
+ con1.start();
+ con.getExceptionListener().onException(new JMSException(""));
+ Connection con2 = scf.createConnection();
+ con2.start();
+ scf.destroy(); // should trigger actual close
+
+ cfControl.verify();
+ assertEquals(2, con.getStartCount());
+ assertEquals(2, con.getCloseCount());
+ assertEquals(1, listener.getCount());
+ }
+
+ public void testConnectionFactory102WithQueue() throws JMSException {
+ MockControl cfControl = MockControl.createControl(QueueConnectionFactory.class);
+ QueueConnectionFactory cf = (QueueConnectionFactory) cfControl.getMock();
+ MockControl conControl = MockControl.createControl(QueueConnection.class);
+ QueueConnection con = (QueueConnection) conControl.getMock();
+
+ cf.createQueueConnection();
+ cfControl.setReturnValue(con, 1);
+ con.start();
+ conControl.setVoidCallable(2);
+ con.stop();
+ conControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ cfControl.replay();
+ conControl.replay();
+
+ SingleConnectionFactory scf = new SingleConnectionFactory102(cf, false);
+ QueueConnection con1 = scf.createQueueConnection();
+ con1.start();
+ con1.close(); // should be ignored
+ QueueConnection con2 = scf.createQueueConnection();
+ con2.start();
+ con2.close(); // should be ignored
+ scf.destroy(); // should trigger actual close
+
+ cfControl.verify();
+ conControl.verify();
+ }
+
+ public void testConnectionFactory102WithTopic() throws JMSException {
+ MockControl cfControl = MockControl.createControl(TopicConnectionFactory.class);
+ TopicConnectionFactory cf = (TopicConnectionFactory) cfControl.getMock();
+ MockControl conControl = MockControl.createControl(TopicConnection.class);
+ TopicConnection con = (TopicConnection) conControl.getMock();
+
+ cf.createTopicConnection();
+ cfControl.setReturnValue(con, 1);
+ con.start();
+ conControl.setVoidCallable(2);
+ con.stop();
+ conControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ cfControl.replay();
+ conControl.replay();
+
+ SingleConnectionFactory scf = new SingleConnectionFactory102(cf, true);
+ TopicConnection con1 = scf.createTopicConnection();
+ con1.start();
+ con1.close(); // should be ignored
+ TopicConnection con2 = scf.createTopicConnection();
+ con2.start();
+ con2.close(); // should be ignored
+ scf.destroy(); // should trigger actual close
+
+ cfControl.verify();
+ conControl.verify();
+ }
+
+ public void testCachingConnectionFactory() throws JMSException {
+ MockControl cfControl = MockControl.createControl(ConnectionFactory.class);
+ ConnectionFactory cf = (ConnectionFactory) cfControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl txSessionControl = MockControl.createControl(Session.class);
+ Session txSession = (Session) txSessionControl.getMock();
+ MockControl nonTxSessionControl = MockControl.createControl(Session.class);
+ Session nonTxSession = (Session) nonTxSessionControl.getMock();
+
+ cf.createConnection();
+ cfControl.setReturnValue(con, 1);
+ con.createSession(true, Session.AUTO_ACKNOWLEDGE);
+ conControl.setReturnValue(txSession, 1);
+ txSession.getTransacted();
+ txSessionControl.setReturnValue(true, 2);
+ txSession.rollback();
+ txSessionControl.setVoidCallable(1);
+ txSession.commit();
+ txSessionControl.setVoidCallable(1);
+ txSession.close();
+ txSessionControl.setVoidCallable(1);
+ con.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+ conControl.setReturnValue(nonTxSession, 1);
+ nonTxSession.close();
+ nonTxSessionControl.setVoidCallable(1);
+ con.start();
+ conControl.setVoidCallable(2);
+ con.stop();
+ conControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ cfControl.replay();
+ conControl.replay();
+ txSessionControl.replay();
+ nonTxSessionControl.replay();
+
+ CachingConnectionFactory scf = new CachingConnectionFactory(cf);
+ scf.setReconnectOnException(false);
+ Connection con1 = scf.createConnection();
+ Session session1 = con1.createSession(true, Session.AUTO_ACKNOWLEDGE);
+ session1.getTransacted();
+ session1.close(); // should lead to rollback
+ session1 = con1.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+ session1.close(); // should be ignored
+ con1.start();
+ con1.close(); // should be ignored
+ Connection con2 = scf.createConnection();
+ Session session2 = con2.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+ session2.close(); // should be ignored
+ session2 = con2.createSession(true, Session.AUTO_ACKNOWLEDGE);
+ session2.commit();
+ session2.close(); // should be ignored
+ con2.start();
+ con2.close(); // should be ignored
+ scf.destroy(); // should trigger actual close
+
+ cfControl.verify();
+ conControl.verify();
+ txSessionControl.verify();
+ nonTxSessionControl.verify();
+ }
+
+ public void testCachingConnectionFactoryWithQueueConnectionFactoryAndJms102Usage() throws JMSException {
+ MockControl cfControl = MockControl.createControl(QueueConnectionFactory.class);
+ QueueConnectionFactory cf = (QueueConnectionFactory) cfControl.getMock();
+ MockControl conControl = MockControl.createControl(QueueConnection.class);
+ QueueConnection con = (QueueConnection) conControl.getMock();
+ MockControl txSessionControl = MockControl.createControl(QueueSession.class);
+ QueueSession txSession = (QueueSession) txSessionControl.getMock();
+ MockControl nonTxSessionControl = MockControl.createControl(QueueSession.class);
+ QueueSession nonTxSession = (QueueSession) nonTxSessionControl.getMock();
+
+ cf.createQueueConnection();
+ cfControl.setReturnValue(con, 1);
+ con.createQueueSession(true, Session.AUTO_ACKNOWLEDGE);
+ conControl.setReturnValue(txSession, 1);
+ txSession.getTransacted();
+ txSessionControl.setReturnValue(true, 2);
+ txSession.rollback();
+ txSessionControl.setVoidCallable(2);
+ txSession.close();
+ txSessionControl.setVoidCallable(1);
+ con.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE);
+ conControl.setReturnValue(nonTxSession, 1);
+ nonTxSession.close();
+ nonTxSessionControl.setVoidCallable(1);
+ con.start();
+ conControl.setVoidCallable(2);
+ con.stop();
+ conControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ cfControl.replay();
+ conControl.replay();
+ txSessionControl.replay();
+ nonTxSessionControl.replay();
+
+ CachingConnectionFactory scf = new CachingConnectionFactory(cf);
+ scf.setReconnectOnException(false);
+ Connection con1 = scf.createQueueConnection();
+ Session session1 = con1.createSession(true, Session.AUTO_ACKNOWLEDGE);
+ session1.rollback();
+ session1.close(); // should be ignored
+ session1 = con1.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+ session1.close(); // should be ignored
+ con1.start();
+ con1.close(); // should be ignored
+ QueueConnection con2 = scf.createQueueConnection();
+ Session session2 = con2.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE);
+ session2.close(); // should be ignored
+ session2 = con2.createSession(true, Session.AUTO_ACKNOWLEDGE);
+ session2.getTransacted();
+ session2.close(); // should lead to rollback
+ con2.start();
+ con2.close(); // should be ignored
+ scf.destroy(); // should trigger actual close
+
+ cfControl.verify();
+ conControl.verify();
+ txSessionControl.verify();
+ nonTxSessionControl.verify();
+ }
+
+ public void testCachingConnectionFactoryWithTopicConnectionFactoryAndJms102Usage() throws JMSException {
+ MockControl cfControl = MockControl.createControl(TopicConnectionFactory.class);
+ TopicConnectionFactory cf = (TopicConnectionFactory) cfControl.getMock();
+ MockControl conControl = MockControl.createControl(TopicConnection.class);
+ TopicConnection con = (TopicConnection) conControl.getMock();
+ MockControl txSessionControl = MockControl.createControl(TopicSession.class);
+ TopicSession txSession = (TopicSession) txSessionControl.getMock();
+ MockControl nonTxSessionControl = MockControl.createControl(TopicSession.class);
+ TopicSession nonTxSession = (TopicSession) nonTxSessionControl.getMock();
+
+ cf.createTopicConnection();
+ cfControl.setReturnValue(con, 1);
+ con.createTopicSession(true, Session.AUTO_ACKNOWLEDGE);
+ conControl.setReturnValue(txSession, 1);
+ txSession.getTransacted();
+ txSessionControl.setReturnValue(true, 4);
+ txSession.rollback();
+ txSessionControl.setVoidCallable(2);
+ txSession.close();
+ txSessionControl.setVoidCallable(1);
+ con.createTopicSession(false, Session.CLIENT_ACKNOWLEDGE);
+ conControl.setReturnValue(nonTxSession, 1);
+ nonTxSession.close();
+ nonTxSessionControl.setVoidCallable(1);
+ con.start();
+ conControl.setVoidCallable(2);
+ con.stop();
+ conControl.setVoidCallable(1);
+ con.close();
+ conControl.setVoidCallable(1);
+
+ cfControl.replay();
+ conControl.replay();
+ txSessionControl.replay();
+ nonTxSessionControl.replay();
+
+ CachingConnectionFactory scf = new CachingConnectionFactory(cf);
+ scf.setReconnectOnException(false);
+ Connection con1 = scf.createTopicConnection();
+ Session session1 = con1.createSession(true, Session.AUTO_ACKNOWLEDGE);
+ session1.getTransacted();
+ session1.close(); // should lead to rollback
+ session1 = con1.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+ session1.close(); // should be ignored
+ con1.start();
+ con1.close(); // should be ignored
+ TopicConnection con2 = scf.createTopicConnection();
+ Session session2 = con2.createTopicSession(false, Session.CLIENT_ACKNOWLEDGE);
+ session2.close(); // should be ignored
+ session2 = con2.createSession(true, Session.AUTO_ACKNOWLEDGE);
+ session2.getTransacted();
+ session2.close(); // should be ignored
+ con2.start();
+ con2.close(); // should be ignored
+ scf.destroy(); // should trigger actual close
+
+ cfControl.verify();
+ conControl.verify();
+ txSessionControl.verify();
+ nonTxSessionControl.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/connection/TestConnection.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/connection/TestConnection.java
new file mode 100644
index 00000000000..e37dd2e5dcd
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/connection/TestConnection.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jms.connection;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionConsumer;
+import javax.jms.ConnectionMetaData;
+import javax.jms.Destination;
+import javax.jms.ExceptionListener;
+import javax.jms.JMSException;
+import javax.jms.ServerSessionPool;
+import javax.jms.Session;
+import javax.jms.Topic;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class TestConnection implements Connection {
+
+ private ExceptionListener exceptionListener;
+
+ private int startCount;
+
+ private int closeCount;
+
+
+ public Session createSession(boolean b, int i) throws JMSException {
+ return null;
+ }
+
+ public String getClientID() throws JMSException {
+ return null;
+ }
+
+ public void setClientID(String paramName) throws JMSException {
+ }
+
+ public ConnectionMetaData getMetaData() throws JMSException {
+ return null;
+ }
+
+ public ExceptionListener getExceptionListener() throws JMSException {
+ return exceptionListener;
+ }
+
+ public void setExceptionListener(ExceptionListener exceptionListener) throws JMSException {
+ this.exceptionListener = exceptionListener;
+ }
+
+ public void start() throws JMSException {
+ this.startCount++;
+ }
+
+ public void stop() throws JMSException {
+ }
+
+ public void close() throws JMSException {
+ this.closeCount++;
+ }
+
+ public ConnectionConsumer createConnectionConsumer(Destination destination, String paramName, ServerSessionPool serverSessionPool, int i) throws JMSException {
+ return null;
+ }
+
+ public ConnectionConsumer createDurableConnectionConsumer(Topic topic, String paramName, String paramName1, ServerSessionPool serverSessionPool, int i) throws JMSException {
+ return null;
+ }
+
+
+ public int getStartCount() {
+ return startCount;
+ }
+
+ public int getCloseCount() {
+ return closeCount;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/connection/TestExceptionListener.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/connection/TestExceptionListener.java
new file mode 100644
index 00000000000..e3f489f8a84
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/connection/TestExceptionListener.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jms.connection;
+
+import javax.jms.ExceptionListener;
+import javax.jms.JMSException;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class TestExceptionListener implements ExceptionListener {
+
+ private int count = 0;
+
+ public void onException(JMSException ex) {
+ this.count++;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/core/JmsTemplate102JtaTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/core/JmsTemplate102JtaTests.java
new file mode 100644
index 00000000000..8918069e1bf
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/core/JmsTemplate102JtaTests.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jms.core;
+
+/**
+ * @author Juergen Hoeller
+ * @since 06.01.2005
+ */
+public class JmsTemplate102JtaTests extends JmsTemplate102Tests {
+
+ protected boolean useTransactedSession() {
+ return true;
+ }
+
+ protected boolean useTransactedTemplate() {
+ return false;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/core/JmsTemplate102Tests.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/core/JmsTemplate102Tests.java
new file mode 100644
index 00000000000..c9890fd55b4
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/core/JmsTemplate102Tests.java
@@ -0,0 +1,1166 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jms.core;
+
+import javax.jms.DeliveryMode;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.QueueConnection;
+import javax.jms.QueueConnectionFactory;
+import javax.jms.QueueReceiver;
+import javax.jms.QueueSender;
+import javax.jms.QueueSession;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+import javax.jms.Topic;
+import javax.jms.TopicConnection;
+import javax.jms.TopicConnectionFactory;
+import javax.jms.TopicPublisher;
+import javax.jms.TopicSession;
+import javax.jms.TopicSubscriber;
+import javax.naming.Context;
+import javax.naming.NamingException;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.jms.InvalidClientIDException;
+import org.springframework.jms.InvalidDestinationException;
+import org.springframework.jms.InvalidSelectorException;
+import org.springframework.jms.JmsException;
+import org.springframework.jms.JmsSecurityException;
+import org.springframework.jms.MessageEOFException;
+import org.springframework.jms.MessageFormatException;
+import org.springframework.jms.MessageNotReadableException;
+import org.springframework.jms.MessageNotWriteableException;
+import org.springframework.jms.ResourceAllocationException;
+import org.springframework.jms.TransactionInProgressException;
+import org.springframework.jms.TransactionRolledBackException;
+import org.springframework.jms.UncategorizedJmsException;
+import org.springframework.jms.support.converter.SimpleMessageConverter;
+import org.springframework.jms.support.destination.JndiDestinationResolver;
+import org.springframework.jndi.JndiTemplate;
+
+/**
+ * Unit tests for the JmsTemplate implemented using JMS 1.0.2.
+ *
+ * @author Andre Biryukov
+ * @author Mark Pollack
+ */
+public class JmsTemplate102Tests extends TestCase {
+
+ private Context mockJndiContext;
+ private MockControl mockJndiControl;
+
+ private MockControl queueConnectionFactoryControl;
+ private QueueConnectionFactory mockQueueConnectionFactory;
+
+ private MockControl queueConnectionControl;
+ private QueueConnection mockQueueConnection;
+
+ private MockControl queueSessionControl;
+ private QueueSession mockQueueSession;
+
+ private MockControl queueControl;
+ private Queue mockQueue;
+
+ private MockControl topicConnectionFactoryControl;
+ private TopicConnectionFactory mockTopicConnectionFactory;
+
+ private MockControl topicConnectionControl;
+ private TopicConnection mockTopicConnection;
+
+ private MockControl topicSessionControl;
+ private TopicSession mockTopicSession;
+
+ private MockControl topicControl;
+ private Topic mockTopic;
+
+ private int deliveryMode = DeliveryMode.PERSISTENT;
+ private int priority = 9;
+ private int timeToLive = 10000;
+
+
+ /**
+ * Create the mock objects for testing.
+ */
+ protected void setUp() throws Exception {
+ mockJndiControl = MockControl.createControl(Context.class);
+ mockJndiContext = (Context) this.mockJndiControl.getMock();
+
+ createMockForQueues();
+ createMockForTopics();
+
+ mockJndiContext.close();
+ mockJndiControl.replay();
+ }
+
+ private void createMockForTopics() throws JMSException, NamingException {
+ topicConnectionFactoryControl = MockControl.createControl(TopicConnectionFactory.class);
+ mockTopicConnectionFactory = (TopicConnectionFactory) topicConnectionFactoryControl.getMock();
+
+ topicConnectionControl = MockControl.createControl(TopicConnection.class);
+ mockTopicConnection = (TopicConnection) topicConnectionControl.getMock();
+
+ topicControl = MockControl.createControl(Topic.class);
+ mockTopic = (Topic) topicControl.getMock();
+
+ topicSessionControl = MockControl.createControl(TopicSession.class);
+ mockTopicSession = (TopicSession) topicSessionControl.getMock();
+
+ mockTopicConnectionFactory.createTopicConnection();
+ topicConnectionFactoryControl.setReturnValue(mockTopicConnection);
+ topicConnectionFactoryControl.replay();
+
+ mockTopicConnection.createTopicSession(useTransactedTemplate(), Session.AUTO_ACKNOWLEDGE);
+ topicConnectionControl.setReturnValue(mockTopicSession);
+ mockTopicSession.getTransacted();
+ topicSessionControl.setReturnValue(useTransactedSession());
+
+ mockJndiContext.lookup("testTopic");
+ mockJndiControl.setReturnValue(mockTopic);
+ }
+
+ private void createMockForQueues() throws JMSException, NamingException {
+ queueConnectionFactoryControl = MockControl.createControl(QueueConnectionFactory.class);
+ mockQueueConnectionFactory = (QueueConnectionFactory) queueConnectionFactoryControl.getMock();
+
+ queueConnectionControl = MockControl.createControl(QueueConnection.class);
+ mockQueueConnection = (QueueConnection) queueConnectionControl.getMock();
+
+ queueControl = MockControl.createControl(Queue.class);
+ mockQueue = (Queue) queueControl.getMock();
+
+ queueSessionControl = MockControl.createControl(QueueSession.class);
+ mockQueueSession = (QueueSession) queueSessionControl.getMock();
+
+ mockQueueConnectionFactory.createQueueConnection();
+ queueConnectionFactoryControl.setReturnValue(mockQueueConnection);
+ queueConnectionFactoryControl.replay();
+
+ mockQueueConnection.createQueueSession(useTransactedTemplate(), Session.AUTO_ACKNOWLEDGE);
+ queueConnectionControl.setReturnValue(mockQueueSession);
+ mockQueueSession.getTransacted();
+ queueSessionControl.setReturnValue(useTransactedSession());
+
+ mockJndiContext.lookup("testQueue");
+ mockJndiControl.setReturnValue(mockQueue);
+ }
+
+ private JmsTemplate102 createTemplate() {
+ JmsTemplate102 template = new JmsTemplate102();
+ JndiDestinationResolver destMan = new JndiDestinationResolver();
+ destMan.setJndiTemplate(new JndiTemplate() {
+ protected Context createInitialContext() {
+ return mockJndiContext;
+ }
+ });
+ template.setDestinationResolver(destMan);
+ template.setSessionTransacted(useTransactedTemplate());
+ return template;
+ }
+
+ protected boolean useTransactedSession() {
+ return false;
+ }
+
+ protected boolean useTransactedTemplate() {
+ return false;
+ }
+
+
+ public void testTopicSessionCallback() throws Exception {
+ JmsTemplate102 template = createTemplate();
+ template.setPubSubDomain(true);
+ template.setConnectionFactory(mockTopicConnectionFactory);
+ template.afterPropertiesSet();
+
+ mockTopicSession.close();
+ topicSessionControl.setVoidCallable(1);
+
+ mockTopicConnection.close();
+ topicConnectionControl.setVoidCallable(1);
+
+ topicSessionControl.replay();
+ topicConnectionControl.replay();
+
+ template.execute(new SessionCallback() {
+ public Object doInJms(Session session) throws JMSException {
+ boolean b = session.getTransacted();
+ return null;
+ }
+ });
+
+ topicConnectionFactoryControl.verify();
+ topicConnectionControl.verify();
+ topicSessionControl.verify();
+ }
+
+ /**
+ * Test the execute(ProducerCallback) using a topic.
+ */
+ public void testTopicProducerCallback() throws Exception {
+ JmsTemplate102 template = createTemplate();
+ template.setPubSubDomain(true);
+ template.setConnectionFactory(mockTopicConnectionFactory);
+ template.afterPropertiesSet();
+
+ MockControl topicPublisherControl = MockControl.createControl(TopicPublisher.class);
+ TopicPublisher mockTopicPublisher = (TopicPublisher) topicPublisherControl.getMock();
+
+ mockTopicSession.createPublisher(null);
+ topicSessionControl.setReturnValue(mockTopicPublisher);
+
+ mockTopicPublisher.getPriority();
+ topicPublisherControl.setReturnValue(4);
+
+ mockTopicPublisher.close();
+ topicPublisherControl.setVoidCallable(1);
+ mockTopicSession.close();
+ topicSessionControl.setVoidCallable(1);
+ mockTopicConnection.close();
+ topicConnectionControl.setVoidCallable(1);
+
+ topicPublisherControl.replay();
+ topicSessionControl.replay();
+ topicConnectionControl.replay();
+
+ template.execute(new ProducerCallback() {
+ public Object doInJms(Session session, MessageProducer producer) throws JMSException {
+ boolean b = session.getTransacted();
+ int i = producer.getPriority();
+ return null;
+ }
+ });
+
+ topicConnectionFactoryControl.verify();
+ topicConnectionControl.verify();
+ topicSessionControl.verify();
+ }
+
+ /**
+ * Test the execute(ProducerCallback) using a topic.
+ */
+ public void testTopicProducerCallbackWithIdAndTimestampDisabled() throws Exception {
+ JmsTemplate102 template = createTemplate();
+ template.setPubSubDomain(true);
+ template.setConnectionFactory(mockTopicConnectionFactory);
+ template.setMessageIdEnabled(false);
+ template.setMessageTimestampEnabled(false);
+ template.afterPropertiesSet();
+
+ MockControl topicPublisherControl = MockControl.createControl(TopicPublisher.class);
+ TopicPublisher mockTopicPublisher = (TopicPublisher) topicPublisherControl.getMock();
+
+ mockTopicSession.createPublisher(null);
+ topicSessionControl.setReturnValue(mockTopicPublisher);
+
+ mockTopicPublisher.setDisableMessageID(true);
+ topicPublisherControl.setVoidCallable(1);
+ mockTopicPublisher.setDisableMessageTimestamp(true);
+ topicPublisherControl.setVoidCallable(1);
+ mockTopicPublisher.getPriority();
+ topicPublisherControl.setReturnValue(4);
+
+ mockTopicPublisher.close();
+ topicPublisherControl.setVoidCallable(1);
+ mockTopicSession.close();
+ topicSessionControl.setVoidCallable(1);
+ mockTopicConnection.close();
+ topicConnectionControl.setVoidCallable(1);
+
+ topicPublisherControl.replay();
+ topicSessionControl.replay();
+ topicConnectionControl.replay();
+
+ template.execute(new ProducerCallback() {
+ public Object doInJms(Session session, MessageProducer producer) throws JMSException {
+ boolean b = session.getTransacted();
+ int i = producer.getPriority();
+ return null;
+ }
+ });
+
+ topicConnectionFactoryControl.verify();
+ topicConnectionControl.verify();
+ topicSessionControl.verify();
+ }
+
+ /**
+ * Test the method execute(SessionCallback action) with using the
+ * point to point domain as specified by the value of isPubSubDomain = false.
+ */
+ public void testQueueSessionCallback() throws Exception {
+ JmsTemplate102 template = createTemplate();
+ // Point-to-Point (queues) are the default domain
+ template.setConnectionFactory(mockQueueConnectionFactory);
+ template.afterPropertiesSet();
+
+ mockQueueSession.close();
+ queueSessionControl.setVoidCallable(1);
+
+ mockQueueConnection.close();
+ queueConnectionControl.setVoidCallable(1);
+
+ queueSessionControl.replay();
+ queueConnectionControl.replay();
+
+ template.execute(new SessionCallback() {
+ public Object doInJms(Session session) throws JMSException {
+ boolean b = session.getTransacted();
+ return null;
+ }
+ });
+
+ queueConnectionFactoryControl.verify();
+ queueConnectionControl.verify();
+ queueSessionControl.verify();
+ }
+
+ /**
+ * Test the method execute(ProducerCallback) with a Queue.
+ */
+ public void testQueueProducerCallback() throws Exception {
+ JmsTemplate102 template = createTemplate();
+ // Point-to-Point (queues) are the default domain.
+ template.setConnectionFactory(mockQueueConnectionFactory);
+ template.afterPropertiesSet();
+
+ MockControl queueSenderControl = MockControl.createControl(QueueSender.class);
+ QueueSender mockQueueSender = (QueueSender) queueSenderControl.getMock();
+
+ mockQueueSession.createSender(null);
+ queueSessionControl.setReturnValue(mockQueueSender);
+
+ mockQueueSender.getPriority();
+ queueSenderControl.setReturnValue(4);
+
+ mockQueueSender.close();
+ queueSenderControl.setVoidCallable(1);
+ mockQueueSession.close();
+ queueSessionControl.setVoidCallable(1);
+ mockQueueConnection.close();
+ queueConnectionControl.setVoidCallable(1);
+
+ queueSenderControl.replay();
+ queueSessionControl.replay();
+ queueConnectionControl.replay();
+
+ template.execute(new ProducerCallback() {
+ public Object doInJms(Session session, MessageProducer producer)
+ throws JMSException {
+ boolean b = session.getTransacted();
+ int i = producer.getPriority();
+ return null;
+ }
+ });
+
+ queueConnectionFactoryControl.verify();
+ queueConnectionControl.verify();
+ queueSessionControl.verify();
+ }
+
+ public void testQueueProducerCallbackWithIdAndTimestampDisabled() throws Exception {
+ JmsTemplate102 template = createTemplate();
+ // Point-to-Point (queues) are the default domain.
+ template.setConnectionFactory(mockQueueConnectionFactory);
+ template.setMessageIdEnabled(false);
+ template.setMessageTimestampEnabled(false);
+ template.afterPropertiesSet();
+
+ MockControl queueSenderControl = MockControl.createControl(QueueSender.class);
+ QueueSender mockQueueSender = (QueueSender) queueSenderControl.getMock();
+
+ mockQueueSession.createSender(null);
+ queueSessionControl.setReturnValue(mockQueueSender);
+
+ mockQueueSender.setDisableMessageID(true);
+ queueSenderControl.setVoidCallable(1);
+ mockQueueSender.setDisableMessageTimestamp(true);
+ queueSenderControl.setVoidCallable(1);
+ mockQueueSender.getPriority();
+ queueSenderControl.setReturnValue(4);
+
+ mockQueueSender.close();
+ queueSenderControl.setVoidCallable(1);
+ mockQueueSession.close();
+ queueSessionControl.setVoidCallable(1);
+ mockQueueConnection.close();
+ queueConnectionControl.setVoidCallable(1);
+
+ queueSenderControl.replay();
+ queueSessionControl.replay();
+ queueConnectionControl.replay();
+
+ template.execute(new ProducerCallback() {
+ public Object doInJms(Session session, MessageProducer producer) throws JMSException {
+ boolean b = session.getTransacted();
+ int i = producer.getPriority();
+ return null;
+ }
+ });
+
+ queueConnectionFactoryControl.verify();
+ queueConnectionControl.verify();
+ queueSessionControl.verify();
+ }
+
+ /**
+ * Test the setting of the JmsTemplate properties.
+ */
+ public void testBeanProperties() throws Exception {
+ JmsTemplate102 template = createTemplate();
+ template.setConnectionFactory(mockQueueConnectionFactory);
+
+ assertTrue("connection factory ok", template.getConnectionFactory() == mockQueueConnectionFactory);
+
+ JmsTemplate102 s102 = createTemplate();
+ try {
+ s102.afterPropertiesSet();
+ fail("IllegalArgumentException not thrown. ConnectionFactory should be set");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+
+ // The default is for the JmsTemplate102 to send to queues.
+ // Test to make sure exeception is thrown and has reasonable message.
+ s102 = createTemplate();
+ s102.setConnectionFactory(mockTopicConnectionFactory);
+ try {
+ s102.afterPropertiesSet();
+ fail("IllegalArgumentException not thrown. Mismatch of Destination and ConnectionFactory types.");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+
+ s102 = createTemplate();
+ s102.setConnectionFactory(mockQueueConnectionFactory);
+ s102.setPubSubDomain(true);
+ try {
+ s102.afterPropertiesSet();
+ fail("IllegalArgumentException not thrown. Mismatch of Destination and ConnectionFactory types.");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ /**
+ * Test the method send(String destination, MessgaeCreator c) using
+ * a queue and default QOS values.
+ */
+ public void testSendStringQueue() throws Exception {
+ sendQueue(true, false, false, true);
+ }
+
+ /**
+ * Test the method send(String destination, MessageCreator c) when
+ * explicit QOS parameters are enabled, using a queue.
+ */
+ public void testSendStringQueueWithQOS() throws Exception {
+ sendQueue(false, false, false, false);
+ }
+
+ /**
+ * Test the method send(MessageCreator c) using default QOS values.
+ */
+ public void testSendDefaultDestinationQueue() throws Exception {
+ sendQueue(true, false, true, true);
+ }
+
+ /**
+ * Test the method send(MessageCreator c) using explicit QOS values.
+ */
+ public void testSendDefaultDestinationQueueWithQOS() throws Exception {
+ sendQueue(false, false, true, false);
+ }
+
+ /**
+ * Test the method send(String destination, MessageCreator c) using
+ * a topic and default QOS values.
+ */
+ public void testSendStringTopic() throws Exception {
+ sendTopic(true, false);
+ }
+
+ /**
+ * Test the method send(String destination, MessageCreator c) using explicit
+ * QOS values.
+ */
+ public void testSendStringTopicWithQOS() throws Exception {
+ sendTopic(false, false);
+ }
+
+ /**
+ * Test the method send(Destination queue, MessgaeCreator c) using
+ * a queue and default QOS values.
+ */
+ public void testSendQueue() throws Exception {
+ sendQueue(true, false, false, true);
+ }
+
+ /**
+ * Test the method send(Destination queue, MessageCreator c) sing explicit
+ * QOS values.
+ */
+ public void testSendQueueWithQOS() throws Exception {
+ sendQueue(false, false, false, false);
+ }
+
+ /**
+ * Test the method send(Destination queue, MessgaeCreator c) using
+ * a topic and default QOS values.
+ */
+ public void testSendTopic() throws Exception {
+ sendTopic(true, false);
+ }
+
+ /**
+ * Test the method send(Destination queue, MessageCreator c) using explicity
+ * QOS values.
+ */
+ public void testSendTopicWithQOS() throws Exception {
+ sendQueue(false, false, false, true);
+ }
+
+ /**
+ * Common method for testing a send method that uses the MessageCreator
+ * callback but with different QOS options.
+ */
+ private void sendQueue(
+ boolean ignoreQOS, boolean explicitQueue, boolean useDefaultDestination, boolean disableIdAndTimestamp)
+ throws Exception {
+
+ JmsTemplate102 template = createTemplate();
+ template.setConnectionFactory(mockQueueConnectionFactory);
+ template.afterPropertiesSet();
+
+ if (useDefaultDestination) {
+ template.setDefaultDestination(mockQueue);
+ }
+ if (disableIdAndTimestamp) {
+ template.setMessageIdEnabled(false);
+ template.setMessageTimestampEnabled(false);
+ }
+
+ MockControl queueSenderControl = MockControl.createControl(QueueSender.class);
+ QueueSender mockQueueSender = (QueueSender) queueSenderControl.getMock();
+
+ MockControl messageControl = MockControl.createControl(TextMessage.class);
+ TextMessage mockMessage = (TextMessage) messageControl.getMock();
+
+ if (disableIdAndTimestamp) {
+ mockQueueSender.setDisableMessageID(true);
+ queueSenderControl.setVoidCallable(1);
+ mockQueueSender.setDisableMessageTimestamp(true);
+ queueSenderControl.setVoidCallable(1);
+ }
+
+ mockQueueSession.createSender(this.mockQueue);
+ queueSessionControl.setReturnValue(mockQueueSender);
+ mockQueueSession.createTextMessage("just testing");
+ queueSessionControl.setReturnValue(mockMessage);
+
+ if (useTransactedTemplate()) {
+ mockQueueSession.commit();
+ queueSessionControl.setVoidCallable(1);
+ }
+
+ if (ignoreQOS) {
+ mockQueueSender.send(mockMessage);
+ }
+ else {
+ template.setExplicitQosEnabled(true);
+ template.setDeliveryMode(deliveryMode);
+ template.setPriority(priority);
+ template.setTimeToLive(timeToLive);
+ mockQueueSender.send(mockMessage, deliveryMode, priority, timeToLive);
+ }
+ queueSenderControl.setVoidCallable(1);
+
+ mockQueueSender.close();
+ queueSenderControl.setVoidCallable(1);
+ mockQueueSession.close();
+ queueSessionControl.setVoidCallable(1);
+ mockQueueConnection.close();
+ queueConnectionControl.setVoidCallable(1);
+
+ queueSenderControl.replay();
+ queueSessionControl.replay();
+ queueConnectionControl.replay();
+
+ if (useDefaultDestination) {
+ template.send(new MessageCreator() {
+ public Message createMessage(Session session) throws JMSException {
+ return session.createTextMessage("just testing");
+ }
+ });
+ }
+ else {
+ if (explicitQueue) {
+ template.send(mockQueue, new MessageCreator() {
+ public Message createMessage(Session session) throws JMSException {
+ return session.createTextMessage("just testing");
+ }
+ });
+ }
+ else {
+ template.send("testQueue", new MessageCreator() {
+ public Message createMessage(Session session)
+ throws JMSException {
+ return session.createTextMessage("just testing");
+ }
+ });
+ }
+ }
+
+ queueConnectionFactoryControl.verify();
+ queueConnectionControl.verify();
+ queueSessionControl.verify();
+ queueSenderControl.verify();
+ }
+
+ private void sendTopic(boolean ignoreQOS, boolean explicitTopic) throws Exception {
+ JmsTemplate102 template = createTemplate();
+ template.setPubSubDomain(true);
+ template.setConnectionFactory(mockTopicConnectionFactory);
+ template.afterPropertiesSet();
+
+ MockControl topicPublisherControl = MockControl.createControl(TopicPublisher.class);
+ TopicPublisher mockTopicPublisher = (TopicPublisher) topicPublisherControl.getMock();
+
+ MockControl messageControl = MockControl.createControl(TextMessage.class);
+ TextMessage mockMessage = (TextMessage) messageControl.getMock();
+
+ mockTopicSession.createPublisher(this.mockTopic);
+ topicSessionControl.setReturnValue(mockTopicPublisher);
+ mockTopicSession.createTextMessage("just testing");
+ topicSessionControl.setReturnValue(mockMessage);
+
+ if (useTransactedTemplate()) {
+ mockTopicSession.commit();
+ topicSessionControl.setVoidCallable(1);
+ }
+
+ mockTopicPublisher.close();
+ topicPublisherControl.setVoidCallable(1);
+ mockTopicSession.close();
+ topicSessionControl.setVoidCallable(1);
+ mockTopicConnection.close();
+ topicConnectionControl.setVoidCallable(1);
+
+
+ topicSessionControl.replay();
+ topicConnectionControl.replay();
+
+ if (ignoreQOS) {
+ mockTopicPublisher.publish(mockMessage);
+ }
+ else {
+ template.setExplicitQosEnabled(true);
+ template.setDeliveryMode(deliveryMode);
+ template.setPriority(priority);
+ template.setTimeToLive(timeToLive);
+ mockTopicPublisher.publish(mockMessage, deliveryMode, priority, timeToLive);
+ }
+ topicPublisherControl.replay();
+
+ template.setPubSubDomain(true);
+
+ if (explicitTopic) {
+ template.send(mockTopic, new MessageCreator() {
+ public Message createMessage(Session session)
+ throws JMSException {
+ return session.createTextMessage("just testing");
+ }
+ });
+ }
+ else {
+ template.send("testTopic", new MessageCreator() {
+ public Message createMessage(Session session)
+ throws JMSException {
+ return session.createTextMessage("just testing");
+ }
+ });
+ }
+
+ topicConnectionFactoryControl.verify();
+ topicConnectionControl.verify();
+ topicSessionControl.verify();
+ topicPublisherControl.verify();
+ }
+
+ public void testConverter() throws Exception {
+ JmsTemplate102 template = createTemplate();
+ template.setConnectionFactory(mockQueueConnectionFactory);
+ template.setMessageConverter(new SimpleMessageConverter());
+ String s = "Hello world";
+
+ MockControl queueSenderControl = MockControl.createControl(QueueSender.class);
+ QueueSender mockQueueSender = (QueueSender) queueSenderControl.getMock();
+ MockControl messageControl = MockControl.createControl(TextMessage.class);
+ TextMessage mockMessage = (TextMessage) messageControl.getMock();
+
+ mockQueueSession.createSender(this.mockQueue);
+ queueSessionControl.setReturnValue(mockQueueSender);
+ mockQueueSession.createTextMessage("Hello world");
+ queueSessionControl.setReturnValue(mockMessage);
+
+ if (useTransactedTemplate()) {
+ mockQueueSession.commit();
+ queueSessionControl.setVoidCallable(1);
+ }
+
+ mockQueueSender.send(mockMessage);
+ queueSenderControl.setVoidCallable(1);
+
+ mockQueueSender.close();
+ queueSenderControl.setVoidCallable(1);
+ mockQueueSession.close();
+ queueSessionControl.setVoidCallable(1);
+ mockQueueConnection.close();
+ queueConnectionControl.setVoidCallable(1);
+
+ queueSenderControl.replay();
+ queueSessionControl.replay();
+ queueConnectionControl.replay();
+
+ template.convertAndSend(mockQueue, s);
+
+ queueConnectionFactoryControl.verify();
+ queueConnectionControl.verify();
+ queueSessionControl.verify();
+ queueSenderControl.verify();
+ }
+
+ public void testQueueReceiveDefaultDestination() throws Exception {
+ doTestReceive(false, false, true, false, false, false, false, JmsTemplate.RECEIVE_TIMEOUT_INDEFINITE_WAIT);
+ }
+
+ public void testQueueReceiveDestination() throws Exception {
+ doTestReceive(false, true, false, false, false, false, true, JmsTemplate.RECEIVE_TIMEOUT_INDEFINITE_WAIT);
+ }
+
+ public void testQueueReceiveDestinationWithClientAcknowledge() throws Exception {
+ doTestReceive(false, true, false, false, true, false, false, 1000);
+ }
+
+ public void testQueueReceiveStringDestination() throws Exception {
+ doTestReceive(false, false, false, false, false, false, true, JmsTemplate.RECEIVE_TIMEOUT_NO_WAIT);
+ }
+
+ public void testQueueReceiveDefaultDestinationWithSelector() throws Exception {
+ doTestReceive(false, false, true, false, false, true, true, 1000);
+ }
+
+ public void testQueueReceiveDestinationWithSelector() throws Exception {
+ doTestReceive(false, true, false, false, false, true, false, JmsTemplate.RECEIVE_TIMEOUT_NO_WAIT);
+ }
+
+ public void testQueueReceiveDestinationWithClientAcknowledgeWithSelector() throws Exception {
+ doTestReceive(false, true, false, false, true, true, true, JmsTemplate.RECEIVE_TIMEOUT_INDEFINITE_WAIT);
+ }
+
+ public void testQueueReceiveStringDestinationWithSelector() throws Exception {
+ doTestReceive(false, false, false, false, false, true, false, JmsTemplate.RECEIVE_TIMEOUT_INDEFINITE_WAIT);
+ }
+
+ public void testQueueReceiveAndConvertDefaultDestination() throws Exception {
+ doTestReceive(false, false, true, true, false, false, false, 1000);
+ }
+
+ public void testQueueReceiveAndConvertStringDestination() throws Exception {
+ doTestReceive(false, false, false, true, false, false, true, JmsTemplate.RECEIVE_TIMEOUT_INDEFINITE_WAIT);
+ }
+
+ public void testQueueReceiveAndConvertDestination() throws Exception {
+ doTestReceive(false, true, false, true, false, false, true, 1000);
+ }
+
+ public void testQueueReceiveAndConvertDefaultDestinationWithSelector() throws Exception {
+ doTestReceive(false, false, true, true, false, true, true, JmsTemplate.RECEIVE_TIMEOUT_NO_WAIT);
+ }
+
+ public void testQueueReceiveAndConvertStringDestinationWithSelector() throws Exception {
+ doTestReceive(false, false, false, true, false, true, true, JmsTemplate.RECEIVE_TIMEOUT_INDEFINITE_WAIT);
+ }
+
+ public void testQueueReceiveAndConvertDestinationWithSelector() throws Exception {
+ doTestReceive(false, true, false, true, false, true, false, 1000);
+ }
+
+ public void testTopicReceiveDefaultDestination() throws Exception {
+ doTestReceive(true, false, true, false, false, false, false, JmsTemplate.RECEIVE_TIMEOUT_INDEFINITE_WAIT);
+ }
+
+ public void testTopicReceiveDestination() throws Exception {
+ doTestReceive(true, true, false, false, false, false, true, JmsTemplate.RECEIVE_TIMEOUT_INDEFINITE_WAIT);
+ }
+
+ public void testTopicReceiveDestinationWithClientAcknowledge() throws Exception {
+ doTestReceive(true, true, false, false, true, false, false, 1000);
+ }
+
+ public void testTopicReceiveStringDestination() throws Exception {
+ doTestReceive(true, false, false, false, false, false, true, JmsTemplate.RECEIVE_TIMEOUT_NO_WAIT);
+ }
+
+ public void testTopicReceiveDefaultDestinationWithSelector() throws Exception {
+ doTestReceive(true, false, true, false, false, true, true, 1000);
+ }
+
+ public void testTopicReceiveDestinationWithSelector() throws Exception {
+ doTestReceive(true, true, false, false, false, true, false, 1000);
+ }
+
+ public void testTopicReceiveDestinationWithClientAcknowledgeWithSelector() throws Exception {
+ doTestReceive(true, true, false, false, true, true, true, JmsTemplate.RECEIVE_TIMEOUT_INDEFINITE_WAIT);
+ }
+
+ public void testTopicReceiveStringDestinationWithSelector() throws Exception {
+ doTestReceive(true, false, false, false, false, true, false, JmsTemplate.RECEIVE_TIMEOUT_INDEFINITE_WAIT);
+ }
+
+ public void testTopicReceiveAndConvertDefaultDestination() throws Exception {
+ doTestReceive(true, false, true, true, false, false, false, 1000);
+ }
+
+ public void testTopicReceiveAndConvertStringDestination() throws Exception {
+ doTestReceive(true, false, false, true, false, false, true, JmsTemplate.RECEIVE_TIMEOUT_INDEFINITE_WAIT);
+ }
+
+ public void testTopicReceiveAndConvertDestination() throws Exception {
+ doTestReceive(true, true, false, true, false, false, true, 1000);
+ }
+
+ public void testTopicReceiveAndConvertDefaultDestinationWithSelector() throws Exception {
+ doTestReceive(true, false, true, true, false, true, true, JmsTemplate.RECEIVE_TIMEOUT_NO_WAIT);
+ }
+
+ public void testTopicReceiveAndConvertStringDestinationWithSelector() throws Exception {
+ doTestReceive(true, false, false, true, false, true, true, JmsTemplate.RECEIVE_TIMEOUT_INDEFINITE_WAIT);
+ }
+
+ public void testTopicReceiveAndConvertDestinationWithSelector() throws Exception {
+ doTestReceive(true, true, false, true, false, true, false, 1000);
+ }
+
+ private void doTestReceive(
+ boolean pubSub,
+ boolean explicitDestination, boolean useDefaultDestination, boolean testConverter,
+ boolean clientAcknowledge, boolean messageSelector, boolean noLocal, long timeout)
+ throws Exception {
+
+ JmsTemplate102 template = createTemplate();
+ template.setPubSubDomain(pubSub);
+ if (pubSub) {
+ template.setConnectionFactory(mockTopicConnectionFactory);
+ }
+ else {
+ template.setConnectionFactory(mockQueueConnectionFactory);
+ }
+
+ // Override the default settings for client ack used in the test setup.
+ // Can't use Session.getAcknowledgeMode()
+ if (pubSub) {
+ topicConnectionControl.reset();
+ if (clientAcknowledge) {
+ template.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
+ mockTopicConnection.createTopicSession(useTransactedTemplate(), Session.CLIENT_ACKNOWLEDGE);
+ }
+ else {
+ template.setSessionAcknowledgeMode(Session.AUTO_ACKNOWLEDGE);
+ mockTopicConnection.createTopicSession(useTransactedTemplate(), Session.AUTO_ACKNOWLEDGE);
+ }
+ topicConnectionControl.setReturnValue(mockTopicSession);
+ }
+ else {
+ queueConnectionControl.reset();
+ if (clientAcknowledge) {
+ template.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
+ mockQueueConnection.createQueueSession(useTransactedTemplate(), Session.CLIENT_ACKNOWLEDGE);
+ }
+ else {
+ template.setSessionAcknowledgeMode(Session.AUTO_ACKNOWLEDGE);
+ mockQueueConnection.createQueueSession(useTransactedTemplate(), Session.AUTO_ACKNOWLEDGE);
+ }
+ queueConnectionControl.setReturnValue(mockQueueSession);
+ }
+
+ Destination dest = pubSub ? (Destination) mockTopic : (Destination) mockQueue;
+
+ if (useDefaultDestination) {
+ template.setDefaultDestination(dest);
+ }
+ if (noLocal) {
+ template.setPubSubNoLocal(true);
+ }
+ template.setReceiveTimeout(timeout);
+
+ if (pubSub) {
+ mockTopicConnection.start();
+ topicConnectionControl.setVoidCallable(1);
+ mockTopicConnection.close();
+ topicConnectionControl.setVoidCallable(1);
+ }
+ else {
+ mockQueueConnection.start();
+ queueConnectionControl.setVoidCallable(1);
+ mockQueueConnection.close();
+ queueConnectionControl.setVoidCallable(1);
+ }
+
+ String selectorString = "selector";
+ MockControl messageConsumerControl = null;
+ MessageConsumer mockMessageConsumer = null;
+
+ if (pubSub) {
+ messageConsumerControl = MockControl.createControl(TopicSubscriber.class);
+ TopicSubscriber mockTopicSubscriber = (TopicSubscriber) messageConsumerControl.getMock();
+ mockMessageConsumer = mockTopicSubscriber;
+ mockTopicSession.createSubscriber(mockTopic, messageSelector ? selectorString : null, noLocal);
+ topicSessionControl.setReturnValue(mockTopicSubscriber);
+ }
+ else {
+ messageConsumerControl = MockControl.createControl(QueueReceiver.class);
+ QueueReceiver mockQueueReceiver = (QueueReceiver) messageConsumerControl.getMock();
+ mockMessageConsumer = mockQueueReceiver;
+ mockQueueSession.createReceiver(mockQueue, messageSelector ? selectorString : null);
+ queueSessionControl.setReturnValue(mockQueueReceiver);
+ }
+
+ if (useTransactedTemplate()) {
+ if (pubSub) {
+ mockTopicSession.commit();
+ topicSessionControl.setVoidCallable(1);
+ }
+ else {
+ mockQueueSession.commit();
+ queueSessionControl.setVoidCallable(1);
+ }
+ }
+
+ if (pubSub) {
+ mockTopicSession.close();
+ topicSessionControl.setVoidCallable(1);
+ }
+ else {
+ mockQueueSession.close();
+ queueSessionControl.setVoidCallable(1);
+ }
+
+ MockControl messageControl = MockControl.createControl(TextMessage.class);
+ TextMessage mockMessage = (TextMessage) messageControl.getMock();
+
+ if (testConverter) {
+ mockMessage.getText();
+ messageControl.setReturnValue("Hello World!");
+ }
+ if (!useTransactedSession() && clientAcknowledge) {
+ mockMessage.acknowledge();
+ messageControl.setVoidCallable(1);
+ }
+
+ if (pubSub) {
+ topicSessionControl.replay();
+ topicConnectionControl.replay();
+ }
+ else {
+ queueSessionControl.replay();
+ queueConnectionControl.replay();
+ }
+ messageControl.replay();
+
+ if (timeout == JmsTemplate.RECEIVE_TIMEOUT_NO_WAIT) {
+ mockMessageConsumer.receiveNoWait();
+ }
+ else if (timeout == JmsTemplate.RECEIVE_TIMEOUT_INDEFINITE_WAIT) {
+ mockMessageConsumer.receive();
+ }
+ else {
+ mockMessageConsumer.receive(timeout);
+ }
+ messageConsumerControl.setReturnValue(mockMessage);
+ mockMessageConsumer.close();
+ messageConsumerControl.setVoidCallable(1);
+
+ messageConsumerControl.replay();
+
+ Message message = null;
+ String textFromMessage = null;
+
+ if (useDefaultDestination) {
+ if (testConverter) {
+ textFromMessage = (String)
+ (messageSelector ? template.receiveSelectedAndConvert(selectorString) :
+ template.receiveAndConvert());
+ }
+ else {
+ message = (messageSelector ? template.receiveSelected(selectorString) : template.receive());
+ }
+ }
+ else if (explicitDestination) {
+ if (testConverter) {
+ textFromMessage = (String)
+ (messageSelector ? template.receiveSelectedAndConvert(dest, selectorString) :
+ template.receiveAndConvert(dest));
+ }
+ else {
+ message = (messageSelector ? template.receiveSelected(dest, selectorString) :
+ template.receive(dest));
+ }
+ }
+ else {
+ String destinationName = (pubSub ? "testTopic" : "testQueue");
+ if (testConverter) {
+ textFromMessage = (String)
+ (messageSelector ? template.receiveSelectedAndConvert(destinationName, selectorString) :
+ template.receiveAndConvert(destinationName));
+ }
+ else {
+ message = (messageSelector ? template.receiveSelected(destinationName, selectorString) :
+ template.receive(destinationName));
+ }
+ }
+
+ if (pubSub) {
+ topicConnectionFactoryControl.verify();
+ topicConnectionControl.verify();
+ topicSessionControl.verify();
+ }
+ else {
+ queueConnectionFactoryControl.verify();
+ queueConnectionControl.verify();
+ queueSessionControl.verify();
+ }
+ messageConsumerControl.verify();
+ messageControl.verify();
+
+ if (testConverter) {
+ assertEquals("Message text should be equal", "Hello World!", textFromMessage);
+ }
+ else {
+ assertEquals("Messages should refer to the same object", message, mockMessage);
+ }
+ }
+
+ public void testIllegalStateException() throws Exception {
+ doTestJmsException(new javax.jms.IllegalStateException(""), org.springframework.jms.IllegalStateException.class);
+ }
+
+ public void testInvalidClientIDException() throws Exception {
+ doTestJmsException(new javax.jms.InvalidClientIDException(""), InvalidClientIDException.class);
+ }
+
+ public void testInvalidDestinationException() throws Exception {
+ doTestJmsException(new javax.jms.InvalidDestinationException(""), InvalidDestinationException.class);
+ }
+
+ public void testInvalidSelectorException() throws Exception {
+ doTestJmsException(new javax.jms.InvalidSelectorException(""), InvalidSelectorException.class);
+ }
+
+ public void testJmsSecurityException() throws Exception {
+ doTestJmsException(new javax.jms.JMSSecurityException(""), JmsSecurityException.class);
+ }
+
+ public void testMessageEOFException() throws Exception {
+ doTestJmsException(new javax.jms.MessageEOFException(""), MessageEOFException.class);
+ }
+
+ public void testMessageFormatException() throws Exception {
+ doTestJmsException(new javax.jms.MessageFormatException(""), MessageFormatException.class);
+ }
+
+ public void testMessageNotReadableException() throws Exception {
+ doTestJmsException(new javax.jms.MessageNotReadableException(""), MessageNotReadableException.class);
+ }
+
+ public void testMessageNotWriteableException() throws Exception {
+ doTestJmsException(new javax.jms.MessageNotWriteableException(""), MessageNotWriteableException.class);
+ }
+
+ public void testResourceAllocationException() throws Exception {
+ doTestJmsException(new javax.jms.ResourceAllocationException(""), ResourceAllocationException.class);
+ }
+
+ public void testTransactionInProgressException() throws Exception {
+ doTestJmsException(new javax.jms.TransactionInProgressException(""), TransactionInProgressException.class);
+ }
+
+ public void testTransactionRolledBackException() throws Exception {
+ doTestJmsException(new javax.jms.TransactionRolledBackException(""), TransactionRolledBackException.class);
+ }
+
+ public void testUncategorizedJmsException() throws Exception {
+ doTestJmsException(new javax.jms.JMSException(""), UncategorizedJmsException.class);
+ }
+
+ protected void doTestJmsException(JMSException original, Class thrownExceptionClass) throws Exception {
+ JmsTemplate template = createTemplate();
+ template.setConnectionFactory(mockQueueConnectionFactory);
+ template.setMessageConverter(new SimpleMessageConverter());
+ String s = "Hello world";
+
+ MockControl queueSenderControl = MockControl.createControl(QueueSender.class);
+ QueueSender mockQueueSender = (QueueSender) queueSenderControl.getMock();
+ MockControl messageControl = MockControl.createControl(TextMessage.class);
+ TextMessage mockMessage = (TextMessage) messageControl.getMock();
+
+ queueSessionControl.reset();
+ mockQueueSession.createSender(mockQueue);
+ queueSessionControl.setReturnValue(mockQueueSender);
+ mockQueueSession.createTextMessage("Hello world");
+ queueSessionControl.setReturnValue(mockMessage);
+
+ mockQueueSender.send(mockMessage);
+ queueSenderControl.setThrowable(original, 1);
+ mockQueueSender.close();
+ queueSenderControl.setVoidCallable(1);
+
+ mockQueueSession.close();
+ queueSessionControl.setVoidCallable(1);
+ mockQueueConnection.close();
+ queueConnectionControl.setVoidCallable(1);
+
+ queueSenderControl.replay();
+ queueSessionControl.replay();
+ queueConnectionControl.replay();
+
+ try {
+ template.convertAndSend(mockQueue, s);
+ fail("Should have thrown JmsException");
+ }
+ catch (JmsException wrappedEx) {
+ // expected
+ assertEquals(thrownExceptionClass, wrappedEx.getClass());
+ assertEquals(original, wrappedEx.getCause());
+ }
+
+ queueSenderControl.verify();
+ queueSessionControl.verify();
+ queueConnectionControl.verify();
+ queueConnectionFactoryControl.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/core/JmsTemplate102TransactedTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/core/JmsTemplate102TransactedTests.java
new file mode 100644
index 00000000000..20e5b3ed2bb
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/core/JmsTemplate102TransactedTests.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jms.core;
+
+/**
+ * @author Juergen Hoeller
+ * @since 06.01.2005
+ */
+public class JmsTemplate102TransactedTests extends JmsTemplate102Tests {
+
+ protected boolean useTransactedSession() {
+ return true;
+ }
+
+ protected boolean useTransactedTemplate() {
+ return true;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/core/JmsTemplateJtaTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/core/JmsTemplateJtaTests.java
new file mode 100644
index 00000000000..f13a7ccd562
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/core/JmsTemplateJtaTests.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jms.core;
+
+/**
+ * @author Juergen Hoeller
+ * @since 06.01.2005
+ */
+public class JmsTemplateJtaTests extends JmsTemplateTests {
+
+ protected boolean useTransactedSession() {
+ return true;
+ }
+
+ protected boolean useTransactedTemplate() {
+ return false;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/core/JmsTemplateTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/core/JmsTemplateTests.java
new file mode 100644
index 00000000000..4cd15f43485
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/core/JmsTemplateTests.java
@@ -0,0 +1,847 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jms.core;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.List;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.DeliveryMode;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+import javax.naming.Context;
+import javax.naming.NamingException;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.jms.InvalidClientIDException;
+import org.springframework.jms.InvalidDestinationException;
+import org.springframework.jms.InvalidSelectorException;
+import org.springframework.jms.JmsException;
+import org.springframework.jms.JmsSecurityException;
+import org.springframework.jms.MessageEOFException;
+import org.springframework.jms.MessageFormatException;
+import org.springframework.jms.MessageNotReadableException;
+import org.springframework.jms.MessageNotWriteableException;
+import org.springframework.jms.ResourceAllocationException;
+import org.springframework.jms.TransactionInProgressException;
+import org.springframework.jms.TransactionRolledBackException;
+import org.springframework.jms.UncategorizedJmsException;
+import org.springframework.jms.connection.ConnectionFactoryUtils;
+import org.springframework.jms.connection.SingleConnectionFactory;
+import org.springframework.jms.connection.TransactionAwareConnectionFactoryProxy;
+import org.springframework.jms.support.JmsUtils;
+import org.springframework.jms.support.converter.SimpleMessageConverter;
+import org.springframework.jms.support.destination.JndiDestinationResolver;
+import org.springframework.jndi.JndiTemplate;
+import org.springframework.transaction.support.TransactionSynchronization;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+
+/**
+ * Unit tests for the JmsTemplate implemented using JMS 1.1.
+ *
+ * @author Andre Biryukov
+ * @author Mark Pollack
+ */
+public class JmsTemplateTests extends TestCase {
+
+ private Context mockJndiContext;
+ private MockControl mockJndiControl;
+
+ private MockControl connectionFactoryControl;
+ private ConnectionFactory mockConnectionFactory;
+
+ private MockControl connectionControl;
+ private Connection mockConnection;
+
+ private MockControl sessionControl;
+ private Session mockSession;
+
+ private MockControl queueControl;
+ private Destination mockQueue;
+
+ private int deliveryMode = DeliveryMode.PERSISTENT;
+ private int priority = 9;
+ private int timeToLive = 10000;
+
+
+ /**
+ * Create the mock objects for testing.
+ */
+ protected void setUp() throws Exception {
+ mockJndiControl = MockControl.createControl(Context.class);
+ mockJndiContext = (Context) this.mockJndiControl.getMock();
+
+ createMockforDestination();
+
+ mockJndiContext.close();
+ mockJndiControl.replay();
+ }
+
+ private void createMockforDestination() throws JMSException, NamingException {
+ connectionFactoryControl = MockControl.createControl(ConnectionFactory.class);
+ mockConnectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+
+ connectionControl = MockControl.createControl(Connection.class);
+ mockConnection = (Connection) connectionControl.getMock();
+
+ sessionControl = MockControl.createControl(Session.class);
+ mockSession = (Session) sessionControl.getMock();
+
+ queueControl = MockControl.createControl(Queue.class);
+ mockQueue = (Queue) queueControl.getMock();
+
+ mockConnectionFactory.createConnection();
+ connectionFactoryControl.setReturnValue(mockConnection);
+ connectionFactoryControl.replay();
+
+ mockConnection.createSession(useTransactedTemplate(), Session.AUTO_ACKNOWLEDGE);
+ connectionControl.setReturnValue(mockSession);
+ mockSession.getTransacted();
+ sessionControl.setReturnValue(useTransactedSession());
+
+ mockJndiContext.lookup("testDestination");
+ mockJndiControl.setReturnValue(mockQueue);
+ }
+
+ private JmsTemplate createTemplate() {
+ JmsTemplate template = new JmsTemplate();
+ JndiDestinationResolver destMan = new JndiDestinationResolver();
+ destMan.setJndiTemplate(new JndiTemplate() {
+ protected Context createInitialContext() {
+ return mockJndiContext;
+ }
+ });
+ template.setDestinationResolver(destMan);
+ template.setSessionTransacted(useTransactedTemplate());
+ return template;
+ }
+
+ protected boolean useTransactedSession() {
+ return false;
+ }
+
+ protected boolean useTransactedTemplate() {
+ return false;
+ }
+
+
+ public void testExceptionStackTrace() {
+ JMSException jmsEx = new JMSException("could not connect");
+ Exception innerEx = new Exception("host not found");
+ jmsEx.setLinkedException(innerEx);
+ JmsException springJmsEx = JmsUtils.convertJmsAccessException(jmsEx);
+ StringWriter sw = new StringWriter();
+ PrintWriter out = new PrintWriter(sw);
+ springJmsEx.printStackTrace(out);
+ String trace = sw.toString();
+ assertTrue("inner jms exception not found", trace.indexOf("host not found") > 0);
+ }
+
+ public void testProducerCallback() throws Exception {
+ JmsTemplate template = createTemplate();
+ template.setConnectionFactory(mockConnectionFactory);
+
+ MockControl messageProducerControl = MockControl.createControl(MessageProducer.class);
+ MessageProducer mockMessageProducer = (MessageProducer) messageProducerControl.getMock();
+
+ mockSession.createProducer(null);
+ sessionControl.setReturnValue(mockMessageProducer);
+
+ mockMessageProducer.getPriority();
+ messageProducerControl.setReturnValue(4);
+
+ mockMessageProducer.close();
+ messageProducerControl.setVoidCallable(1);
+ mockSession.close();
+ sessionControl.setVoidCallable(1);
+ mockConnection.close();
+ connectionControl.setVoidCallable(1);
+
+ messageProducerControl.replay();
+ sessionControl.replay();
+ connectionControl.replay();
+
+ template.execute(new ProducerCallback() {
+ public Object doInJms(Session session, MessageProducer producer) throws JMSException {
+ boolean b = session.getTransacted();
+ int i = producer.getPriority();
+ return null;
+ }
+ });
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testProducerCallbackWithIdAndTimestampDisabled() throws Exception {
+ JmsTemplate template = createTemplate();
+ template.setConnectionFactory(mockConnectionFactory);
+ template.setMessageIdEnabled(false);
+ template.setMessageTimestampEnabled(false);
+
+ MockControl messageProducerControl = MockControl.createControl(MessageProducer.class);
+ MessageProducer mockMessageProducer = (MessageProducer) messageProducerControl.getMock();
+
+ mockSession.createProducer(null);
+ sessionControl.setReturnValue(mockMessageProducer);
+
+ mockMessageProducer.setDisableMessageID(true);
+ messageProducerControl.setVoidCallable(1);
+ mockMessageProducer.setDisableMessageTimestamp(true);
+ messageProducerControl.setVoidCallable(1);
+ mockMessageProducer.getPriority();
+ messageProducerControl.setReturnValue(4);
+
+ mockMessageProducer.close();
+ messageProducerControl.setVoidCallable(1);
+ mockSession.close();
+ sessionControl.setVoidCallable(1);
+ mockConnection.close();
+ connectionControl.setVoidCallable(1);
+
+ messageProducerControl.replay();
+ sessionControl.replay();
+ connectionControl.replay();
+
+ template.execute(new ProducerCallback() {
+ public Object doInJms(Session session, MessageProducer producer) throws JMSException {
+ boolean b = session.getTransacted();
+ int i = producer.getPriority();
+ return null;
+ }
+ });
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ sessionControl.verify();
+ }
+
+ /**
+ * Test the method execute(SessionCallback action).
+ */
+ public void testSessionCallback() throws Exception {
+ JmsTemplate template = createTemplate();
+ template.setConnectionFactory(mockConnectionFactory);
+
+ mockSession.close();
+ sessionControl.setVoidCallable(1);
+
+ mockConnection.close();
+ connectionControl.setVoidCallable(1);
+
+ sessionControl.replay();
+ connectionControl.replay();
+
+ template.execute(new SessionCallback() {
+ public Object doInJms(Session session) throws JMSException {
+ boolean b = session.getTransacted();
+ return null;
+ }
+ });
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testSessionCallbackWithinSynchronizedTransaction() throws Exception {
+ SingleConnectionFactory scf = new SingleConnectionFactory(mockConnectionFactory);
+ JmsTemplate template = createTemplate();
+ template.setConnectionFactory(scf);
+
+ mockConnection.start();
+ connectionControl.setVoidCallable(3);
+ // We're gonna call getTransacted 3 times, i.e. 2 more times.
+ mockSession.getTransacted();
+ sessionControl.setReturnValue(useTransactedSession(), 2);
+ if (useTransactedTemplate()) {
+ mockSession.commit();
+ sessionControl.setVoidCallable(1);
+ }
+ mockSession.close();
+ sessionControl.setVoidCallable(1);
+ mockConnection.stop();
+ connectionControl.setVoidCallable(1);
+ mockConnection.close();
+ connectionControl.setVoidCallable(1);
+
+ sessionControl.replay();
+ connectionControl.replay();
+
+ TransactionSynchronizationManager.initSynchronization();
+ try {
+ template.execute(new SessionCallback() {
+ public Object doInJms(Session session) throws JMSException {
+ boolean b = session.getTransacted();
+ return null;
+ }
+ });
+ template.execute(new SessionCallback() {
+ public Object doInJms(Session session) throws JMSException {
+ boolean b = session.getTransacted();
+ return null;
+ }
+ });
+
+ assertSame(mockSession, ConnectionFactoryUtils.getTransactionalSession(scf, null, false));
+ assertSame(mockSession, ConnectionFactoryUtils.getTransactionalSession(scf, scf.createConnection(), false));
+
+ TransactionAwareConnectionFactoryProxy tacf = new TransactionAwareConnectionFactoryProxy(scf);
+ Connection tac = tacf.createConnection();
+ Session tas = tac.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ boolean b = tas.getTransacted();
+ tas.close();
+ tac.close();
+
+ List synchs = TransactionSynchronizationManager.getSynchronizations();
+ assertEquals(1, synchs.size());
+ TransactionSynchronization synch = (TransactionSynchronization) synchs.get(0);
+ synch.beforeCommit(false);
+ synch.beforeCompletion();
+ synch.afterCommit();
+ synch.afterCompletion(TransactionSynchronization.STATUS_UNKNOWN);
+ }
+ finally {
+ TransactionSynchronizationManager.clearSynchronization();
+ scf.destroy();
+ }
+ assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ sessionControl.verify();
+ }
+
+ /**
+ * Test sending to a destination using the method
+ * send(Destination d, MessageCreator messageCreator)
+ */
+ public void testSendDestination() throws Exception {
+ doTestSendDestination(true, false, true, false);
+ }
+
+ /**
+ * Test seding to a destination using the method
+ * send(String d, MessageCreator messageCreator)
+ */
+ public void testSendDestinationName() throws Exception {
+ doTestSendDestination(false, false, true, false);
+ }
+
+ /**
+ * Test sending to a destination using the method
+ * send(Destination d, MessageCreator messageCreator) using QOS parameters.
+ */
+ public void testSendDestinationWithQOS() throws Exception {
+ doTestSendDestination(true, false, false, true);
+ }
+
+ /**
+ * Test sending to a destination using the method
+ * send(String d, MessageCreator messageCreator) using QOS parameters.
+ */
+ public void testSendDestinationNameWithQOS() throws Exception {
+ doTestSendDestination(false, false, false, true);
+ }
+
+ /**
+ * Test sending to the default destination.
+ */
+ public void testSendDefaultDestination() throws Exception {
+ doTestSendDestination(true, true, true, true);
+ }
+
+ /**
+ * Test sending to the default destination name.
+ */
+ public void testSendDefaultDestinationName() throws Exception {
+ doTestSendDestination(false, true, true, true);
+ }
+
+ /**
+ * Test sending to the default destination using explicit QOS parameters.
+ */
+ public void testSendDefaultDestinationWithQOS() throws Exception {
+ doTestSendDestination(true, true, false, false);
+ }
+
+ /**
+ * Test sending to the default destination name using explicit QOS parameters.
+ */
+ public void testSendDefaultDestinationNameWithQOS() throws Exception {
+ doTestSendDestination(false, true, false, false);
+ }
+
+ /**
+ * Common method for testing a send method that uses the MessageCreator
+ * callback but with different QOS options.
+ * @param ignoreQOS test using default QOS options.
+ */
+ private void doTestSendDestination(
+ boolean explicitDestination, boolean useDefaultDestination,
+ boolean ignoreQOS, boolean disableIdAndTimestamp) throws Exception {
+
+ JmsTemplate template = createTemplate();
+ template.setConnectionFactory(mockConnectionFactory);
+
+ String destinationName = "testDestination";
+
+ if (useDefaultDestination) {
+ if (explicitDestination) {
+ template.setDefaultDestination(mockQueue);
+ }
+ else {
+ template.setDefaultDestinationName(destinationName);
+ }
+ }
+ if (disableIdAndTimestamp) {
+ template.setMessageIdEnabled(false);
+ template.setMessageTimestampEnabled(false);
+ }
+
+ MockControl messageProducerControl = MockControl.createControl(MessageProducer.class);
+ MessageProducer mockMessageProducer = (MessageProducer) messageProducerControl.getMock();
+
+ MockControl messageControl = MockControl.createControl(TextMessage.class);
+ TextMessage mockMessage = (TextMessage) messageControl.getMock();
+
+ mockSession.createProducer(mockQueue);
+ sessionControl.setReturnValue(mockMessageProducer);
+ mockSession.createTextMessage("just testing");
+ sessionControl.setReturnValue(mockMessage);
+
+ if (useTransactedTemplate()) {
+ mockSession.commit();
+ sessionControl.setVoidCallable(1);
+ }
+
+ if (disableIdAndTimestamp) {
+ mockMessageProducer.setDisableMessageID(true);
+ messageProducerControl.setVoidCallable(1);
+ mockMessageProducer.setDisableMessageTimestamp(true);
+ messageProducerControl.setVoidCallable(1);
+ }
+
+ if (ignoreQOS) {
+ mockMessageProducer.send(mockMessage);
+ }
+ else {
+ template.setExplicitQosEnabled(true);
+ template.setDeliveryMode(deliveryMode);
+ template.setPriority(priority);
+ template.setTimeToLive(timeToLive);
+ mockMessageProducer.send(mockMessage, deliveryMode, priority, timeToLive);
+ }
+ messageProducerControl.setVoidCallable(1);
+
+ mockMessageProducer.close();
+ messageProducerControl.setVoidCallable(1);
+ mockSession.close();
+ sessionControl.setVoidCallable(1);
+ mockConnection.close();
+ connectionControl.setVoidCallable(1);
+
+ messageProducerControl.replay();
+ sessionControl.replay();
+ connectionControl.replay();
+
+ if (useDefaultDestination) {
+ template.send(new MessageCreator() {
+ public Message createMessage(Session session) throws JMSException {
+ return session.createTextMessage("just testing");
+ }
+ });
+ }
+ else {
+ if (explicitDestination) {
+ template.send(mockQueue, new MessageCreator() {
+ public Message createMessage(Session session) throws JMSException {
+ return session.createTextMessage("just testing");
+ }
+ });
+ }
+ else {
+ template.send(destinationName, new MessageCreator() {
+ public Message createMessage(Session session) throws JMSException {
+ return session.createTextMessage("just testing");
+ }
+ });
+ }
+ }
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ sessionControl.verify();
+ messageProducerControl.verify();
+ }
+
+ public void testConverter() throws Exception {
+ JmsTemplate template = createTemplate();
+ template.setConnectionFactory(mockConnectionFactory);
+ template.setMessageConverter(new SimpleMessageConverter());
+ String s = "Hello world";
+
+ MockControl messageProducerControl = MockControl.createControl(MessageProducer.class);
+ MessageProducer mockMessageProducer = (MessageProducer) messageProducerControl.getMock();
+ MockControl messageControl = MockControl.createControl(TextMessage.class);
+ TextMessage mockMessage = (TextMessage) messageControl.getMock();
+
+ mockSession.createProducer(mockQueue);
+ sessionControl.setReturnValue(mockMessageProducer);
+ mockSession.createTextMessage("Hello world");
+ sessionControl.setReturnValue(mockMessage);
+
+ mockMessageProducer.send(mockMessage);
+ messageProducerControl.setVoidCallable(1);
+ mockMessageProducer.close();
+ messageProducerControl.setVoidCallable(1);
+
+ if (useTransactedTemplate()) {
+ mockSession.commit();
+ sessionControl.setVoidCallable(1);
+ }
+
+ mockSession.close();
+ sessionControl.setVoidCallable(1);
+ mockConnection.close();
+ connectionControl.setVoidCallable(1);
+
+ messageProducerControl.replay();
+ sessionControl.replay();
+ connectionControl.replay();
+
+ template.convertAndSend(mockQueue, s);
+
+ messageProducerControl.verify();
+ sessionControl.verify();
+ connectionControl.verify();
+ connectionFactoryControl.verify();
+ }
+
+ public void testReceiveDefaultDestination() throws Exception {
+ doTestReceive(true, true, false, false, false, false, JmsTemplate.RECEIVE_TIMEOUT_INDEFINITE_WAIT);
+ }
+
+ public void testReceiveDefaultDestinationName() throws Exception {
+ doTestReceive(false, true, false, false, false, false, JmsTemplate.RECEIVE_TIMEOUT_INDEFINITE_WAIT);
+ }
+
+ public void testReceiveDestination() throws Exception {
+ doTestReceive(true, false, false, false, false, true, JmsTemplate.RECEIVE_TIMEOUT_INDEFINITE_WAIT);
+ }
+
+ public void testReceiveDestinationWithClientAcknowledge() throws Exception {
+ doTestReceive(true, false, false, true, false, false, 1000);
+ }
+
+ public void testReceiveDestinationName() throws Exception {
+ doTestReceive(false, false, false, false, false, true, 1000);
+ }
+
+ public void testReceiveDefaultDestinationWithSelector() throws Exception {
+ doTestReceive(true, true, false, false, true, true, 1000);
+ }
+
+ public void testReceiveDefaultDestinationNameWithSelector() throws Exception {
+ doTestReceive(false, true, false, false, true, true, JmsTemplate.RECEIVE_TIMEOUT_NO_WAIT);
+ }
+
+ public void testReceiveDestinationWithSelector() throws Exception {
+ doTestReceive(true, false, false, false, true, false, 1000);
+ }
+
+ public void testReceiveDestinationWithClientAcknowledgeWithSelector() throws Exception {
+ doTestReceive(true, false, false, true, true, true, JmsTemplate.RECEIVE_TIMEOUT_INDEFINITE_WAIT);
+ }
+
+ public void testReceiveDestinationNameWithSelector() throws Exception {
+ doTestReceive(false, false, false, false, true, false, JmsTemplate.RECEIVE_TIMEOUT_NO_WAIT);
+ }
+
+ public void testReceiveAndConvertDefaultDestination() throws Exception {
+ doTestReceive(true, true, true, false, false, false, 1000);
+ }
+
+ public void testReceiveAndConvertDefaultDestinationName() throws Exception {
+ doTestReceive(false, true, true, false, false, false, 1000);
+ }
+
+ public void testReceiveAndConvertDestinationName() throws Exception {
+ doTestReceive(false, false, true, false, false, true, JmsTemplate.RECEIVE_TIMEOUT_INDEFINITE_WAIT);
+ }
+
+ public void testReceiveAndConvertDestination() throws Exception {
+ doTestReceive(true, false, true, false, false, true, 1000);
+ }
+
+ public void testReceiveAndConvertDefaultDestinationWithSelector() throws Exception {
+ doTestReceive(true, true, true, false, true, true, JmsTemplate.RECEIVE_TIMEOUT_NO_WAIT);
+ }
+
+ public void testReceiveAndConvertDestinationNameWithSelector() throws Exception {
+ doTestReceive(false, false, true, false, true, true, JmsTemplate.RECEIVE_TIMEOUT_INDEFINITE_WAIT);
+ }
+
+ public void testReceiveAndConvertDestinationWithSelector() throws Exception {
+ doTestReceive(true, false, true, false, true, false, 1000);
+ }
+
+ private void doTestReceive(
+ boolean explicitDestination, boolean useDefaultDestination, boolean testConverter,
+ boolean clientAcknowledge, boolean messageSelector, boolean noLocal, long timeout)
+ throws Exception {
+
+ JmsTemplate template = createTemplate();
+ template.setConnectionFactory(mockConnectionFactory);
+
+ String destinationName = "testDestination";
+
+ if (useDefaultDestination) {
+ if (explicitDestination) {
+ template.setDefaultDestination(mockQueue);
+ }
+ else {
+ template.setDefaultDestinationName(destinationName);
+ }
+ }
+ if (noLocal) {
+ template.setPubSubNoLocal(true);
+ }
+ template.setReceiveTimeout(timeout);
+
+ mockConnection.start();
+ connectionControl.setVoidCallable(1);
+ mockConnection.close();
+ connectionControl.setVoidCallable(1);
+
+ MockControl messageConsumerControl = MockControl.createControl(MessageConsumer.class);
+ MessageConsumer mockMessageConsumer = (MessageConsumer) messageConsumerControl.getMock();
+
+ String selectorString = "selector";
+ mockSession.createConsumer(mockQueue, messageSelector ? selectorString : null);
+ sessionControl.setReturnValue(mockMessageConsumer);
+
+ if (useTransactedTemplate()) {
+ mockSession.commit();
+ sessionControl.setVoidCallable(1);
+ }
+ else if (!useTransactedSession()) {
+ mockSession.getAcknowledgeMode();
+ if (clientAcknowledge) {
+ sessionControl.setReturnValue(Session.CLIENT_ACKNOWLEDGE, 1);
+ }
+ else {
+ sessionControl.setReturnValue(Session.AUTO_ACKNOWLEDGE, 1);
+ }
+ }
+
+ mockSession.close();
+ sessionControl.setVoidCallable(1);
+
+ MockControl messageControl = MockControl.createControl(TextMessage.class);
+ TextMessage mockMessage = (TextMessage) messageControl.getMock();
+
+ if (testConverter) {
+ mockMessage.getText();
+ messageControl.setReturnValue("Hello World!");
+ }
+ if (!useTransactedSession() && clientAcknowledge) {
+ mockMessage.acknowledge();
+ messageControl.setVoidCallable(1);
+ }
+
+ sessionControl.replay();
+ connectionControl.replay();
+ messageControl.replay();
+
+ if (timeout == JmsTemplate.RECEIVE_TIMEOUT_NO_WAIT) {
+ mockMessageConsumer.receiveNoWait();
+ }
+ else if (timeout == JmsTemplate.RECEIVE_TIMEOUT_INDEFINITE_WAIT) {
+ mockMessageConsumer.receive();
+ }
+ else {
+ mockMessageConsumer.receive(timeout);
+ }
+
+ messageConsumerControl.setReturnValue(mockMessage);
+ mockMessageConsumer.close();
+ messageConsumerControl.setVoidCallable(1);
+
+ messageConsumerControl.replay();
+
+ Message message = null;
+ String textFromMessage = null;
+
+ if (useDefaultDestination) {
+ if (testConverter) {
+ textFromMessage = (String)
+ (messageSelector ? template.receiveSelectedAndConvert(selectorString) :
+ template.receiveAndConvert());
+ }
+ else {
+ message = (messageSelector ? template.receiveSelected(selectorString) : template.receive());
+ }
+ }
+ else if (explicitDestination) {
+ if (testConverter) {
+ textFromMessage = (String)
+ (messageSelector ? template.receiveSelectedAndConvert(mockQueue, selectorString) :
+ template.receiveAndConvert(mockQueue));
+ }
+ else {
+ message = (messageSelector ? template.receiveSelected(mockQueue, selectorString) :
+ template.receive(mockQueue));
+ }
+ }
+ else {
+ if (testConverter) {
+ textFromMessage = (String)
+ (messageSelector ? template.receiveSelectedAndConvert(destinationName, selectorString) :
+ template.receiveAndConvert(destinationName));
+ }
+ else {
+ message = (messageSelector ? template.receiveSelected(destinationName, selectorString) :
+ template.receive(destinationName));
+ }
+ }
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ sessionControl.verify();
+ messageConsumerControl.verify();
+ messageControl.verify();
+
+ if (testConverter) {
+ assertEquals("Message text should be equal", "Hello World!", textFromMessage);
+ }
+ else {
+ assertEquals("Messages should refer to the same object", message, mockMessage);
+ }
+ }
+
+ public void testIllegalStateException() throws Exception {
+ doTestJmsException(new javax.jms.IllegalStateException(""), org.springframework.jms.IllegalStateException.class);
+ }
+
+ public void testInvalidClientIDException() throws Exception {
+ doTestJmsException(new javax.jms.InvalidClientIDException(""), InvalidClientIDException.class);
+ }
+
+ public void testInvalidDestinationException() throws Exception {
+ doTestJmsException(new javax.jms.InvalidDestinationException(""), InvalidDestinationException.class);
+ }
+
+ public void testInvalidSelectorException() throws Exception {
+ doTestJmsException(new javax.jms.InvalidSelectorException(""), InvalidSelectorException.class);
+ }
+
+ public void testJmsSecurityException() throws Exception {
+ doTestJmsException(new javax.jms.JMSSecurityException(""), JmsSecurityException.class);
+ }
+
+ public void testMessageEOFException() throws Exception {
+ doTestJmsException(new javax.jms.MessageEOFException(""), MessageEOFException.class);
+ }
+
+ public void testMessageFormatException() throws Exception {
+ doTestJmsException(new javax.jms.MessageFormatException(""), MessageFormatException.class);
+ }
+
+ public void testMessageNotReadableException() throws Exception {
+ doTestJmsException(new javax.jms.MessageNotReadableException(""), MessageNotReadableException.class);
+ }
+
+ public void testMessageNotWriteableException() throws Exception {
+ doTestJmsException(new javax.jms.MessageNotWriteableException(""), MessageNotWriteableException.class);
+ }
+
+ public void testResourceAllocationException() throws Exception {
+ doTestJmsException(new javax.jms.ResourceAllocationException(""), ResourceAllocationException.class);
+ }
+
+ public void testTransactionInProgressException() throws Exception {
+ doTestJmsException(new javax.jms.TransactionInProgressException(""), TransactionInProgressException.class);
+ }
+
+ public void testTransactionRolledBackException() throws Exception {
+ doTestJmsException(new javax.jms.TransactionRolledBackException(""), TransactionRolledBackException.class);
+ }
+
+ public void testUncategorizedJmsException() throws Exception {
+ doTestJmsException(new javax.jms.JMSException(""), UncategorizedJmsException.class);
+ }
+
+ protected void doTestJmsException(JMSException original, Class thrownExceptionClass) throws Exception {
+ JmsTemplate template = createTemplate();
+ template.setConnectionFactory(mockConnectionFactory);
+ template.setMessageConverter(new SimpleMessageConverter());
+ String s = "Hello world";
+
+ MockControl messageProducerControl = MockControl.createControl(MessageProducer.class);
+ MessageProducer mockMessageProducer = (MessageProducer) messageProducerControl.getMock();
+ MockControl messageControl = MockControl.createControl(TextMessage.class);
+ TextMessage mockMessage = (TextMessage) messageControl.getMock();
+
+ sessionControl.reset();
+ mockSession.createProducer(mockQueue);
+ sessionControl.setReturnValue(mockMessageProducer);
+ mockSession.createTextMessage("Hello world");
+ sessionControl.setReturnValue(mockMessage);
+
+ mockMessageProducer.send(mockMessage);
+ messageProducerControl.setThrowable(original, 1);
+ mockMessageProducer.close();
+ messageProducerControl.setVoidCallable(1);
+
+ mockSession.close();
+ sessionControl.setVoidCallable(1);
+ mockConnection.close();
+ connectionControl.setVoidCallable(1);
+
+ messageProducerControl.replay();
+ sessionControl.replay();
+ connectionControl.replay();
+
+ try {
+ template.convertAndSend(mockQueue, s);
+ fail("Should have thrown JmsException");
+ }
+ catch (JmsException wrappedEx) {
+ // expected
+ assertEquals(thrownExceptionClass, wrappedEx.getClass());
+ assertEquals(original, wrappedEx.getCause());
+ }
+
+ messageProducerControl.verify();
+ sessionControl.verify();
+ connectionControl.verify();
+ connectionFactoryControl.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/core/JmsTemplateTransactedTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/core/JmsTemplateTransactedTests.java
new file mode 100644
index 00000000000..a3874798cc6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/core/JmsTemplateTransactedTests.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jms.core;
+
+/**
+ * @author Juergen Hoeller
+ * @since 06.01.2005
+ */
+public class JmsTemplateTransactedTests extends JmsTemplateTests {
+
+ protected boolean useTransactedSession() {
+ return true;
+ }
+
+ protected boolean useTransactedTemplate() {
+ return true;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/core/support/JmsGatewaySupportTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/core/support/JmsGatewaySupportTests.java
new file mode 100644
index 00000000000..1007b4c1d70
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/core/support/JmsGatewaySupportTests.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jms.core.support;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jms.ConnectionFactory;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.jms.core.JmsTemplate;
+
+/**
+ * @author Mark Pollack
+ * @since 24.9.2004
+ */
+public class JmsGatewaySupportTests extends TestCase {
+
+ public void testJmsGatewaySupportWithConnectionFactory() throws Exception {
+ MockControl connectionFactoryControl = MockControl.createControl(ConnectionFactory.class);
+ ConnectionFactory mockConnectionFactory = (ConnectionFactory) connectionFactoryControl.getMock();
+ connectionFactoryControl.replay();
+ final List test = new ArrayList();
+ JmsGatewaySupport gateway = new JmsGatewaySupport() {
+ protected void initGateway() {
+ test.add("test");
+ }
+ };
+ gateway.setConnectionFactory(mockConnectionFactory);
+ gateway.afterPropertiesSet();
+ assertEquals("Correct ConnectionFactory", mockConnectionFactory, gateway.getConnectionFactory());
+ assertEquals("Correct JmsTemplate", mockConnectionFactory, gateway.getJmsTemplate().getConnectionFactory());
+ assertEquals("initGatway called", test.size(), 1);
+ connectionFactoryControl.verify();
+
+ }
+ public void testJmsGatewaySupportWithJmsTemplate() throws Exception {
+ JmsTemplate template = new JmsTemplate();
+ final List test = new ArrayList();
+ JmsGatewaySupport gateway = new JmsGatewaySupport() {
+ protected void initGateway() {
+ test.add("test");
+ }
+ };
+ gateway.setJmsTemplate(template);
+ gateway.afterPropertiesSet();
+ assertEquals("Correct JmsTemplate", template, gateway.getJmsTemplate());
+ assertEquals("initGateway called", test.size(), 1);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/AbstractMessageListenerContainerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/AbstractMessageListenerContainerTests.java
new file mode 100644
index 00000000000..77e28962507
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/AbstractMessageListenerContainerTests.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jms.listener;
+
+import junit.framework.TestCase;
+
+import org.springframework.test.AssertThrows;
+
+/**
+ * Unit tests for the {@link AbstractMessageListenerContainer} class.
+ *
+ * @author Rick Evans
+ */
+public abstract class AbstractMessageListenerContainerTests extends TestCase {
+
+ protected abstract AbstractMessageListenerContainer getContainer();
+
+
+ public void testSettingMessageListenerToANullType() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ getContainer().setMessageListener(null);
+ }
+ }.runTest();
+ }
+
+ public void testSettingMessageListenerToAnUnsupportedType() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ getContainer().setMessageListener("Bingo");
+ }
+ }.runTest();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/SimpleMessageListenerContainerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/SimpleMessageListenerContainerTests.java
new file mode 100644
index 00000000000..d029d74b752
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/SimpleMessageListenerContainerTests.java
@@ -0,0 +1,607 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jms.listener;
+
+import java.util.HashSet;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.ExceptionListener;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageListener;
+import javax.jms.Session;
+
+import org.easymock.MockControl;
+import org.easymock.internal.AlwaysMatcher;
+
+import org.springframework.core.task.TaskExecutor;
+import org.springframework.jms.StubQueue;
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class SimpleMessageListenerContainerTests extends AbstractMessageListenerContainerTests {
+
+ private static final String DESTINATION_NAME = "foo";
+
+ private static final String EXCEPTION_MESSAGE = "This.Is.It";
+
+ private static final StubQueue QUEUE_DESTINATION = new StubQueue();
+
+
+ private SimpleMessageListenerContainer container;
+
+
+ protected void setUp() throws Exception {
+ this.container = (SimpleMessageListenerContainer) getContainer();
+ }
+
+ protected AbstractMessageListenerContainer getContainer() {
+ return new SimpleMessageListenerContainer();
+ }
+
+
+ public void testSessionTransactedModeReallyDoesDefaultToFalse() throws Exception {
+ assertFalse("The [pubSubLocal] property of SimpleMessageListenerContainer " +
+ "must default to false. Change this test (and the " +
+ "attendant Javadoc) if you have changed the default.",
+ container.isPubSubNoLocal());
+ }
+
+ public void testSettingConcurrentConsumersToZeroIsNotAllowed() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ container.setConcurrentConsumers(0);
+ container.afterPropertiesSet();
+ }
+ }.runTest();
+ }
+
+ public void testSettingConcurrentConsumersToANegativeValueIsNotAllowed() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ container.setConcurrentConsumers(-198);
+ container.afterPropertiesSet();
+ }
+ }.runTest();
+ }
+
+ public void testInitDoesNotStartTheConnectionIfAutoStartIsSetToFalse() throws Exception {
+ MockControl mockMessageConsumer = MockControl.createControl(MessageConsumer.class);
+ MessageConsumer messageConsumer = (MessageConsumer) mockMessageConsumer.getMock();
+ messageConsumer.setMessageListener(null);
+ // anon. inner class passed in, so just expect a call...
+ mockMessageConsumer.setMatcher(new AlwaysMatcher());
+ mockMessageConsumer.setVoidCallable();
+ mockMessageConsumer.replay();
+
+ MockControl mockSession = MockControl.createControl(Session.class);
+ Session session = (Session) mockSession.getMock();
+ // Queue gets created in order to create MessageConsumer for that Destination...
+ session.createQueue(DESTINATION_NAME);
+ mockSession.setReturnValue(QUEUE_DESTINATION);
+ // and then the MessageConsumer gets created...
+ session.createConsumer(QUEUE_DESTINATION, null); // no MessageSelector...
+ mockSession.setReturnValue(messageConsumer);
+ mockSession.replay();
+
+ MockControl mockConnection = MockControl.createControl(Connection.class);
+ Connection connection = (Connection) mockConnection.getMock();
+ connection.setExceptionListener(this.container);
+ mockConnection.setVoidCallable();
+ // session gets created in order to register MessageListener...
+ connection.createSession(this.container.isSessionTransacted(), this.container.getSessionAcknowledgeMode());
+ mockConnection.setReturnValue(session);
+ mockConnection.replay();
+
+ MockControl mockConnectionFactory = MockControl.createControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) mockConnectionFactory.getMock();
+ connectionFactory.createConnection();
+ mockConnectionFactory.setReturnValue(connection);
+ mockConnectionFactory.replay();
+
+ this.container.setConnectionFactory(connectionFactory);
+ this.container.setDestinationName(DESTINATION_NAME);
+
+ this.container.setMessageListener(new TestMessageListener());
+ this.container.setAutoStartup(false);
+ this.container.afterPropertiesSet();
+
+ mockMessageConsumer.verify();
+ mockSession.verify();
+ mockConnection.verify();
+ mockConnectionFactory.verify();
+ }
+
+ public void testInitStartsTheConnectionByDefault() throws Exception {
+ MockControl mockMessageConsumer = MockControl.createControl(MessageConsumer.class);
+ MessageConsumer messageConsumer = (MessageConsumer) mockMessageConsumer.getMock();
+ messageConsumer.setMessageListener(null);
+ // anon. inner class passed in, so just expect a call...
+ mockMessageConsumer.setMatcher(new AlwaysMatcher());
+ mockMessageConsumer.setVoidCallable();
+ mockMessageConsumer.replay();
+
+ MockControl mockSession = MockControl.createControl(Session.class);
+ Session session = (Session) mockSession.getMock();
+ // Queue gets created in order to create MessageConsumer for that Destination...
+ session.createQueue(DESTINATION_NAME);
+ mockSession.setReturnValue(QUEUE_DESTINATION);
+ // and then the MessageConsumer gets created...
+ session.createConsumer(QUEUE_DESTINATION, null); // no MessageSelector...
+ mockSession.setReturnValue(messageConsumer);
+ mockSession.replay();
+
+ MockControl mockConnection = MockControl.createControl(Connection.class);
+ Connection connection = (Connection) mockConnection.getMock();
+ connection.setExceptionListener(this.container);
+ mockConnection.setVoidCallable();
+ // session gets created in order to register MessageListener...
+ connection.createSession(this.container.isSessionTransacted(), this.container.getSessionAcknowledgeMode());
+ mockConnection.setReturnValue(session);
+ // and the connection is start()ed after the listener is registered...
+ connection.start();
+ mockConnection.setVoidCallable();
+ mockConnection.replay();
+
+ MockControl mockConnectionFactory = MockControl.createControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) mockConnectionFactory.getMock();
+ connectionFactory.createConnection();
+ mockConnectionFactory.setReturnValue(connection);
+ mockConnectionFactory.replay();
+
+ this.container.setConnectionFactory(connectionFactory);
+ this.container.setDestinationName(DESTINATION_NAME);
+
+ this.container.setMessageListener(new TestMessageListener());
+ this.container.afterPropertiesSet();
+
+ mockMessageConsumer.verify();
+ mockSession.verify();
+ mockConnection.verify();
+ mockConnectionFactory.verify();
+ }
+
+ public void testCorrectSessionExposedForSessionAwareMessageListenerInvocation() throws Exception {
+ final SimpleMessageConsumer messageConsumer = new SimpleMessageConsumer();
+
+ MockControl mockSession = MockControl.createControl(Session.class);
+ final Session session = (Session) mockSession.getMock();
+ // Queue gets created in order to create MessageConsumer for that Destination...
+ session.createQueue(DESTINATION_NAME);
+ mockSession.setReturnValue(QUEUE_DESTINATION);
+ // and then the MessageConsumer gets created...
+ session.createConsumer(QUEUE_DESTINATION, null); // no MessageSelector...
+ mockSession.setReturnValue(messageConsumer);
+ // an exception is thrown, so the rollback logic is being applied here...
+ session.getTransacted();
+ mockSession.setReturnValue(false);
+ session.getAcknowledgeMode();
+ mockSession.setReturnValue(Session.AUTO_ACKNOWLEDGE);
+ mockSession.replay();
+
+ MockControl mockConnection = MockControl.createControl(Connection.class);
+ Connection connection = (Connection) mockConnection.getMock();
+ connection.setExceptionListener(this.container);
+ mockConnection.setVoidCallable();
+ // session gets created in order to register MessageListener...
+ connection.createSession(this.container.isSessionTransacted(), this.container.getSessionAcknowledgeMode());
+ mockConnection.setReturnValue(session);
+ // and the connection is start()ed after the listener is registered...
+ connection.start();
+ mockConnection.setVoidCallable();
+ mockConnection.replay();
+
+ MockControl mockConnectionFactory = MockControl.createControl(ConnectionFactory.class);
+ final ConnectionFactory connectionFactory = (ConnectionFactory) mockConnectionFactory.getMock();
+ connectionFactory.createConnection();
+ mockConnectionFactory.setReturnValue(connection);
+ mockConnectionFactory.replay();
+
+ final HashSet failure = new HashSet();
+
+ this.container.setConnectionFactory(connectionFactory);
+ this.container.setDestinationName(DESTINATION_NAME);
+ this.container.setMessageListener(new SessionAwareMessageListener() {
+ public void onMessage(Message message, Session sess) {
+ try {
+ // Check correct Session passed into SessionAwareMessageListener.
+ assertSame(sess, session);
+ }
+ catch (Throwable ex) {
+ failure.add("MessageListener execution failed: " + ex);
+ }
+ }
+ });
+
+ this.container.afterPropertiesSet();
+
+ MockControl mockMessage = MockControl.createControl(Message.class);
+ final Message message = (Message) mockMessage.getMock();
+ mockMessage.replay();
+ messageConsumer.sendMessage(message);
+
+ if (!failure.isEmpty()) {
+ fail(failure.iterator().next().toString());
+ }
+
+ mockMessage.verify();
+ mockSession.verify();
+ mockConnection.verify();
+ mockConnectionFactory.verify();
+ }
+
+ public void testTaskExecutorCorrectlyInvokedWhenSpecified() throws Exception {
+ final SimpleMessageConsumer messageConsumer = new SimpleMessageConsumer();
+
+ MockControl mockSession = MockControl.createControl(Session.class);
+ final Session session = (Session) mockSession.getMock();
+ session.createQueue(DESTINATION_NAME);
+ mockSession.setReturnValue(QUEUE_DESTINATION);
+ session.createConsumer(QUEUE_DESTINATION, null); // no MessageSelector...
+ mockSession.setReturnValue(messageConsumer);
+ session.getTransacted();
+ mockSession.setReturnValue(false);
+ session.getAcknowledgeMode();
+ mockSession.setReturnValue(Session.AUTO_ACKNOWLEDGE);
+ mockSession.replay();
+
+ MockControl mockConnection = MockControl.createControl(Connection.class);
+ Connection connection = (Connection) mockConnection.getMock();
+ connection.setExceptionListener(this.container);
+ mockConnection.setVoidCallable();
+ connection.createSession(this.container.isSessionTransacted(), this.container.getSessionAcknowledgeMode());
+ mockConnection.setReturnValue(session);
+ connection.start();
+ mockConnection.setVoidCallable();
+ mockConnection.replay();
+
+ MockControl mockConnectionFactory = MockControl.createControl(ConnectionFactory.class);
+ final ConnectionFactory connectionFactory = (ConnectionFactory) mockConnectionFactory.getMock();
+ connectionFactory.createConnection();
+ mockConnectionFactory.setReturnValue(connection);
+ mockConnectionFactory.replay();
+
+ final TestMessageListener listener = new TestMessageListener();
+
+ this.container.setConnectionFactory(connectionFactory);
+ this.container.setDestinationName(DESTINATION_NAME);
+ this.container.setMessageListener(listener);
+ this.container.setTaskExecutor(new TaskExecutor() {
+ public void execute(Runnable task) {
+ listener.executorInvoked = true;
+ assertFalse(listener.listenerInvoked);
+ task.run();
+ assertTrue(listener.listenerInvoked);
+ }
+ });
+ this.container.afterPropertiesSet();
+
+ MockControl mockMessage = MockControl.createControl(Message.class);
+ final Message message = (Message) mockMessage.getMock();
+ mockMessage.replay();
+ messageConsumer.sendMessage(message);
+
+ assertTrue(listener.executorInvoked);
+ assertTrue(listener.listenerInvoked);
+ mockMessage.verify();
+ mockSession.verify();
+ mockConnection.verify();
+ mockConnectionFactory.verify();
+ }
+
+ public void testRegisteredExceptionListenerIsInvokedOnException() throws Exception {
+ final SimpleMessageConsumer messageConsumer = new SimpleMessageConsumer();
+
+ MockControl mockSession = MockControl.createControl(Session.class);
+ Session session = (Session) mockSession.getMock();
+ // Queue gets created in order to create MessageConsumer for that Destination...
+ session.createQueue(DESTINATION_NAME);
+ mockSession.setReturnValue(QUEUE_DESTINATION);
+ // and then the MessageConsumer gets created...
+ session.createConsumer(QUEUE_DESTINATION, null); // no MessageSelector...
+ mockSession.setReturnValue(messageConsumer);
+ // an exception is thrown, so the rollback logic is being applied here...
+ session.getTransacted();
+ mockSession.setReturnValue(false);
+ mockSession.replay();
+
+ MockControl mockConnection = MockControl.createControl(Connection.class);
+ Connection connection = (Connection) mockConnection.getMock();
+ connection.setExceptionListener(this.container);
+ mockConnection.setVoidCallable();
+ // session gets created in order to register MessageListener...
+ connection.createSession(this.container.isSessionTransacted(), this.container.getSessionAcknowledgeMode());
+ mockConnection.setReturnValue(session);
+ // and the connection is start()ed after the listener is registered...
+ connection.start();
+ mockConnection.setVoidCallable();
+ mockConnection.replay();
+
+ MockControl mockConnectionFactory = MockControl.createControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) mockConnectionFactory.getMock();
+ connectionFactory.createConnection();
+ mockConnectionFactory.setReturnValue(connection);
+ mockConnectionFactory.replay();
+
+ final JMSException theException = new JMSException(EXCEPTION_MESSAGE);
+
+ this.container.setConnectionFactory(connectionFactory);
+ this.container.setDestinationName(DESTINATION_NAME);
+ this.container.setMessageListener(new SessionAwareMessageListener() {
+ public void onMessage(Message message, Session session) throws JMSException {
+ throw theException;
+ }
+ });
+
+ MockControl mockExceptionListener = MockControl.createControl(ExceptionListener.class);
+ ExceptionListener exceptionListener = (ExceptionListener) mockExceptionListener.getMock();
+ exceptionListener.onException(theException);
+ mockExceptionListener.setVoidCallable();
+ mockExceptionListener.replay();
+
+ this.container.setExceptionListener(exceptionListener);
+ this.container.afterPropertiesSet();
+
+ // manually trigger an Exception with the above bad MessageListener...
+ MockControl mockMessage = MockControl.createControl(Message.class);
+ final Message message = (Message) mockMessage.getMock();
+ mockMessage.replay();
+
+ // a Throwable from a MessageListener MUST simply be swallowed...
+ messageConsumer.sendMessage(message);
+
+ mockExceptionListener.verify();
+ mockMessage.verify();
+ mockSession.verify();
+ mockConnection.verify();
+ mockConnectionFactory.verify();
+ }
+
+ public void testNoRollbackOccursIfSessionIsNotTransactedAndThatExceptionsDo_NOT_Propagate() throws Exception {
+ final SimpleMessageConsumer messageConsumer = new SimpleMessageConsumer();
+
+ MockControl mockSession = MockControl.createControl(Session.class);
+ Session session = (Session) mockSession.getMock();
+ // Queue gets created in order to create MessageConsumer for that Destination...
+ session.createQueue(DESTINATION_NAME);
+ mockSession.setReturnValue(QUEUE_DESTINATION);
+ // and then the MessageConsumer gets created...
+ session.createConsumer(QUEUE_DESTINATION, null); // no MessageSelector...
+ mockSession.setReturnValue(messageConsumer);
+ // an exception is thrown, so the rollback logic is being applied here...
+ session.getTransacted();
+ mockSession.setReturnValue(false);
+ mockSession.replay();
+
+ MockControl mockConnection = MockControl.createControl(Connection.class);
+ Connection connection = (Connection) mockConnection.getMock();
+ connection.setExceptionListener(this.container);
+ mockConnection.setVoidCallable();
+ // session gets created in order to register MessageListener...
+ connection.createSession(this.container.isSessionTransacted(), this.container.getSessionAcknowledgeMode());
+ mockConnection.setReturnValue(session);
+ // and the connection is start()ed after the listener is registered...
+ connection.start();
+ mockConnection.setVoidCallable();
+ mockConnection.replay();
+
+ MockControl mockConnectionFactory = MockControl.createControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) mockConnectionFactory.getMock();
+ connectionFactory.createConnection();
+ mockConnectionFactory.setReturnValue(connection);
+ mockConnectionFactory.replay();
+
+ this.container.setConnectionFactory(connectionFactory);
+ this.container.setDestinationName(DESTINATION_NAME);
+ this.container.setMessageListener(new MessageListener() {
+ public void onMessage(Message message) {
+ throw new UnsupportedOperationException();
+ }
+ });
+ this.container.afterPropertiesSet();
+
+ // manually trigger an Exception with the above bad MessageListener...
+ MockControl mockMessage = MockControl.createControl(Message.class);
+ final Message message = (Message) mockMessage.getMock();
+ mockMessage.replay();
+
+ // a Throwable from a MessageListener MUST simply be swallowed...
+ messageConsumer.sendMessage(message);
+
+ mockMessage.verify();
+ mockSession.verify();
+ mockConnection.verify();
+ mockConnectionFactory.verify();
+ }
+
+ public void testTransactedSessionsGetRollbackLogicAppliedAndThatExceptionsStillDo_NOT_Propagate() throws Exception {
+ this.container.setSessionTransacted(true);
+
+ final SimpleMessageConsumer messageConsumer = new SimpleMessageConsumer();
+
+ MockControl mockSession = MockControl.createControl(Session.class);
+ Session session = (Session) mockSession.getMock();
+ // Queue gets created in order to create MessageConsumer for that Destination...
+ session.createQueue(DESTINATION_NAME);
+ mockSession.setReturnValue(QUEUE_DESTINATION);
+ // and then the MessageConsumer gets created...
+ session.createConsumer(QUEUE_DESTINATION, null); // no MessageSelector...
+ mockSession.setReturnValue(messageConsumer);
+ // an exception is thrown, so the rollback logic is being applied here...
+ session.getTransacted();
+ mockSession.setReturnValue(true);
+ // Session is rolled back 'cos it is transacted...
+ session.rollback();
+ mockSession.setVoidCallable();
+ mockSession.replay();
+
+ MockControl mockConnection = MockControl.createControl(Connection.class);
+ Connection connection = (Connection) mockConnection.getMock();
+ connection.setExceptionListener(this.container);
+ mockConnection.setVoidCallable();
+ // session gets created in order to register MessageListener...
+ connection.createSession(this.container.isSessionTransacted(), this.container.getSessionAcknowledgeMode());
+ mockConnection.setReturnValue(session);
+ // and the connection is start()ed after the listener is registered...
+ connection.start();
+ mockConnection.setVoidCallable();
+ mockConnection.replay();
+
+ MockControl mockConnectionFactory = MockControl.createControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) mockConnectionFactory.getMock();
+ connectionFactory.createConnection();
+ mockConnectionFactory.setReturnValue(connection);
+ mockConnectionFactory.replay();
+
+ this.container.setConnectionFactory(connectionFactory);
+ this.container.setDestinationName(DESTINATION_NAME);
+ this.container.setMessageListener(new MessageListener() {
+ public void onMessage(Message message) {
+ throw new UnsupportedOperationException();
+ }
+ });
+ this.container.afterPropertiesSet();
+
+ // manually trigger an Exception with the above bad MessageListener...
+ MockControl mockMessage = MockControl.createControl(Message.class);
+ final Message message = (Message) mockMessage.getMock();
+ mockMessage.replay();
+
+ // a Throwable from a MessageListener MUST simply be swallowed...
+ messageConsumer.sendMessage(message);
+
+ mockMessage.verify();
+ mockSession.verify();
+ mockConnection.verify();
+ mockConnectionFactory.verify();
+ }
+
+ public void testDestroyClosesConsumersSessionsAndConnectionInThatOrder() throws Exception {
+ MockControl mockMessageConsumer = MockControl.createControl(MessageConsumer.class);
+ MessageConsumer messageConsumer = (MessageConsumer) mockMessageConsumer.getMock();
+ messageConsumer.setMessageListener(null);
+ // anon. inner class passed in, so just expect a call...
+ mockMessageConsumer.setMatcher(new AlwaysMatcher());
+ mockMessageConsumer.setVoidCallable();
+ // closing down...
+ messageConsumer.close();
+ mockMessageConsumer.setVoidCallable();
+ mockMessageConsumer.replay();
+
+ MockControl mockSession = MockControl.createControl(Session.class);
+ Session session = (Session) mockSession.getMock();
+ // Queue gets created in order to create MessageConsumer for that Destination...
+ session.createQueue(DESTINATION_NAME);
+ mockSession.setReturnValue(QUEUE_DESTINATION);
+ // and then the MessageConsumer gets created...
+ session.createConsumer(QUEUE_DESTINATION, null); // no MessageSelector...
+ mockSession.setReturnValue(messageConsumer);
+ // closing down...
+ session.close();
+ mockSession.setVoidCallable();
+ mockSession.replay();
+
+ MockControl mockConnection = MockControl.createControl(Connection.class);
+ Connection connection = (Connection) mockConnection.getMock();
+ connection.setExceptionListener(this.container);
+ mockConnection.setVoidCallable();
+ // session gets created in order to register MessageListener...
+ connection.createSession(this.container.isSessionTransacted(), this.container.getSessionAcknowledgeMode());
+ mockConnection.setReturnValue(session);
+ // and the connection is start()ed after the listener is registered...
+ connection.start();
+ mockConnection.setVoidCallable();
+ // closing down...
+ connection.close();
+ mockConnection.setVoidCallable();
+ mockConnection.replay();
+
+ MockControl mockConnectionFactory = MockControl.createControl(ConnectionFactory.class);
+ ConnectionFactory connectionFactory = (ConnectionFactory) mockConnectionFactory.getMock();
+ connectionFactory.createConnection();
+ mockConnectionFactory.setReturnValue(connection);
+ mockConnectionFactory.replay();
+
+ this.container.setConnectionFactory(connectionFactory);
+ this.container.setDestinationName(DESTINATION_NAME);
+
+ this.container.setMessageListener(new TestMessageListener());
+ this.container.afterPropertiesSet();
+ this.container.destroy();
+
+ mockMessageConsumer.verify();
+ mockSession.verify();
+ mockConnection.verify();
+ mockConnectionFactory.verify();
+ }
+
+
+ private static class TestMessageListener implements MessageListener {
+
+ public boolean executorInvoked = false;
+
+ public boolean listenerInvoked = false;
+
+ public void onMessage(Message message) {
+ this.listenerInvoked = true;
+ }
+ }
+
+
+ private static class SimpleMessageConsumer implements MessageConsumer {
+
+ private MessageListener messageListener;
+
+ public void sendMessage(Message message) throws JMSException {
+ this.messageListener.onMessage(message);
+ }
+
+ public String getMessageSelector() throws JMSException {
+ throw new UnsupportedOperationException();
+ }
+
+ public MessageListener getMessageListener() throws JMSException {
+ return this.messageListener;
+ }
+
+ public void setMessageListener(MessageListener messageListener) throws JMSException {
+ this.messageListener = messageListener;
+ }
+
+ public Message receive() throws JMSException {
+ throw new UnsupportedOperationException();
+ }
+
+ public Message receive(long l) throws JMSException {
+ throw new UnsupportedOperationException();
+ }
+
+ public Message receiveNoWait() throws JMSException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void close() throws JMSException {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/MessageContentsDelegate.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/MessageContentsDelegate.java
new file mode 100644
index 00000000000..6686a8e53a3
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/MessageContentsDelegate.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jms.listener.adapter;
+
+import java.util.Map;
+
+/**
+ * See the MessageListenerAdapterTests class for usage.
+ *
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public interface MessageContentsDelegate {
+
+ void handleMessage(CharSequence message);
+
+ void handleMessage(Map message);
+
+ void handleMessage(byte[] message);
+
+ void handleMessage(Number message);
+
+ void handleMessage(Object message);
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/MessageDelegate.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/MessageDelegate.java
new file mode 100644
index 00000000000..ecff85c7bc5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/MessageDelegate.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jms.listener.adapter;
+
+import javax.jms.BytesMessage;
+import javax.jms.MapMessage;
+import javax.jms.ObjectMessage;
+import javax.jms.TextMessage;
+
+/**
+ * See the MessageListenerAdapterTests class for usage.
+ *
+ * @author Rick Evans
+ */
+public interface MessageDelegate {
+
+ void handleMessage(TextMessage message);
+
+ void handleMessage(MapMessage message);
+
+ void handleMessage(BytesMessage message);
+
+ void handleMessage(ObjectMessage message);
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/MessageListenerAdapter102Tests.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/MessageListenerAdapter102Tests.java
new file mode 100644
index 00000000000..f9e44d1b6a3
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/MessageListenerAdapter102Tests.java
@@ -0,0 +1,432 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jms.listener.adapter;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+import org.springframework.jms.support.converter.SimpleMessageConverter102;
+import org.springframework.test.AssertThrows;
+
+import javax.jms.*;
+
+/**
+ * Unit tests for the {@link MessageListenerAdapter102} class.
+ *
+ * @author Rick Evans
+ */
+public final class MessageListenerAdapter102Tests extends TestCase {
+
+ private static final String TEXT = "The Runaways";
+ private static final String CORRELATION_ID = "100";
+ private static final String RESPONSE_TEXT = "Old Lace";
+
+
+ public void testWithMessageContentsDelegateForBytesMessage() throws Exception {
+
+ MockControl mockBytesMessage = MockControl.createControl(BytesMessage.class);
+ BytesMessage bytesMessage = (BytesMessage) mockBytesMessage.getMock();
+ // BytesMessage contents must be unwrapped...
+ bytesMessage.readBytes(null);
+ mockBytesMessage.setMatcher(MockControl.ALWAYS_MATCHER);
+ mockBytesMessage.setReturnValue(TEXT.getBytes().length);
+ mockBytesMessage.replay();
+
+ MockControl mockDelegate = MockControl.createControl(MessageContentsDelegate.class);
+ MessageContentsDelegate delegate = (MessageContentsDelegate) mockDelegate.getMock();
+ delegate.handleMessage(TEXT.getBytes());
+ mockDelegate.setMatcher(MockControl.ALWAYS_MATCHER);
+ mockDelegate.setVoidCallable();
+ mockDelegate.replay();
+
+ MessageListenerAdapter102 adapter = new MessageListenerAdapter102(delegate);
+ adapter.onMessage(bytesMessage);
+
+ mockDelegate.verify();
+ mockBytesMessage.verify();
+ }
+
+ public void testWithMessageDelegate() throws Exception {
+
+ MockControl mockTextMessage = MockControl.createControl(TextMessage.class);
+ TextMessage textMessage = (TextMessage) mockTextMessage.getMock();
+ mockTextMessage.replay();
+
+ MockControl mockDelegate = MockControl.createControl(MessageDelegate.class);
+ MessageDelegate delegate = (MessageDelegate) mockDelegate.getMock();
+ delegate.handleMessage(textMessage);
+ mockDelegate.setVoidCallable();
+ mockDelegate.replay();
+
+ MessageListenerAdapter102 adapter = new MessageListenerAdapter102(delegate);
+ // we DON'T want the default SimpleMessageConversion happening...
+ adapter.setMessageConverter(null);
+ adapter.onMessage(textMessage);
+
+ mockDelegate.verify();
+ mockTextMessage.verify();
+ }
+
+ public void testThatTheDefaultMessageConverterisIndeedTheSimpleMessageConverter102() throws Exception {
+ MessageListenerAdapter102 adapter = new MessageListenerAdapter102();
+ assertNotNull("The default [MessageConverter] must never be null.", adapter.getMessageConverter());
+ assertTrue("The default [MessageConverter] must be of the type [SimpleMessageConverter102]; if you've just changed it, then change this test to reflect your change.", adapter.getMessageConverter() instanceof SimpleMessageConverter102);
+ }
+
+ public void testWithResponsiveMessageDelegate_DoesNotSendReturnTextMessageIfNoSessionSupplied() throws Exception {
+
+ MockControl mockTextMessage = MockControl.createControl(TextMessage.class);
+ TextMessage textMessage = (TextMessage) mockTextMessage.getMock();
+ mockTextMessage.replay();
+
+ MockControl mockDelegate = MockControl.createControl(ResponsiveMessageDelegate.class);
+ ResponsiveMessageDelegate delegate = (ResponsiveMessageDelegate) mockDelegate.getMock();
+ delegate.handleMessage(textMessage);
+ mockDelegate.setReturnValue(TEXT);
+ mockDelegate.replay();
+
+ MessageListenerAdapter102 adapter = new MessageListenerAdapter102(delegate);
+ // we DON'T want the default SimpleMessageConversion happening...
+ adapter.setMessageConverter(null);
+ adapter.onMessage(textMessage);
+
+ mockDelegate.verify();
+ mockTextMessage.verify();
+ }
+
+ public void testWithResponsiveMessageDelegateWithDefaultDestination_SendsReturnTextMessageWhenSessionSuppliedForQueue() throws Exception {
+
+ MockControl mockDestination = MockControl.createControl(Queue.class);
+ Queue destination = (Queue) mockDestination.getMock();
+ mockDestination.replay();
+
+ MockControl mockSentTextMessage = MockControl.createControl(TextMessage.class);
+ TextMessage sentTextMessage = (TextMessage) mockSentTextMessage.getMock();
+ // correlation ID is queried when response is being created...
+ sentTextMessage.getJMSCorrelationID();
+ mockSentTextMessage.setReturnValue(CORRELATION_ID);
+ // Reply-To is queried when response is being created...
+ sentTextMessage.getJMSReplyTo();
+ mockSentTextMessage.setReturnValue(null); // we want to fall back to the default...
+ mockSentTextMessage.replay();
+
+ MockControl mockResponseTextMessage = MockControl.createControl(TextMessage.class);
+ TextMessage responseTextMessage = (TextMessage) mockResponseTextMessage.getMock();
+ responseTextMessage.setJMSCorrelationID(CORRELATION_ID);
+ mockResponseTextMessage.setVoidCallable();
+ mockResponseTextMessage.replay();
+
+ MockControl mockQueueSender = MockControl.createControl(QueueSender.class);
+ QueueSender queueSender = (QueueSender) mockQueueSender.getMock();
+ queueSender.send(responseTextMessage);
+ mockQueueSender.setVoidCallable();
+ queueSender.close();
+ mockQueueSender.setVoidCallable();
+ mockQueueSender.replay();
+
+ MockControl mockSession = MockControl.createControl(QueueSession.class);
+ QueueSession session = (QueueSession) mockSession.getMock();
+ session.createTextMessage(RESPONSE_TEXT);
+ mockSession.setReturnValue(responseTextMessage);
+ session.createSender(destination);
+ mockSession.setReturnValue(queueSender);
+ mockSession.replay();
+
+ MockControl mockDelegate = MockControl.createControl(ResponsiveMessageDelegate.class);
+ ResponsiveMessageDelegate delegate = (ResponsiveMessageDelegate) mockDelegate.getMock();
+ delegate.handleMessage(sentTextMessage);
+ mockDelegate.setReturnValue(RESPONSE_TEXT);
+ mockDelegate.replay();
+
+ MessageListenerAdapter102 adapter = new MessageListenerAdapter102(delegate) {
+ protected Object extractMessage(Message message) {
+ return message;
+ }
+ };
+ adapter.setDefaultResponseDestination(destination);
+ adapter.onMessage(sentTextMessage, session);
+
+ mockDelegate.verify();
+ mockSentTextMessage.verify();
+ mockResponseTextMessage.verify();
+ mockSession.verify();
+ mockDestination.verify();
+ mockQueueSender.verify();
+ }
+
+ public void testWithResponsiveMessageDelegateWithDefaultDestination_SendsReturnTextMessageWhenSessionSuppliedForTopic() throws Exception {
+
+ MockControl mockDestination = MockControl.createControl(Topic.class);
+ Topic destination = (Topic) mockDestination.getMock();
+ mockDestination.replay();
+
+ MockControl mockSentTextMessage = MockControl.createControl(TextMessage.class);
+ TextMessage sentTextMessage = (TextMessage) mockSentTextMessage.getMock();
+ // correlation ID is queried when response is being created...
+ sentTextMessage.getJMSCorrelationID();
+ mockSentTextMessage.setReturnValue(CORRELATION_ID);
+ // Reply-To is queried when response is being created...
+ sentTextMessage.getJMSReplyTo();
+ mockSentTextMessage.setReturnValue(null); // we want to fall back to the default...
+ mockSentTextMessage.replay();
+
+ MockControl mockResponseTextMessage = MockControl.createControl(TextMessage.class);
+ TextMessage responseTextMessage = (TextMessage) mockResponseTextMessage.getMock();
+ responseTextMessage.setJMSCorrelationID(CORRELATION_ID);
+ mockResponseTextMessage.setVoidCallable();
+ mockResponseTextMessage.replay();
+
+ MockControl mockTopicPublisher = MockControl.createControl(TopicPublisher.class);
+ TopicPublisher topicPublisher = (TopicPublisher) mockTopicPublisher.getMock();
+ topicPublisher.publish(responseTextMessage);
+ mockTopicPublisher.setVoidCallable();
+ topicPublisher.close();
+ mockTopicPublisher.setVoidCallable();
+ mockTopicPublisher.replay();
+
+ MockControl mockSession = MockControl.createControl(TopicSession.class);
+ TopicSession session = (TopicSession) mockSession.getMock();
+ session.createTextMessage(RESPONSE_TEXT);
+ mockSession.setReturnValue(responseTextMessage);
+ session.createPublisher(destination);
+ mockSession.setReturnValue(topicPublisher);
+ mockSession.replay();
+
+ MockControl mockDelegate = MockControl.createControl(ResponsiveMessageDelegate.class);
+ ResponsiveMessageDelegate delegate = (ResponsiveMessageDelegate) mockDelegate.getMock();
+ delegate.handleMessage(sentTextMessage);
+ mockDelegate.setReturnValue(RESPONSE_TEXT);
+ mockDelegate.replay();
+
+ MessageListenerAdapter102 adapter = new MessageListenerAdapter102(delegate) {
+ protected Object extractMessage(Message message) {
+ return message;
+ }
+ };
+ adapter.setDefaultResponseDestination(destination);
+ adapter.onMessage(sentTextMessage, session);
+
+ mockDelegate.verify();
+ mockSentTextMessage.verify();
+ mockResponseTextMessage.verify();
+ mockSession.verify();
+ mockDestination.verify();
+ mockTopicPublisher.verify();
+ }
+
+ public void testWithResponsiveMessageDelegateNoDefaultDestination_SendsReturnTextMessageWhenSessionSupplied() throws Exception {
+
+ MockControl mockDestination = MockControl.createControl(Queue.class);
+ Queue destination = (Queue) mockDestination.getMock();
+ mockDestination.replay();
+
+ MockControl mockSentTextMessage = MockControl.createControl(TextMessage.class);
+ TextMessage sentTextMessage = (TextMessage) mockSentTextMessage.getMock();
+ // correlation ID is queried when response is being created...
+ sentTextMessage.getJMSCorrelationID();
+ mockSentTextMessage.setReturnValue(CORRELATION_ID);
+ // Reply-To is queried when response is being created...
+ sentTextMessage.getJMSReplyTo();
+ mockSentTextMessage.setReturnValue(destination);
+ mockSentTextMessage.replay();
+
+ MockControl mockResponseTextMessage = MockControl.createControl(TextMessage.class);
+ TextMessage responseTextMessage = (TextMessage) mockResponseTextMessage.getMock();
+ responseTextMessage.setJMSCorrelationID(CORRELATION_ID);
+ mockResponseTextMessage.setVoidCallable();
+ mockResponseTextMessage.replay();
+
+ MockControl mockQueueSender = MockControl.createControl(QueueSender.class);
+ QueueSender queueSender = (QueueSender) mockQueueSender.getMock();
+ queueSender.send(responseTextMessage);
+ mockQueueSender.setVoidCallable();
+ queueSender.close();
+ mockQueueSender.setVoidCallable();
+ mockQueueSender.replay();
+
+ MockControl mockSession = MockControl.createControl(QueueSession.class);
+ QueueSession session = (QueueSession) mockSession.getMock();
+ session.createTextMessage(RESPONSE_TEXT);
+ mockSession.setReturnValue(responseTextMessage);
+ session.createSender(destination);
+ mockSession.setReturnValue(queueSender);
+ mockSession.replay();
+
+ MockControl mockDelegate = MockControl.createControl(ResponsiveMessageDelegate.class);
+ ResponsiveMessageDelegate delegate = (ResponsiveMessageDelegate) mockDelegate.getMock();
+ delegate.handleMessage(sentTextMessage);
+ mockDelegate.setReturnValue(RESPONSE_TEXT);
+ mockDelegate.replay();
+
+ MessageListenerAdapter102 adapter = new MessageListenerAdapter102(delegate) {
+ protected Object extractMessage(Message message) {
+ return message;
+ }
+ };
+ adapter.onMessage(sentTextMessage, session);
+
+ mockDelegate.verify();
+ mockSentTextMessage.verify();
+ mockResponseTextMessage.verify();
+ mockSession.verify();
+ mockDestination.verify();
+ mockQueueSender.verify();
+ }
+
+ public void testWithResponsiveMessageDelegateNoDefaultDestinationAndNoReplyToDestination_SendsReturnTextMessageWhenSessionSupplied() throws Exception {
+
+ MockControl mockSentTextMessage = MockControl.createControl(TextMessage.class);
+ final TextMessage sentTextMessage = (TextMessage) mockSentTextMessage.getMock();
+ // correlation ID is queried when response is being created...
+ sentTextMessage.getJMSCorrelationID();
+ mockSentTextMessage.setReturnValue(CORRELATION_ID);
+ // Reply-To is queried when response is being created...
+ sentTextMessage.getJMSReplyTo();
+ mockSentTextMessage.setReturnValue(null);
+ mockSentTextMessage.replay();
+
+ MockControl mockResponseTextMessage = MockControl.createControl(TextMessage.class);
+ TextMessage responseTextMessage = (TextMessage) mockResponseTextMessage.getMock();
+ responseTextMessage.setJMSCorrelationID(CORRELATION_ID);
+ mockResponseTextMessage.setVoidCallable();
+ mockResponseTextMessage.replay();
+
+ MockControl mockSession = MockControl.createControl(QueueSession.class);
+ final QueueSession session = (QueueSession) mockSession.getMock();
+ session.createTextMessage(RESPONSE_TEXT);
+ mockSession.setReturnValue(responseTextMessage);
+ mockSession.replay();
+
+ MockControl mockDelegate = MockControl.createControl(ResponsiveMessageDelegate.class);
+ ResponsiveMessageDelegate delegate = (ResponsiveMessageDelegate) mockDelegate.getMock();
+ delegate.handleMessage(sentTextMessage);
+ mockDelegate.setReturnValue(RESPONSE_TEXT);
+ mockDelegate.replay();
+
+ final MessageListenerAdapter102 adapter = new MessageListenerAdapter102(delegate) {
+ protected Object extractMessage(Message message) {
+ return message;
+ }
+ };
+ new AssertThrows(InvalidDestinationException.class) {
+ public void test() throws Exception {
+ adapter.onMessage(sentTextMessage, session);
+ }
+ }.runTest();
+
+ mockDelegate.verify();
+ mockSentTextMessage.verify();
+ mockResponseTextMessage.verify();
+ mockSession.verify();
+ }
+
+ public void testWithResponsiveMessageDelegateNoDefaultDestination_SendsReturnTextMessageWhenSessionSupplied_AndSendingThrowsJMSException() throws Exception {
+
+ MockControl mockDestination = MockControl.createControl(Queue.class);
+ Queue destination = (Queue) mockDestination.getMock();
+ mockDestination.replay();
+
+ MockControl mockSentTextMessage = MockControl.createControl(TextMessage.class);
+ final TextMessage sentTextMessage = (TextMessage) mockSentTextMessage.getMock();
+ // correlation ID is queried when response is being created...
+ sentTextMessage.getJMSCorrelationID();
+ mockSentTextMessage.setReturnValue(CORRELATION_ID);
+ // Reply-To is queried when response is being created...
+ sentTextMessage.getJMSReplyTo();
+ mockSentTextMessage.setReturnValue(destination);
+ mockSentTextMessage.replay();
+
+ MockControl mockResponseTextMessage = MockControl.createControl(TextMessage.class);
+ TextMessage responseTextMessage = (TextMessage) mockResponseTextMessage.getMock();
+ responseTextMessage.setJMSCorrelationID(CORRELATION_ID);
+ mockResponseTextMessage.setVoidCallable();
+ mockResponseTextMessage.replay();
+
+ MockControl mockQueueSender = MockControl.createControl(QueueSender.class);
+ QueueSender queueSender = (QueueSender) mockQueueSender.getMock();
+ queueSender.send(responseTextMessage);
+ mockQueueSender.setThrowable(new JMSException("Dow!"));
+ // ensure that regardless of a JMSException the producer is closed...
+ queueSender.close();
+ mockQueueSender.setVoidCallable();
+ mockQueueSender.replay();
+
+ MockControl mockSession = MockControl.createControl(QueueSession.class);
+ final QueueSession session = (QueueSession) mockSession.getMock();
+ session.createTextMessage(RESPONSE_TEXT);
+ mockSession.setReturnValue(responseTextMessage);
+ session.createSender(destination);
+ mockSession.setReturnValue(queueSender);
+ mockSession.replay();
+
+ MockControl mockDelegate = MockControl.createControl(ResponsiveMessageDelegate.class);
+ ResponsiveMessageDelegate delegate = (ResponsiveMessageDelegate) mockDelegate.getMock();
+ delegate.handleMessage(sentTextMessage);
+ mockDelegate.setReturnValue(RESPONSE_TEXT);
+ mockDelegate.replay();
+
+ final MessageListenerAdapter102 adapter = new MessageListenerAdapter102(delegate) {
+ protected Object extractMessage(Message message) {
+ return message;
+ }
+ };
+ new AssertThrows(JMSException.class) {
+ public void test() throws Exception {
+ adapter.onMessage(sentTextMessage, session);
+ }
+ }.runTest();
+
+ mockDelegate.verify();
+ mockSentTextMessage.verify();
+ mockResponseTextMessage.verify();
+ mockSession.verify();
+ mockDestination.verify();
+ mockQueueSender.verify();
+ }
+
+ public void testWithResponsiveMessageDelegateDoesNotSendReturnTextMessageWhenSessionSupplied_AndListenerMethodThrowsException() throws Exception {
+
+ MockControl mockSentTextMessage = MockControl.createControl(TextMessage.class);
+ final TextMessage sentTextMessage = (TextMessage) mockSentTextMessage.getMock();
+ mockSentTextMessage.replay();
+
+ MockControl mockSession = MockControl.createControl(QueueSession.class);
+ final QueueSession session = (QueueSession) mockSession.getMock();
+ mockSession.replay();
+
+ MockControl mockDelegate = MockControl.createControl(ResponsiveMessageDelegate.class);
+ ResponsiveMessageDelegate delegate = (ResponsiveMessageDelegate) mockDelegate.getMock();
+ delegate.handleMessage(sentTextMessage);
+ mockDelegate.setThrowable(new IllegalArgumentException("Dow!"));
+ mockDelegate.replay();
+
+ final MessageListenerAdapter102 adapter = new MessageListenerAdapter102(delegate) {
+ protected Object extractMessage(Message message) {
+ return message;
+ }
+ };
+ new AssertThrows(ListenerExecutionFailedException.class) {
+ public void test() throws Exception {
+ adapter.onMessage(sentTextMessage, session);
+ }
+ }.runTest();
+
+ mockDelegate.verify();
+ mockSentTextMessage.verify();
+ mockSession.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/MessageListenerAdapterTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/MessageListenerAdapterTests.java
new file mode 100644
index 00000000000..b66d07a9076
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/MessageListenerAdapterTests.java
@@ -0,0 +1,657 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jms.listener.adapter;
+
+import java.io.Serializable;
+
+import javax.jms.BytesMessage;
+import javax.jms.IllegalStateException;
+import javax.jms.InvalidDestinationException;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageProducer;
+import javax.jms.ObjectMessage;
+import javax.jms.Queue;
+import javax.jms.QueueSender;
+import javax.jms.QueueSession;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.jms.support.converter.MessageConversionException;
+import org.springframework.jms.support.converter.SimpleMessageConverter;
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class MessageListenerAdapterTests extends TestCase {
+
+ private static final String TEXT = "I fancy a good cuppa right now";
+
+ private static final Integer NUMBER = new Integer(1);
+
+ private static final SerializableObject OBJECT = new SerializableObject();
+
+ private static final String CORRELATION_ID = "100";
+
+ private static final String RESPONSE_TEXT = "... wi' some full fat creamy milk. Top banana.";
+
+
+ public void testWithMessageContentsDelegateForTextMessage() throws Exception {
+ MockControl mockTextMessage = MockControl.createControl(TextMessage.class);
+ TextMessage textMessage = (TextMessage) mockTextMessage.getMock();
+ // TextMessage contents must be unwrapped...
+ textMessage.getText();
+ mockTextMessage.setReturnValue(TEXT);
+ mockTextMessage.replay();
+
+ MockControl mockDelegate = MockControl.createControl(MessageContentsDelegate.class);
+ MessageContentsDelegate delegate = (MessageContentsDelegate) mockDelegate.getMock();
+ delegate.handleMessage(TEXT);
+ mockDelegate.setVoidCallable();
+ mockDelegate.replay();
+
+ MessageListenerAdapter adapter = new MessageListenerAdapter(delegate);
+ adapter.onMessage(textMessage);
+
+ mockDelegate.verify();
+ mockTextMessage.verify();
+ }
+
+ public void testWithMessageContentsDelegateForBytesMessage() throws Exception {
+ MockControl mockBytesMessage = MockControl.createControl(BytesMessage.class);
+ BytesMessage bytesMessage = (BytesMessage) mockBytesMessage.getMock();
+ // BytesMessage contents must be unwrapped...
+ bytesMessage.getBodyLength();
+ mockBytesMessage.setReturnValue(TEXT.getBytes().length);
+ bytesMessage.readBytes(null);
+ mockBytesMessage.setMatcher(MockControl.ALWAYS_MATCHER);
+ mockBytesMessage.setReturnValue(TEXT.getBytes().length);
+ mockBytesMessage.replay();
+
+ MockControl mockDelegate = MockControl.createControl(MessageContentsDelegate.class);
+ MessageContentsDelegate delegate = (MessageContentsDelegate) mockDelegate.getMock();
+ delegate.handleMessage(TEXT.getBytes());
+ mockDelegate.setMatcher(MockControl.ALWAYS_MATCHER);
+ mockDelegate.setVoidCallable();
+ mockDelegate.replay();
+
+ MessageListenerAdapter adapter = new MessageListenerAdapter(delegate);
+ adapter.onMessage(bytesMessage);
+
+ mockDelegate.verify();
+ mockBytesMessage.verify();
+ }
+
+ public void testWithMessageContentsDelegateForObjectMessage() throws Exception {
+ MockControl mockObjectMessage = MockControl.createControl(ObjectMessage.class);
+ ObjectMessage objectMessage = (ObjectMessage) mockObjectMessage.getMock();
+ objectMessage.getObject();
+ mockObjectMessage.setReturnValue(NUMBER);
+ mockObjectMessage.replay();
+
+ MockControl mockDelegate = MockControl.createControl(MessageContentsDelegate.class);
+ MessageContentsDelegate delegate = (MessageContentsDelegate) mockDelegate.getMock();
+ delegate.handleMessage(NUMBER);
+ mockDelegate.setVoidCallable();
+ mockDelegate.replay();
+
+ MessageListenerAdapter adapter = new MessageListenerAdapter(delegate);
+ adapter.onMessage(objectMessage);
+
+ mockDelegate.verify();
+ mockObjectMessage.verify();
+ }
+
+ public void testWithMessageContentsDelegateForObjectMessageWithPlainObject() throws Exception {
+ MockControl mockObjectMessage = MockControl.createControl(ObjectMessage.class);
+ ObjectMessage objectMessage = (ObjectMessage) mockObjectMessage.getMock();
+ objectMessage.getObject();
+ mockObjectMessage.setReturnValue(OBJECT);
+ mockObjectMessage.replay();
+
+ MockControl mockDelegate = MockControl.createControl(MessageContentsDelegate.class);
+ MessageContentsDelegate delegate = (MessageContentsDelegate) mockDelegate.getMock();
+ delegate.handleMessage(OBJECT);
+ mockDelegate.setVoidCallable();
+ mockDelegate.replay();
+
+ MessageListenerAdapter adapter = new MessageListenerAdapter(delegate);
+ adapter.onMessage(objectMessage);
+
+ mockDelegate.verify();
+ mockObjectMessage.verify();
+ }
+
+ public void testWithMessageDelegate() throws Exception {
+ MockControl mockTextMessage = MockControl.createControl(TextMessage.class);
+ TextMessage textMessage = (TextMessage) mockTextMessage.getMock();
+ mockTextMessage.replay();
+
+ MockControl mockDelegate = MockControl.createControl(MessageDelegate.class);
+ MessageDelegate delegate = (MessageDelegate) mockDelegate.getMock();
+ delegate.handleMessage(textMessage);
+ mockDelegate.setVoidCallable();
+ mockDelegate.replay();
+
+ MessageListenerAdapter adapter = new MessageListenerAdapter(delegate);
+ // we DON'T want the default SimpleMessageConversion happening...
+ adapter.setMessageConverter(null);
+ adapter.onMessage(textMessage);
+
+ mockDelegate.verify();
+ mockTextMessage.verify();
+ }
+
+ public void testWhenTheAdapterItselfIsTheDelegate() throws Exception {
+ MockControl mockTextMessage = MockControl.createControl(TextMessage.class);
+ TextMessage textMessage = (TextMessage) mockTextMessage.getMock();
+ // TextMessage contents must be unwrapped...
+ textMessage.getText();
+ mockTextMessage.setReturnValue(TEXT);
+ mockTextMessage.replay();
+
+ StubMessageListenerAdapter adapter = new StubMessageListenerAdapter();
+ adapter.onMessage(textMessage);
+ assertTrue(adapter.wasCalled());
+
+ mockTextMessage.verify();
+ }
+
+ public void testRainyDayWithNoApplicableHandlingMethods() throws Exception {
+ MockControl mockTextMessage = MockControl.createControl(TextMessage.class);
+ TextMessage textMessage = (TextMessage) mockTextMessage.getMock();
+ // TextMessage contents must be unwrapped...
+ textMessage.getText();
+ mockTextMessage.setReturnValue(TEXT);
+ mockTextMessage.replay();
+
+ StubMessageListenerAdapter adapter = new StubMessageListenerAdapter();
+ adapter.setDefaultListenerMethod("walnutsRock");
+ adapter.onMessage(textMessage);
+ assertFalse(adapter.wasCalled());
+
+ mockTextMessage.verify();
+ }
+
+ public void testThatAnExceptionThrownFromTheHandlingMethodIsSimplySwallowedByDefault() throws Exception {
+ final IllegalArgumentException exception = new IllegalArgumentException();
+
+ MockControl mockTextMessage = MockControl.createControl(TextMessage.class);
+ TextMessage textMessage = (TextMessage) mockTextMessage.getMock();
+ mockTextMessage.replay();
+
+ MockControl mockDelegate = MockControl.createControl(MessageDelegate.class);
+ MessageDelegate delegate = (MessageDelegate) mockDelegate.getMock();
+ delegate.handleMessage(textMessage);
+ mockDelegate.setThrowable(exception);
+ mockDelegate.replay();
+
+ MessageListenerAdapter adapter = new MessageListenerAdapter(delegate) {
+ protected void handleListenerException(Throwable ex) {
+ assertNotNull("The Throwable passed to the handleListenerException(..) method must never be null.", ex);
+ assertTrue("The Throwable passed to the handleListenerException(..) method must be of type [ListenerExecutionFailedException].",
+ ex instanceof ListenerExecutionFailedException);
+ ListenerExecutionFailedException lefx = (ListenerExecutionFailedException) ex;
+ Throwable cause = lefx.getCause();
+ assertNotNull("The cause of a ListenerExecutionFailedException must be preserved.", cause);
+ assertSame(exception, cause);
+ }
+ };
+ // we DON'T want the default SimpleMessageConversion happening...
+ adapter.setMessageConverter(null);
+ adapter.onMessage(textMessage);
+
+ mockDelegate.verify();
+ mockTextMessage.verify();
+ }
+
+ public void testThatTheDefaultMessageConverterisIndeedTheSimpleMessageConverter() throws Exception {
+ MessageListenerAdapter adapter = new MessageListenerAdapter();
+ assertNotNull("The default [MessageConverter] must never be null.", adapter.getMessageConverter());
+ assertTrue("The default [MessageConverter] must be of the type [SimpleMessageConverter]",
+ adapter.getMessageConverter() instanceof SimpleMessageConverter);
+ }
+
+ public void testThatWhenNoDelegateIsSuppliedTheDelegateIsAssumedToBeTheMessageListenerAdapterItself() throws Exception {
+ MessageListenerAdapter adapter = new MessageListenerAdapter();
+ assertSame(adapter, adapter.getDelegate());
+ }
+
+ public void testThatTheDefaultMessageHandlingMethodNameIsTheConstantDefault() throws Exception {
+ MessageListenerAdapter adapter = new MessageListenerAdapter();
+ assertEquals(MessageListenerAdapter.ORIGINAL_DEFAULT_LISTENER_METHOD, adapter.getDefaultListenerMethod());
+ }
+
+ public void testWithResponsiveMessageDelegate_DoesNotSendReturnTextMessageIfNoSessionSupplied() throws Exception {
+ MockControl mockTextMessage = MockControl.createControl(TextMessage.class);
+ TextMessage textMessage = (TextMessage) mockTextMessage.getMock();
+ mockTextMessage.replay();
+
+ MockControl mockDelegate = MockControl.createControl(ResponsiveMessageDelegate.class);
+ ResponsiveMessageDelegate delegate = (ResponsiveMessageDelegate) mockDelegate.getMock();
+ delegate.handleMessage(textMessage);
+ mockDelegate.setReturnValue(TEXT);
+ mockDelegate.replay();
+
+ MessageListenerAdapter adapter = new MessageListenerAdapter(delegate);
+ // we DON'T want the default SimpleMessageConversion happening...
+ adapter.setMessageConverter(null);
+ adapter.onMessage(textMessage);
+
+ mockDelegate.verify();
+ mockTextMessage.verify();
+ }
+
+ public void testWithResponsiveMessageDelegateWithDefaultDestination_SendsReturnTextMessageWhenSessionSupplied() throws Exception {
+ MockControl mockDestination = MockControl.createControl(Queue.class);
+ Queue destination = (Queue) mockDestination.getMock();
+ mockDestination.replay();
+
+ MockControl mockSentTextMessage = MockControl.createControl(TextMessage.class);
+ TextMessage sentTextMessage = (TextMessage) mockSentTextMessage.getMock();
+ // correlation ID is queried when response is being created...
+ sentTextMessage.getJMSCorrelationID();
+ mockSentTextMessage.setReturnValue(CORRELATION_ID);
+ // Reply-To is queried when response is being created...
+ sentTextMessage.getJMSReplyTo();
+ mockSentTextMessage.setReturnValue(null); // we want to fall back to the default...
+ mockSentTextMessage.replay();
+
+ MockControl mockResponseTextMessage = MockControl.createControl(TextMessage.class);
+ TextMessage responseTextMessage = (TextMessage) mockResponseTextMessage.getMock();
+ responseTextMessage.setJMSCorrelationID(CORRELATION_ID);
+ mockResponseTextMessage.setVoidCallable();
+ mockResponseTextMessage.replay();
+
+ MockControl mockQueueSender = MockControl.createControl(QueueSender.class);
+ QueueSender queueSender = (QueueSender) mockQueueSender.getMock();
+ queueSender.send(responseTextMessage);
+ mockQueueSender.setVoidCallable();
+ queueSender.close();
+ mockQueueSender.setVoidCallable();
+ mockQueueSender.replay();
+
+ MockControl mockSession = MockControl.createControl(Session.class);
+ Session session = (Session) mockSession.getMock();
+ session.createTextMessage(RESPONSE_TEXT);
+ mockSession.setReturnValue(responseTextMessage);
+ session.createProducer(destination);
+ mockSession.setReturnValue(queueSender);
+ mockSession.replay();
+
+ MockControl mockDelegate = MockControl.createControl(ResponsiveMessageDelegate.class);
+ ResponsiveMessageDelegate delegate = (ResponsiveMessageDelegate) mockDelegate.getMock();
+ delegate.handleMessage(sentTextMessage);
+ mockDelegate.setReturnValue(RESPONSE_TEXT);
+ mockDelegate.replay();
+
+ MessageListenerAdapter adapter = new MessageListenerAdapter(delegate) {
+ protected Object extractMessage(Message message) {
+ return message;
+ }
+ };
+ adapter.setDefaultResponseDestination(destination);
+ adapter.onMessage(sentTextMessage, session);
+
+ mockDelegate.verify();
+ mockSentTextMessage.verify();
+ mockResponseTextMessage.verify();
+ mockSession.verify();
+ mockDestination.verify();
+ mockQueueSender.verify();
+ }
+
+ public void testWithResponsiveMessageDelegateNoDefaultDestination_SendsReturnTextMessageWhenSessionSupplied() throws Exception {
+ MockControl mockDestination = MockControl.createControl(Queue.class);
+ Queue destination = (Queue) mockDestination.getMock();
+ mockDestination.replay();
+
+ MockControl mockSentTextMessage = MockControl.createControl(TextMessage.class);
+ TextMessage sentTextMessage = (TextMessage) mockSentTextMessage.getMock();
+ // correlation ID is queried when response is being created...
+ sentTextMessage.getJMSCorrelationID();
+ mockSentTextMessage.setReturnValue(null);
+ sentTextMessage.getJMSMessageID();
+ mockSentTextMessage.setReturnValue(CORRELATION_ID);
+ // Reply-To is queried when response is being created...
+ sentTextMessage.getJMSReplyTo();
+ mockSentTextMessage.setReturnValue(destination);
+ mockSentTextMessage.replay();
+
+ MockControl mockResponseTextMessage = MockControl.createControl(TextMessage.class);
+ TextMessage responseTextMessage = (TextMessage) mockResponseTextMessage.getMock();
+ responseTextMessage.setJMSCorrelationID(CORRELATION_ID);
+ mockResponseTextMessage.setVoidCallable();
+ mockResponseTextMessage.replay();
+
+ MockControl mockMessageProducer = MockControl.createControl(MessageProducer.class);
+ MessageProducer messageProducer = (MessageProducer) mockMessageProducer.getMock();
+ messageProducer.send(responseTextMessage);
+ mockMessageProducer.setVoidCallable();
+ messageProducer.close();
+ mockMessageProducer.setVoidCallable();
+ mockMessageProducer.replay();
+
+ MockControl mockSession = MockControl.createControl(Session.class);
+ Session session = (Session) mockSession.getMock();
+ session.createTextMessage(RESPONSE_TEXT);
+ mockSession.setReturnValue(responseTextMessage);
+ session.createProducer(destination);
+ mockSession.setReturnValue(messageProducer);
+ mockSession.replay();
+
+ MockControl mockDelegate = MockControl.createControl(ResponsiveMessageDelegate.class);
+ ResponsiveMessageDelegate delegate = (ResponsiveMessageDelegate) mockDelegate.getMock();
+ delegate.handleMessage(sentTextMessage);
+ mockDelegate.setReturnValue(RESPONSE_TEXT);
+ mockDelegate.replay();
+
+ MessageListenerAdapter adapter = new MessageListenerAdapter(delegate) {
+ protected Object extractMessage(Message message) {
+ return message;
+ }
+ };
+ adapter.onMessage(sentTextMessage, session);
+
+ mockDelegate.verify();
+ mockSentTextMessage.verify();
+ mockResponseTextMessage.verify();
+ mockSession.verify();
+ mockDestination.verify();
+ mockMessageProducer.verify();
+ }
+
+ public void testWithResponsiveMessageDelegateNoDefaultDestinationAndNoReplyToDestination_SendsReturnTextMessageWhenSessionSupplied() throws Exception {
+ MockControl mockSentTextMessage = MockControl.createControl(TextMessage.class);
+ final TextMessage sentTextMessage = (TextMessage) mockSentTextMessage.getMock();
+ // correlation ID is queried when response is being created...
+ sentTextMessage.getJMSCorrelationID();
+ mockSentTextMessage.setReturnValue(CORRELATION_ID);
+ // Reply-To is queried when response is being created...
+ sentTextMessage.getJMSReplyTo();
+ mockSentTextMessage.setReturnValue(null);
+ mockSentTextMessage.replay();
+
+ MockControl mockResponseTextMessage = MockControl.createControl(TextMessage.class);
+ TextMessage responseTextMessage = (TextMessage) mockResponseTextMessage.getMock();
+ responseTextMessage.setJMSCorrelationID(CORRELATION_ID);
+ mockResponseTextMessage.setVoidCallable();
+ mockResponseTextMessage.replay();
+
+ MockControl mockSession = MockControl.createControl(QueueSession.class);
+ final QueueSession session = (QueueSession) mockSession.getMock();
+ session.createTextMessage(RESPONSE_TEXT);
+ mockSession.setReturnValue(responseTextMessage);
+ mockSession.replay();
+
+ MockControl mockDelegate = MockControl.createControl(ResponsiveMessageDelegate.class);
+ ResponsiveMessageDelegate delegate = (ResponsiveMessageDelegate) mockDelegate.getMock();
+ delegate.handleMessage(sentTextMessage);
+ mockDelegate.setReturnValue(RESPONSE_TEXT);
+ mockDelegate.replay();
+
+ final MessageListenerAdapter adapter = new MessageListenerAdapter(delegate) {
+ protected Object extractMessage(Message message) {
+ return message;
+ }
+ };
+ new AssertThrows(InvalidDestinationException.class) {
+ public void test() throws Exception {
+ adapter.onMessage(sentTextMessage, session);
+ }
+ }.runTest();
+
+ mockDelegate.verify();
+ mockSentTextMessage.verify();
+ mockResponseTextMessage.verify();
+ mockSession.verify();
+ }
+
+ public void testWithResponsiveMessageDelegateNoDefaultDestination_SendsReturnTextMessageWhenSessionSupplied_AndSendingThrowsJMSException() throws Exception {
+ MockControl mockDestination = MockControl.createControl(Queue.class);
+ Queue destination = (Queue) mockDestination.getMock();
+ mockDestination.replay();
+
+ MockControl mockSentTextMessage = MockControl.createControl(TextMessage.class);
+ final TextMessage sentTextMessage = (TextMessage) mockSentTextMessage.getMock();
+ // correlation ID is queried when response is being created...
+ sentTextMessage.getJMSCorrelationID();
+ mockSentTextMessage.setReturnValue(CORRELATION_ID);
+ // Reply-To is queried when response is being created...
+ sentTextMessage.getJMSReplyTo();
+ mockSentTextMessage.setReturnValue(destination);
+ mockSentTextMessage.replay();
+
+ MockControl mockResponseTextMessage = MockControl.createControl(TextMessage.class);
+ TextMessage responseTextMessage = (TextMessage) mockResponseTextMessage.getMock();
+ responseTextMessage.setJMSCorrelationID(CORRELATION_ID);
+ mockResponseTextMessage.setVoidCallable();
+ mockResponseTextMessage.replay();
+
+ MockControl mockMessageProducer = MockControl.createControl(MessageProducer.class);
+ MessageProducer messageProducer = (MessageProducer) mockMessageProducer.getMock();
+ messageProducer.send(responseTextMessage);
+ mockMessageProducer.setThrowable(new JMSException("Dow!"));
+ // ensure that regardless of a JMSException the producer is closed...
+ messageProducer.close();
+ mockMessageProducer.setVoidCallable();
+ mockMessageProducer.replay();
+
+ MockControl mockSession = MockControl.createControl(QueueSession.class);
+ final QueueSession session = (QueueSession) mockSession.getMock();
+ session.createTextMessage(RESPONSE_TEXT);
+ mockSession.setReturnValue(responseTextMessage);
+ session.createProducer(destination);
+ mockSession.setReturnValue(messageProducer);
+ mockSession.replay();
+
+ MockControl mockDelegate = MockControl.createControl(ResponsiveMessageDelegate.class);
+ ResponsiveMessageDelegate delegate = (ResponsiveMessageDelegate) mockDelegate.getMock();
+ delegate.handleMessage(sentTextMessage);
+ mockDelegate.setReturnValue(RESPONSE_TEXT);
+ mockDelegate.replay();
+
+ final MessageListenerAdapter adapter = new MessageListenerAdapter(delegate) {
+ protected Object extractMessage(Message message) {
+ return message;
+ }
+ };
+ new AssertThrows(JMSException.class) {
+ public void test() throws Exception {
+ adapter.onMessage(sentTextMessage, session);
+ }
+ }.runTest();
+
+ mockDelegate.verify();
+ mockSentTextMessage.verify();
+ mockResponseTextMessage.verify();
+ mockSession.verify();
+ mockDestination.verify();
+ mockMessageProducer.verify();
+ }
+
+ public void testWithResponsiveMessageDelegateDoesNotSendReturnTextMessageWhenSessionSupplied_AndListenerMethodThrowsException() throws Exception {
+ MockControl mockMessage = MockControl.createControl(TextMessage.class);
+ final TextMessage message = (TextMessage) mockMessage.getMock();
+ mockMessage.replay();
+
+ MockControl mockSession = MockControl.createControl(QueueSession.class);
+ final QueueSession session = (QueueSession) mockSession.getMock();
+ mockSession.replay();
+
+ MockControl mockDelegate = MockControl.createControl(ResponsiveMessageDelegate.class);
+ ResponsiveMessageDelegate delegate = (ResponsiveMessageDelegate) mockDelegate.getMock();
+ delegate.handleMessage(message);
+ mockDelegate.setThrowable(new IllegalArgumentException("Dow!"));
+ mockDelegate.replay();
+
+ final MessageListenerAdapter adapter = new MessageListenerAdapter(delegate) {
+ protected Object extractMessage(Message message) {
+ return message;
+ }
+ };
+ new AssertThrows(ListenerExecutionFailedException.class) {
+ public void test() throws Exception {
+ adapter.onMessage(message, session);
+ }
+ }.runTest();
+
+ mockDelegate.verify();
+ mockMessage.verify();
+ mockSession.verify();
+ }
+
+ public void testFailsIfNoDefaultListenerMethodNameIsSupplied() throws Exception {
+ MockControl mockMessage = MockControl.createControl(TextMessage.class);
+ final TextMessage message = (TextMessage) mockMessage.getMock();
+ message.getText();
+ mockMessage.setReturnValue(TEXT);
+
+ mockMessage.replay();
+
+ final MessageListenerAdapter adapter = new MessageListenerAdapter() {
+ protected void handleListenerException(Throwable ex) {
+ assertTrue(ex instanceof IllegalStateException);
+ }
+ };
+ adapter.setDefaultListenerMethod(null);
+ adapter.onMessage(message);
+
+ mockMessage.verify();
+ }
+
+ public void testFailsWhenOverriddenGetListenerMethodNameReturnsNull() throws Exception {
+ MockControl mockMessage = MockControl.createControl(TextMessage.class);
+ final TextMessage message = (TextMessage) mockMessage.getMock();
+ message.getText();
+ mockMessage.setReturnValue(TEXT);
+
+ mockMessage.replay();
+
+ final MessageListenerAdapter adapter = new MessageListenerAdapter() {
+ protected void handleListenerException(Throwable ex) {
+ assertTrue(ex instanceof javax.jms.IllegalStateException);
+ }
+ protected String getListenerMethodName(Message originalMessage, Object extractedMessage) {
+ return null;
+ }
+ };
+ adapter.setDefaultListenerMethod(null);
+ adapter.onMessage(message);
+
+ mockMessage.verify();
+ }
+
+ public void testWithResponsiveMessageDelegateWhenReturnTypeIsNotAJMSMessageAndNoMessageConverterIsSupplied() throws Exception {
+ MockControl mockSentTextMessage = MockControl.createControl(TextMessage.class);
+ final TextMessage sentTextMessage = (TextMessage) mockSentTextMessage.getMock();
+ mockSentTextMessage.replay();
+
+ MockControl mockSession = MockControl.createControl(Session.class);
+ final Session session = (Session) mockSession.getMock();
+ mockSession.replay();
+
+ MockControl mockDelegate = MockControl.createControl(ResponsiveMessageDelegate.class);
+ ResponsiveMessageDelegate delegate = (ResponsiveMessageDelegate) mockDelegate.getMock();
+ delegate.handleMessage(sentTextMessage);
+ mockDelegate.setReturnValue(RESPONSE_TEXT);
+ mockDelegate.replay();
+
+ final MessageListenerAdapter adapter = new MessageListenerAdapter(delegate) {
+ protected Object extractMessage(Message message) {
+ return message;
+ }
+ };
+ adapter.setMessageConverter(null);
+ new AssertThrows(MessageConversionException.class) {
+ public void test() throws Exception {
+ adapter.onMessage(sentTextMessage, session);
+ }
+ }.runTest();
+
+ mockDelegate.verify();
+ mockSentTextMessage.verify();
+ mockSession.verify();
+ }
+
+ public void testWithResponsiveMessageDelegateWhenReturnTypeIsAJMSMessageAndNoMessageConverterIsSupplied() throws Exception {
+ MockControl mockDestination = MockControl.createControl(Queue.class);
+ Queue destination = (Queue) mockDestination.getMock();
+ mockDestination.replay();
+
+ MockControl mockSentTextMessage = MockControl.createControl(TextMessage.class);
+ final TextMessage sentTextMessage = (TextMessage) mockSentTextMessage.getMock();
+ // correlation ID is queried when response is being created...
+ sentTextMessage.getJMSCorrelationID();
+ mockSentTextMessage.setReturnValue(CORRELATION_ID);
+ // Reply-To is queried when response is being created...
+ sentTextMessage.getJMSReplyTo();
+ mockSentTextMessage.setReturnValue(destination);
+ mockSentTextMessage.replay();
+
+ MockControl mockResponseMessage = MockControl.createControl(TextMessage.class);
+ TextMessage responseMessage = (TextMessage) mockResponseMessage.getMock();
+ responseMessage.setJMSCorrelationID(CORRELATION_ID);
+ mockResponseMessage.setVoidCallable();
+ mockResponseMessage.replay();
+
+ MockControl mockQueueSender = MockControl.createControl(QueueSender.class);
+ QueueSender queueSender = (QueueSender) mockQueueSender.getMock();
+ queueSender.send(responseMessage);
+ mockQueueSender.setVoidCallable();
+ queueSender.close();
+ mockQueueSender.setVoidCallable();
+ mockQueueSender.replay();
+
+ MockControl mockSession = MockControl.createControl(Session.class);
+ Session session = (Session) mockSession.getMock();
+ session.createProducer(destination);
+ mockSession.setReturnValue(queueSender);
+ mockSession.replay();
+
+ MockControl mockDelegate = MockControl.createControl(ResponsiveJmsTextMessageReturningMessageDelegate.class);
+ ResponsiveJmsTextMessageReturningMessageDelegate delegate = (ResponsiveJmsTextMessageReturningMessageDelegate) mockDelegate.getMock();
+ delegate.handleMessage(sentTextMessage);
+ mockDelegate.setReturnValue(responseMessage);
+ mockDelegate.replay();
+
+ final MessageListenerAdapter adapter = new MessageListenerAdapter(delegate) {
+ protected Object extractMessage(Message message) {
+ return message;
+ }
+ };
+ adapter.setMessageConverter(null);
+ adapter.onMessage(sentTextMessage, session);
+
+ mockDestination.verify();
+ mockDelegate.verify();
+ mockSentTextMessage.verify();
+ mockSession.verify();
+ mockQueueSender.verify();
+ mockResponseMessage.verify();
+ }
+
+
+ private static class SerializableObject implements Serializable {
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/ResponsiveJmsTextMessageReturningMessageDelegate.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/ResponsiveJmsTextMessageReturningMessageDelegate.java
new file mode 100644
index 00000000000..ffa07f4f294
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/ResponsiveJmsTextMessageReturningMessageDelegate.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jms.listener.adapter;
+
+import javax.jms.TextMessage;
+import javax.jms.MapMessage;
+import javax.jms.BytesMessage;
+import javax.jms.ObjectMessage;
+
+import java.util.Map;
+import java.io.Serializable;
+
+/**
+ * See the MessageListenerAdapterTests class for usage.
+ *
+ * @author Rick Evans
+ */
+public interface ResponsiveJmsTextMessageReturningMessageDelegate {
+
+ TextMessage handleMessage(TextMessage message);
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/ResponsiveMessageDelegate.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/ResponsiveMessageDelegate.java
new file mode 100644
index 00000000000..cb1dedb0939
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/ResponsiveMessageDelegate.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jms.listener.adapter;
+
+import java.io.Serializable;
+import java.util.Map;
+
+import javax.jms.BytesMessage;
+import javax.jms.MapMessage;
+import javax.jms.ObjectMessage;
+import javax.jms.TextMessage;
+
+/**
+ * See the MessageListenerAdapterTests class for usage.
+ *
+ * @author Rick Evans
+ */
+public interface ResponsiveMessageDelegate {
+
+ String handleMessage(TextMessage message);
+
+ Map handleMessage(MapMessage message);
+
+ byte[] handleMessage(BytesMessage message);
+
+ Serializable handleMessage(ObjectMessage message);
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/StubMessageListenerAdapter.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/StubMessageListenerAdapter.java
new file mode 100644
index 00000000000..4973cda8ce5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/StubMessageListenerAdapter.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jms.listener.adapter;
+
+/**
+ * Stub extension of the {@link MessageListenerAdapter} class for use in testing.
+ *
+ * @author Rick Evans
+ */
+public class StubMessageListenerAdapter extends MessageListenerAdapter {
+
+ private boolean wasCalled;
+
+
+ public boolean wasCalled() {
+ return this.wasCalled;
+ }
+
+
+ public void handleMessage(String message) {
+ this.wasCalled = true;
+ }
+
+ protected void handleListenerException(Throwable ex) {
+ System.out.println(ex);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/StubMessageListenerAdapter102.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/StubMessageListenerAdapter102.java
new file mode 100644
index 00000000000..20ea0c40bb6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/adapter/StubMessageListenerAdapter102.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jms.listener.adapter;
+
+/**
+ * Stub extension of the {@link MessageListenerAdapter102} class for use in testing.
+ *
+ * @author Rick Evans
+ */
+public class StubMessageListenerAdapter102 extends MessageListenerAdapter102 {
+
+ private boolean wasCalled;
+
+
+ public boolean wasCalled() {
+ return this.wasCalled;
+ }
+
+
+ public void handleMessage(String message) {
+ this.wasCalled = true;
+ }
+
+ protected void handleListenerException(Throwable ex) {
+ System.out.println(ex);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/endpoint/DefaultJmsActivationSpecFactoryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/endpoint/DefaultJmsActivationSpecFactoryTests.java
new file mode 100644
index 00000000000..3b7e23a91f6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/endpoint/DefaultJmsActivationSpecFactoryTests.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jms.listener.endpoint;
+
+import javax.jms.Destination;
+import javax.jms.Session;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.jca.StubResourceAdapter;
+import org.springframework.jms.StubQueue;
+import org.springframework.jms.support.destination.DestinationResolver;
+
+/**
+ * @author Agim Emruli
+ * @author Juergen Hoeller
+ */
+public class DefaultJmsActivationSpecFactoryTests extends TestCase {
+
+ private JmsActivationSpecConfig activationSpecConfig;
+
+ protected void setUp() throws Exception {
+ activationSpecConfig = new JmsActivationSpecConfig();
+ activationSpecConfig.setMaxConcurrency(5);
+ activationSpecConfig.setPrefetchSize(3);
+ activationSpecConfig.setAcknowledgeMode(Session.AUTO_ACKNOWLEDGE);
+ activationSpecConfig.setClientId("clientid");
+ activationSpecConfig.setDestinationName("destinationname");
+ activationSpecConfig.setDurableSubscriptionName("durableSubscriptionName");
+ activationSpecConfig.setMessageSelector("selector");
+ }
+
+ public void testActiveMQResourceAdapterSetup() {
+ activationSpecConfig.setAcknowledgeMode(Session.SESSION_TRANSACTED);
+ JmsActivationSpecFactory activationSpecFactory = new DefaultJmsActivationSpecFactory();
+ StubActiveMQActivationSpec spec = (StubActiveMQActivationSpec) activationSpecFactory.createActivationSpec(
+ new StubActiveMQResourceAdapter(), activationSpecConfig);
+
+ assertEquals(5, spec.getMaxSessions());
+ assertEquals(3, spec.getMaxMessagesPerSessions());
+ assertTrue(spec.isUseRAManagedTransaction());
+ }
+
+ public void testWebSphereResourceAdapterSetup() throws Exception {
+ Destination destination = new StubQueue();
+
+ MockControl control = MockControl.createControl(DestinationResolver.class);
+ DestinationResolver destinationResolver = (DestinationResolver) control.getMock();
+
+ destinationResolver.resolveDestinationName(null, "destinationname", false);
+ control.setReturnValue(destination);
+ control.replay();
+
+ DefaultJmsActivationSpecFactory activationSpecFactory = new DefaultJmsActivationSpecFactory();
+ activationSpecFactory.setDestinationResolver(destinationResolver);
+
+ StubWebSphereActivationSpecImpl spec = (StubWebSphereActivationSpecImpl) activationSpecFactory
+ .createActivationSpec(new StubWebSphereResourceAdapterImpl(), activationSpecConfig);
+
+ control.verify();
+
+ assertEquals(destination, spec.getDestination());
+ assertEquals(5, spec.getMaxConcurrency());
+ assertEquals(3, spec.getMaxBatchSize());
+ }
+
+
+ private static class StubActiveMQResourceAdapter extends StubResourceAdapter {
+ }
+
+
+ private static class StubWebSphereResourceAdapterImpl extends StubResourceAdapter {
+ }
+
+
+ private static class StubActiveMQActivationSpec extends StubJmsActivationSpec {
+
+ private int maxSessions;
+
+ private int maxMessagesPerSessions;
+
+ private String destination;
+
+ private boolean useRAManagedTransaction;
+
+ public void setMaxSessions(int maxSessions) {
+ this.maxSessions = maxSessions;
+ }
+
+ public void setMaxMessagesPerSessions(int maxMessagesPerSessions) {
+ this.maxMessagesPerSessions = maxMessagesPerSessions;
+ }
+
+ public int getMaxSessions() {
+ return maxSessions;
+ }
+
+ public int getMaxMessagesPerSessions() {
+ return maxMessagesPerSessions;
+ }
+
+ public String getDestination() {
+ return destination;
+ }
+
+ public void setDestination(String destination) {
+ this.destination = destination;
+ }
+
+ public boolean isUseRAManagedTransaction() {
+ return useRAManagedTransaction;
+ }
+
+ public void setUseRAManagedTransaction(boolean useRAManagedTransaction) {
+ this.useRAManagedTransaction = useRAManagedTransaction;
+ }
+ }
+
+
+ private static class StubWebSphereActivationSpecImpl extends StubJmsActivationSpec {
+
+ private Destination destination;
+
+ private int maxConcurrency;
+
+ private int maxBatchSize;
+
+ public void setDestination(Destination destination) {
+ this.destination = destination;
+ }
+
+ public Destination getDestination() {
+ return destination;
+ }
+
+ public int getMaxConcurrency() {
+ return maxConcurrency;
+ }
+
+ public void setMaxConcurrency(int maxConcurrency) {
+ this.maxConcurrency = maxConcurrency;
+ }
+
+ public int getMaxBatchSize() {
+ return maxBatchSize;
+ }
+
+ public void setMaxBatchSize(int maxBatchSize) {
+ this.maxBatchSize = maxBatchSize;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/endpoint/StubJmsActivationSpec.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/endpoint/StubJmsActivationSpec.java
new file mode 100644
index 00000000000..6ffa02b4881
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/endpoint/StubJmsActivationSpec.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jms.listener.endpoint;
+
+import javax.jms.Destination;
+
+import org.springframework.jca.StubActivationSpec;
+
+/**
+ * StubActivationSpec which implements all required and optional properties (see
+ * specification Appendix B.2) except the destination attribute. Because this
+ * can be a string but also an {@link Destination} object, which is configured
+ * as an administrated object.
+ *
+ * @author Agim Emruli
+ */
+public class StubJmsActivationSpec extends StubActivationSpec {
+
+ private String destinationType;
+
+ private String subscriptionDurability;
+
+ private String subscriptionName;
+
+ private String clientId;
+
+ private String messageSelector;
+
+ private String acknowledgeMode;
+
+
+ public String getDestinationType() {
+ return destinationType;
+ }
+
+ public void setDestinationType(String destinationType) {
+ this.destinationType = destinationType;
+ }
+
+ public String getSubscriptionDurability() {
+ return subscriptionDurability;
+ }
+
+ public void setSubscriptionDurability(String subscriptionDurability) {
+ this.subscriptionDurability = subscriptionDurability;
+ }
+
+ public String getSubscriptionName() {
+ return subscriptionName;
+ }
+
+ public void setSubscriptionName(String subscriptionName) {
+ this.subscriptionName = subscriptionName;
+ }
+
+ public String getClientId() {
+ return clientId;
+ }
+
+ public void setClientId(String clientId) {
+ this.clientId = clientId;
+ }
+
+ public String getMessageSelector() {
+ return messageSelector;
+ }
+
+ public void setMessageSelector(String messageSelector) {
+ this.messageSelector = messageSelector;
+ }
+
+ public String getAcknowledgeMode() {
+ return acknowledgeMode;
+ }
+
+ public void setAcknowledgeMode(String acknowledgeMode) {
+ this.acknowledgeMode = acknowledgeMode;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/endpoint/StubJmsActivationSpecFactory.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/endpoint/StubJmsActivationSpecFactory.java
new file mode 100644
index 00000000000..1be6176bd69
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/listener/endpoint/StubJmsActivationSpecFactory.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jms.listener.endpoint;
+
+import javax.resource.spi.ActivationSpec;
+import javax.resource.spi.ResourceAdapter;
+
+import org.springframework.jca.StubActivationSpec;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class StubJmsActivationSpecFactory implements JmsActivationSpecFactory {
+
+ public ActivationSpec createActivationSpec(ResourceAdapter adapter, JmsActivationSpecConfig config) {
+ return new StubActivationSpec();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/remoting/JmsInvokerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/remoting/JmsInvokerTests.java
new file mode 100644
index 00000000000..8c307cd603e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/remoting/JmsInvokerTests.java
@@ -0,0 +1,414 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jms.remoting;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Enumeration;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageProducer;
+import javax.jms.ObjectMessage;
+import javax.jms.Queue;
+import javax.jms.QueueConnection;
+import javax.jms.QueueConnectionFactory;
+import javax.jms.QueueSession;
+import javax.jms.Session;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.jms.support.converter.MessageConversionException;
+import org.springframework.jms.support.converter.SimpleMessageConverter;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class JmsInvokerTests extends TestCase {
+
+ private MockControl connectionFactoryControl;
+ private QueueConnectionFactory mockConnectionFactory;
+
+ private MockControl connectionControl;
+ private QueueConnection mockConnection;
+
+ private MockControl sessionControl;
+ private QueueSession mockSession;
+
+ private MockControl queueControl;
+ private Queue mockQueue;
+
+
+ protected void setUp() throws Exception {
+ connectionFactoryControl = MockControl.createControl(QueueConnectionFactory.class);
+ mockConnectionFactory = (QueueConnectionFactory) connectionFactoryControl.getMock();
+
+ connectionControl = MockControl.createControl(QueueConnection.class);
+ mockConnection = (QueueConnection) connectionControl.getMock();
+
+ sessionControl = MockControl.createControl(QueueSession.class);
+ mockSession = (QueueSession) sessionControl.getMock();
+
+ queueControl = MockControl.createControl(Queue.class);
+ mockQueue = (Queue) queueControl.getMock();
+
+ mockConnectionFactory.createQueueConnection();
+ connectionFactoryControl.setReturnValue(mockConnection, 8);
+
+ mockConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
+ connectionControl.setReturnValue(mockSession, 8);
+
+ mockConnection.start();
+ connectionControl.setVoidCallable(8);
+
+ connectionFactoryControl.replay();
+ connectionControl.replay();
+ }
+
+
+ public void testJmsInvokerProxyFactoryBeanAndServiceExporter() throws Throwable {
+ sessionControl.replay();
+
+ doTestJmsInvokerProxyFactoryBeanAndServiceExporter(false);
+ }
+
+ public void testJmsInvokerProxyFactoryBeanAndServiceExporterWithDynamicQueue() throws Throwable {
+ mockSession.createQueue("myQueue");
+ sessionControl.setReturnValue(mockQueue, 8);
+ sessionControl.replay();
+
+ doTestJmsInvokerProxyFactoryBeanAndServiceExporter(true);
+ }
+
+ private void doTestJmsInvokerProxyFactoryBeanAndServiceExporter(boolean dynamicQueue) throws Throwable {
+ TestBean target = new TestBean("myname", 99);
+
+ final JmsInvokerServiceExporter exporter = new JmsInvokerServiceExporter();
+ exporter.setServiceInterface(ITestBean.class);
+ exporter.setService(target);
+ exporter.setMessageConverter(new MockSimpleMessageConverter());
+ exporter.afterPropertiesSet();
+
+ JmsInvokerProxyFactoryBean pfb = new JmsInvokerProxyFactoryBean() {
+ protected Message doExecuteRequest(Session session, Queue queue, Message requestMessage) throws JMSException {
+ MockControl exporterSessionControl = MockControl.createControl(Session.class);
+ Session mockExporterSession = (Session) exporterSessionControl.getMock();
+ ResponseStoringProducer mockProducer = new ResponseStoringProducer();
+ mockExporterSession.createProducer(requestMessage.getJMSReplyTo());
+ exporterSessionControl.setReturnValue(mockProducer);
+ exporterSessionControl.replay();
+ exporter.onMessage(requestMessage, mockExporterSession);
+ exporterSessionControl.verify();
+ assertTrue(mockProducer.closed);
+ return mockProducer.response;
+ }
+ };
+ pfb.setServiceInterface(ITestBean.class);
+ pfb.setConnectionFactory(this.mockConnectionFactory);
+ if (dynamicQueue) {
+ pfb.setQueueName("myQueue");
+ }
+ else {
+ pfb.setQueue(this.mockQueue);
+ }
+ pfb.setMessageConverter(new MockSimpleMessageConverter());
+
+ pfb.afterPropertiesSet();
+ ITestBean proxy = (ITestBean) pfb.getObject();
+
+ assertEquals("myname", proxy.getName());
+ assertEquals(99, proxy.getAge());
+ proxy.setAge(50);
+ assertEquals(50, proxy.getAge());
+ proxy.setStringArray(new String[] {"str1", "str2"});
+ assertTrue(Arrays.equals(new String[] {"str1", "str2"}, proxy.getStringArray()));
+
+ try {
+ proxy.exceptional(new IllegalStateException());
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ try {
+ proxy.exceptional(new IllegalAccessException());
+ fail("Should have thrown IllegalAccessException");
+ }
+ catch (IllegalAccessException ex) {
+ // expected
+ }
+
+ connectionFactoryControl.verify();
+ connectionControl.verify();
+ sessionControl.verify();
+ }
+
+
+ private static class ResponseStoringProducer implements MessageProducer {
+
+ public Message response;
+
+ public boolean closed = false;
+
+ public void setDisableMessageID(boolean b) throws JMSException {
+ }
+
+ public boolean getDisableMessageID() throws JMSException {
+ return false;
+ }
+
+ public void setDisableMessageTimestamp(boolean b) throws JMSException {
+ }
+
+ public boolean getDisableMessageTimestamp() throws JMSException {
+ return false;
+ }
+
+ public void setDeliveryMode(int i) throws JMSException {
+ }
+
+ public int getDeliveryMode() throws JMSException {
+ return 0;
+ }
+
+ public void setPriority(int i) throws JMSException {
+ }
+
+ public int getPriority() throws JMSException {
+ return 0;
+ }
+
+ public void setTimeToLive(long l) throws JMSException {
+ }
+
+ public long getTimeToLive() throws JMSException {
+ return 0;
+ }
+
+ public Destination getDestination() throws JMSException {
+ return null;
+ }
+
+ public void close() throws JMSException {
+ this.closed = true;
+ }
+
+ public void send(Message message) throws JMSException {
+ this.response = message;
+ }
+
+ public void send(Message message, int i, int i1, long l) throws JMSException {
+ }
+
+ public void send(Destination destination, Message message) throws JMSException {
+ }
+
+ public void send(Destination destination, Message message, int i, int i1, long l) throws JMSException {
+ }
+ }
+
+
+ private static class MockObjectMessage implements ObjectMessage {
+
+ private Serializable serializable;
+
+ private Destination replyTo;
+
+ public MockObjectMessage(Serializable serializable) {
+ this.serializable = serializable;
+ }
+
+ public void setObject(Serializable serializable) throws JMSException {
+ this.serializable = serializable;
+ }
+
+ public Serializable getObject() throws JMSException {
+ return serializable;
+ }
+
+ public String getJMSMessageID() throws JMSException {
+ return null;
+ }
+
+ public void setJMSMessageID(String string) throws JMSException {
+ }
+
+ public long getJMSTimestamp() throws JMSException {
+ return 0;
+ }
+
+ public void setJMSTimestamp(long l) throws JMSException {
+ }
+
+ public byte[] getJMSCorrelationIDAsBytes() throws JMSException {
+ return new byte[0];
+ }
+
+ public void setJMSCorrelationIDAsBytes(byte[] bytes) throws JMSException {
+ }
+
+ public void setJMSCorrelationID(String string) throws JMSException {
+ }
+
+ public String getJMSCorrelationID() throws JMSException {
+ return null;
+ }
+
+ public Destination getJMSReplyTo() throws JMSException {
+ return replyTo;
+ }
+
+ public void setJMSReplyTo(Destination destination) throws JMSException {
+ this.replyTo = destination;
+ }
+
+ public Destination getJMSDestination() throws JMSException {
+ return null;
+ }
+
+ public void setJMSDestination(Destination destination) throws JMSException {
+ }
+
+ public int getJMSDeliveryMode() throws JMSException {
+ return 0;
+ }
+
+ public void setJMSDeliveryMode(int i) throws JMSException {
+ }
+
+ public boolean getJMSRedelivered() throws JMSException {
+ return false;
+ }
+
+ public void setJMSRedelivered(boolean b) throws JMSException {
+ }
+
+ public String getJMSType() throws JMSException {
+ return null;
+ }
+
+ public void setJMSType(String string) throws JMSException {
+ }
+
+ public long getJMSExpiration() throws JMSException {
+ return 0;
+ }
+
+ public void setJMSExpiration(long l) throws JMSException {
+ }
+
+ public int getJMSPriority() throws JMSException {
+ return 0;
+ }
+
+ public void setJMSPriority(int i) throws JMSException {
+ }
+
+ public void clearProperties() throws JMSException {
+ }
+
+ public boolean propertyExists(String string) throws JMSException {
+ return false;
+ }
+
+ public boolean getBooleanProperty(String string) throws JMSException {
+ return false;
+ }
+
+ public byte getByteProperty(String string) throws JMSException {
+ return 0;
+ }
+
+ public short getShortProperty(String string) throws JMSException {
+ return 0;
+ }
+
+ public int getIntProperty(String string) throws JMSException {
+ return 0;
+ }
+
+ public long getLongProperty(String string) throws JMSException {
+ return 0;
+ }
+
+ public float getFloatProperty(String string) throws JMSException {
+ return 0;
+ }
+
+ public double getDoubleProperty(String string) throws JMSException {
+ return 0;
+ }
+
+ public String getStringProperty(String string) throws JMSException {
+ return null;
+ }
+
+ public Object getObjectProperty(String string) throws JMSException {
+ return null;
+ }
+
+ public Enumeration getPropertyNames() throws JMSException {
+ return null;
+ }
+
+ public void setBooleanProperty(String string, boolean b) throws JMSException {
+ }
+
+ public void setByteProperty(String string, byte b) throws JMSException {
+ }
+
+ public void setShortProperty(String string, short i) throws JMSException {
+ }
+
+ public void setIntProperty(String string, int i) throws JMSException {
+ }
+
+ public void setLongProperty(String string, long l) throws JMSException {
+ }
+
+ public void setFloatProperty(String string, float v) throws JMSException {
+ }
+
+ public void setDoubleProperty(String string, double v) throws JMSException {
+ }
+
+ public void setStringProperty(String string, String string1) throws JMSException {
+ }
+
+ public void setObjectProperty(String string, Object object) throws JMSException {
+ }
+
+ public void acknowledge() throws JMSException {
+ }
+
+ public void clearBody() throws JMSException {
+ }
+ }
+
+
+ private static class MockSimpleMessageConverter extends SimpleMessageConverter {
+
+ public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException {
+ return new MockObjectMessage((Serializable) object);
+ }
+ };
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/support/JmsAccessorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/support/JmsAccessorTests.java
new file mode 100644
index 00000000000..49d2a5dca1f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/support/JmsAccessorTests.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jms.support;
+
+import junit.framework.TestCase;
+import org.springframework.test.AssertThrows;
+
+import javax.jms.Session;
+
+/**
+ * Unit tests for the {@link JmsAccessor} class.
+ *
+ * @author Rick Evans
+ */
+public final class JmsAccessorTests extends TestCase {
+
+ public void testChokesIfConnectionFactoryIsNotSupplied() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ JmsAccessor accessor = new StubJmsAccessor();
+ accessor.afterPropertiesSet();
+ }
+ }.runTest();
+ }
+
+ public void testSessionTransactedModeReallyDoesDefaultToFalse() throws Exception {
+ JmsAccessor accessor = new StubJmsAccessor();
+ assertFalse("The [sessionTransacted] property of JmsAccessor must default to " +
+ "false. Change this test (and the attendant Javadoc) if you have " +
+ "changed the default.",
+ accessor.isSessionTransacted());
+ }
+
+ public void testAcknowledgeModeReallyDoesDefaultToAutoAcknowledge() throws Exception {
+ JmsAccessor accessor = new StubJmsAccessor();
+ assertEquals("The [sessionAcknowledgeMode] property of JmsAccessor must default to " +
+ "[Session.AUTO_ACKNOWLEDGE]. Change this test (and the attendant " +
+ "Javadoc) if you have changed the default.",
+ Session.AUTO_ACKNOWLEDGE,
+ accessor.getSessionAcknowledgeMode());
+ }
+
+ public void testSetAcknowledgeModeNameChokesIfBadAckModeIsSupplied() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new StubJmsAccessor().setSessionAcknowledgeModeName("Tally ho chaps!");
+ }
+ }.runTest();
+ }
+
+
+ /**
+ * Crummy, stub, do-nothing subclass of the JmsAccessor class for use in testing.
+ */
+ private static final class StubJmsAccessor extends JmsAccessor {
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/support/SimpleMessageConverter102Tests.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/support/SimpleMessageConverter102Tests.java
new file mode 100644
index 00000000000..6aedec71f5c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/support/SimpleMessageConverter102Tests.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jms.support;
+
+import junit.framework.TestCase;
+import org.easymock.ArgumentsMatcher;
+import org.easymock.MockControl;
+import org.springframework.jms.support.converter.SimpleMessageConverter102;
+
+import javax.jms.BytesMessage;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.Session;
+import java.util.Arrays;
+
+/**
+ * Unit tests for the {@link SimpleMessageConverter102} class.
+ *
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ */
+public final class SimpleMessageConverter102Tests extends TestCase {
+
+ public void testByteArrayConversion102() throws JMSException {
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ MockControl messageControl = MockControl.createControl(BytesMessage.class);
+ BytesMessage message = (BytesMessage) messageControl.getMock();
+
+ byte[] content = new byte[5000];
+
+ session.createBytesMessage();
+ sessionControl.setReturnValue(message, 1);
+ message.writeBytes(content);
+ messageControl.setVoidCallable(1);
+ message.readBytes(new byte[SimpleMessageConverter102.BUFFER_SIZE]);
+ messageControl.setMatcher(new ArgumentsMatcher() {
+ public boolean matches(Object[] arg0, Object[] arg1) {
+ byte[] one = (byte[]) arg0[0];
+ byte[] two = (byte[]) arg1[0];
+ return Arrays.equals(one, two);
+ }
+
+ public String toString(Object[] arg0) {
+ return "bla";
+ }
+ });
+ messageControl.setReturnValue(SimpleMessageConverter102.BUFFER_SIZE, 1);
+ message.readBytes(new byte[SimpleMessageConverter102.BUFFER_SIZE]);
+ messageControl.setReturnValue(5000 - SimpleMessageConverter102.BUFFER_SIZE, 1);
+ sessionControl.replay();
+ messageControl.replay();
+
+ SimpleMessageConverter102 converter = new SimpleMessageConverter102();
+ Message msg = converter.toMessage(content, session);
+ assertEquals(content.length, ((byte[]) converter.fromMessage(msg)).length);
+
+ sessionControl.verify();
+ messageControl.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/support/SimpleMessageConverterTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/support/SimpleMessageConverterTests.java
new file mode 100644
index 00000000000..0c0b6da2ed5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/support/SimpleMessageConverterTests.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jms.support;
+
+import junit.framework.TestCase;
+import org.easymock.ArgumentsMatcher;
+import org.easymock.MockControl;
+import org.springframework.jms.support.converter.MessageConversionException;
+import org.springframework.jms.support.converter.SimpleMessageConverter;
+import org.springframework.test.AssertThrows;
+
+import javax.jms.*;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Unit tests for the {@link SimpleMessageConverter} class.
+ *
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ * @since 18.09.2004
+ */
+public final class SimpleMessageConverterTests extends TestCase {
+
+ public void testStringConversion() throws JMSException {
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ MockControl messageControl = MockControl.createControl(TextMessage.class);
+ TextMessage message = (TextMessage) messageControl.getMock();
+
+ String content = "test";
+
+ session.createTextMessage(content);
+ sessionControl.setReturnValue(message, 1);
+ message.getText();
+ messageControl.setReturnValue(content, 1);
+ sessionControl.replay();
+ messageControl.replay();
+
+ SimpleMessageConverter converter = new SimpleMessageConverter();
+ Message msg = converter.toMessage(content, session);
+ assertEquals(content, converter.fromMessage(msg));
+
+ sessionControl.verify();
+ messageControl.verify();
+ }
+
+ public void testByteArrayConversion() throws JMSException {
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ MockControl messageControl = MockControl.createControl(BytesMessage.class);
+ BytesMessage message = (BytesMessage) messageControl.getMock();
+
+ byte[] content = "test".getBytes();
+
+ session.createBytesMessage();
+ sessionControl.setReturnValue(message, 1);
+ message.writeBytes(content);
+ messageControl.setVoidCallable(1);
+ message.getBodyLength();
+ messageControl.setReturnValue(content.length, 1);
+ message.readBytes(new byte[content.length]);
+ messageControl.setMatcher(new ArgumentsMatcher() {
+ public boolean matches(Object[] arg0, Object[] arg1) {
+ byte[] one = (byte[]) arg0[0];
+ byte[] two = (byte[]) arg1[0];
+ return Arrays.equals(one, two);
+ }
+
+ public String toString(Object[] arg0) {
+ return "bla";
+ }
+ });
+ messageControl.setReturnValue(content.length, 1);
+ sessionControl.replay();
+ messageControl.replay();
+
+ SimpleMessageConverter converter = new SimpleMessageConverter();
+ Message msg = converter.toMessage(content, session);
+ assertEquals(content.length, ((byte[]) converter.fromMessage(msg)).length);
+
+ sessionControl.verify();
+ messageControl.verify();
+ }
+
+ public void testMapConversion() throws JMSException {
+
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ MockControl messageControl = MockControl.createControl(MapMessage.class);
+ MapMessage message = (MapMessage) messageControl.getMock();
+
+ Map content = new HashMap();
+ content.put("key1", "value1");
+ content.put("key2", "value2");
+
+ session.createMapMessage();
+ sessionControl.setReturnValue(message, 1);
+ message.setObject("key1", "value1");
+ messageControl.setVoidCallable(1);
+ message.setObject("key2", "value2");
+ messageControl.setVoidCallable(1);
+ message.getMapNames();
+ messageControl.setReturnValue(Collections.enumeration(content.keySet()));
+ message.getObject("key1");
+ messageControl.setReturnValue("value1", 1);
+ message.getObject("key2");
+ messageControl.setReturnValue("value2", 1);
+
+ sessionControl.replay();
+ messageControl.replay();
+
+ SimpleMessageConverter converter = new SimpleMessageConverter();
+ Message msg = converter.toMessage(content, session);
+ assertEquals(content, converter.fromMessage(msg));
+
+ sessionControl.verify();
+ messageControl.verify();
+ }
+
+ public void testSerializableConversion() throws JMSException {
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ MockControl messageControl = MockControl.createControl(ObjectMessage.class);
+ ObjectMessage message = (ObjectMessage) messageControl.getMock();
+
+ Integer content = new Integer(5);
+
+ session.createObjectMessage(content);
+ sessionControl.setReturnValue(message, 1);
+ message.getObject();
+ messageControl.setReturnValue(content, 1);
+ sessionControl.replay();
+ messageControl.replay();
+
+ SimpleMessageConverter converter = new SimpleMessageConverter();
+ Message msg = converter.toMessage(content, session);
+ assertEquals(content, converter.fromMessage(msg));
+
+ sessionControl.verify();
+ messageControl.verify();
+ }
+
+ public void testToMessageThrowsExceptionIfGivenNullObjectToConvert() throws Exception {
+ new AssertThrows(MessageConversionException.class) {
+ public void test() throws Exception {
+ new SimpleMessageConverter().toMessage(null, null);
+ }
+ }.runTest();
+ }
+
+ public void testToMessageThrowsExceptionIfGivenIncompatibleObjectToConvert() throws Exception {
+ new AssertThrows(MessageConversionException.class) {
+ public void test() throws Exception {
+ new SimpleMessageConverter().toMessage(new Object(), null);
+ }
+ }.runTest();
+ }
+
+ public void testToMessageSimplyReturnsMessageAsIsIfSuppliedWithMessage() throws JMSException {
+
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+
+ MockControl messageControl = MockControl.createControl(ObjectMessage.class);
+ ObjectMessage message = (ObjectMessage) messageControl.getMock();
+
+ sessionControl.replay();
+ messageControl.replay();
+
+ SimpleMessageConverter converter = new SimpleMessageConverter();
+ Message msg = converter.toMessage(message, session);
+ assertSame(message, msg);
+
+ sessionControl.verify();
+ messageControl.verify();
+ }
+
+ public void testFromMessageSimplyReturnsMessageAsIsIfSuppliedWithMessage() throws JMSException {
+
+ MockControl messageControl = MockControl.createControl(Message.class);
+ Message message = (Message) messageControl.getMock();
+
+ messageControl.replay();
+
+ SimpleMessageConverter converter = new SimpleMessageConverter();
+ Object msg = converter.fromMessage(message);
+ assertSame(message, msg);
+
+ messageControl.verify();
+ }
+
+ public void testMapConversionWhereMapHasNonStringTypesForKeys() throws JMSException {
+
+ MockControl messageControl = MockControl.createControl(MapMessage.class);
+ MapMessage message = (MapMessage) messageControl.getMock();
+ messageControl.replay();
+
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ session.createMapMessage();
+ sessionControl.setReturnValue(message);
+ sessionControl.replay();
+
+ final Map content = new HashMap();
+ content.put(new Integer(1), "value1");
+
+ final SimpleMessageConverter converter = new SimpleMessageConverter();
+ new AssertThrows(MessageConversionException.class) {
+ public void test() throws Exception {
+ converter.toMessage(content, session);
+ }
+ }.runTest();
+
+ sessionControl.verify();
+ }
+
+ public void testMapConversionWhereMapHasNNullForKey() throws JMSException {
+
+ MockControl messageControl = MockControl.createControl(MapMessage.class);
+ MapMessage message = (MapMessage) messageControl.getMock();
+ messageControl.replay();
+
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ session.createMapMessage();
+ sessionControl.setReturnValue(message);
+ sessionControl.replay();
+
+ final Map content = new HashMap();
+ content.put(null, "value1");
+
+ final SimpleMessageConverter converter = new SimpleMessageConverter();
+ new AssertThrows(MessageConversionException.class) {
+ public void test() throws Exception {
+ converter.toMessage(content, session);
+ }
+ }.runTest();
+
+ sessionControl.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/support/destination/DynamicDestinationResolverTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/support/destination/DynamicDestinationResolverTests.java
new file mode 100644
index 00000000000..e968d8cf28b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/support/destination/DynamicDestinationResolverTests.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jms.support.destination;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Queue;
+import javax.jms.QueueSession;
+import javax.jms.Session;
+import javax.jms.Topic;
+import javax.jms.TopicSession;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.jms.StubQueue;
+import org.springframework.jms.StubTopic;
+
+/**
+ * @author Rick Evans
+ */
+public class DynamicDestinationResolverTests extends TestCase {
+
+ private static final String DESTINATION_NAME = "foo";
+
+
+ public void testResolveWithPubSubTopicSession() throws Exception {
+
+ Topic expectedDestination = new StubTopic();
+
+ MockControl mockSession = MockControl.createControl(TopicSession.class);
+ TopicSession session = (TopicSession) mockSession.getMock();
+ session.createTopic(DESTINATION_NAME);
+ mockSession.setReturnValue(expectedDestination);
+ mockSession.replay();
+
+ testResolveDestination(session, expectedDestination, true);
+
+ mockSession.verify();
+ }
+
+ public void testResolveWithPubSubVanillaSession() throws Exception {
+
+ Topic expectedDestination = new StubTopic();
+
+ MockControl mockSession = MockControl.createControl(Session.class);
+ Session session = (Session) mockSession.getMock();
+ session.createTopic(DESTINATION_NAME);
+ mockSession.setReturnValue(expectedDestination);
+ mockSession.replay();
+
+ testResolveDestination(session, expectedDestination, true);
+
+ mockSession.verify();
+ }
+
+ public void testResolveWithPointToPointQueueSession() throws Exception {
+
+ Queue expectedDestination = new StubQueue();
+
+ MockControl mockSession = MockControl.createControl(QueueSession.class);
+ Session session = (Session) mockSession.getMock();
+ session.createQueue(DESTINATION_NAME);
+ mockSession.setReturnValue(expectedDestination);
+ mockSession.replay();
+
+ testResolveDestination(session, expectedDestination, false);
+
+ mockSession.verify();
+ }
+
+ public void testResolveWithPointToPointVanillaSession() throws Exception {
+
+ Queue expectedDestination = new StubQueue();
+
+ MockControl mockSession = MockControl.createControl(Session.class);
+ Session session = (Session) mockSession.getMock();
+ session.createQueue(DESTINATION_NAME);
+ mockSession.setReturnValue(expectedDestination);
+ mockSession.replay();
+
+ testResolveDestination(session, expectedDestination, false);
+
+ mockSession.verify();
+ }
+
+ private static void testResolveDestination(Session session, Destination expectedDestination, boolean isPubSub) throws JMSException {
+ DynamicDestinationResolver resolver = new DynamicDestinationResolver();
+ Destination destination = resolver.resolveDestinationName(session, DESTINATION_NAME, isPubSub);
+ assertNotNull(destination);
+ assertSame(expectedDestination, destination);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/support/destination/JmsDestinationAccessorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/support/destination/JmsDestinationAccessorTests.java
new file mode 100644
index 00000000000..80a16af6005
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/support/destination/JmsDestinationAccessorTests.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jms.support.destination;
+
+import javax.jms.ConnectionFactory;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Rick Evans
+ */
+public class JmsDestinationAccessorTests extends TestCase {
+
+ public void testChokesIfDestinationResolverIsetToNullExplcitly() throws Exception {
+ MockControl mockConnectionFactory = MockControl.createControl(ConnectionFactory.class);
+ final ConnectionFactory connectionFactory = (ConnectionFactory) mockConnectionFactory.getMock();
+ mockConnectionFactory.replay();
+
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ JmsDestinationAccessor accessor = new StubJmsDestinationAccessor();
+ accessor.setConnectionFactory(connectionFactory);
+ accessor.setDestinationResolver(null);
+ accessor.afterPropertiesSet();
+ }
+ }.runTest();
+
+ mockConnectionFactory.verify();
+ }
+
+ public void testSessionTransactedModeReallyDoesDefaultToFalse() throws Exception {
+ JmsDestinationAccessor accessor = new StubJmsDestinationAccessor();
+ assertFalse("The [pubSubDomain] property of JmsDestinationAccessor must default to " +
+ "false (i.e. Queues are used by default). Change this test (and the " +
+ "attendant Javadoc) if you have changed the default.",
+ accessor.isPubSubDomain());
+ }
+
+
+ private static class StubJmsDestinationAccessor extends JmsDestinationAccessor {
+
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jms/support/destination/JndiDestinationResolverTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jms/support/destination/JndiDestinationResolverTests.java
new file mode 100644
index 00000000000..8e1b3ee71fb
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jms/support/destination/JndiDestinationResolverTests.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jms.support.destination;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.test.AssertThrows;
+import org.springframework.jms.StubTopic;
+
+import javax.jms.Destination;
+import javax.jms.Session;
+import javax.naming.NamingException;
+
+/**
+ * @author Rick Evans
+ */
+public class JndiDestinationResolverTests extends TestCase {
+
+ private static final String DESTINATION_NAME = "foo";
+
+ private static final Destination DESTINATION = new StubTopic();
+
+
+ public void testHitsCacheSecondTimeThrough() throws Exception {
+
+ MockControl mockSession = MockControl.createControl(Session.class);
+ Session session = (Session) mockSession.getMock();
+ mockSession.replay();
+
+ JndiDestinationResolver resolver = new OneTimeLookupJndiDestinationResolver();
+ Destination destination = resolver.resolveDestinationName(session, DESTINATION_NAME, true);
+ assertNotNull(destination);
+ assertSame(DESTINATION, destination);
+
+ mockSession.verify();
+ }
+
+ public void testDoesNotUseCacheIfCachingIsTurnedOff() throws Exception {
+
+ MockControl mockSession = MockControl.createControl(Session.class);
+ Session session = (Session) mockSession.getMock();
+ mockSession.replay();
+
+ CountingCannedJndiDestinationResolver resolver
+ = new CountingCannedJndiDestinationResolver();
+ resolver.setCache(false);
+ Destination destination = resolver.resolveDestinationName(session, DESTINATION_NAME, true);
+ assertNotNull(destination);
+ assertSame(DESTINATION, destination);
+ assertEquals(1, resolver.getCallCount());
+
+ destination = resolver.resolveDestinationName(session, DESTINATION_NAME, true);
+ assertNotNull(destination);
+ assertSame(DESTINATION, destination);
+ assertEquals(2, resolver.getCallCount());
+
+ mockSession.verify();
+ }
+
+ public void testDelegatesToFallbackIfNotResolvedInJndi() throws Exception {
+ MockControl mockSession = MockControl.createControl(Session.class);
+ Session session = (Session) mockSession.getMock();
+ mockSession.replay();
+
+ MockControl mockDestinationResolver = MockControl.createControl(DestinationResolver.class);
+ DestinationResolver dynamicResolver = (DestinationResolver) mockDestinationResolver.getMock();
+ dynamicResolver.resolveDestinationName(session, DESTINATION_NAME, true);
+ mockDestinationResolver.setReturnValue(DESTINATION);
+ mockDestinationResolver.replay();
+
+ JndiDestinationResolver resolver = new JndiDestinationResolver() {
+ protected Object lookup(String jndiName, Class requiredClass) throws NamingException {
+ throw new NamingException();
+ }
+ };
+ resolver.setFallbackToDynamicDestination(true);
+ resolver.setDynamicDestinationResolver(dynamicResolver);
+ Destination destination = resolver.resolveDestinationName(session, DESTINATION_NAME, true);
+
+ assertNotNull(destination);
+ assertSame(DESTINATION, destination);
+
+ mockSession.verify();
+ mockDestinationResolver.verify();
+ }
+
+ public void testDoesNotDelegateToFallbackIfNotResolvedInJndi() throws Exception {
+ MockControl mockSession = MockControl.createControl(Session.class);
+ final Session session = (Session) mockSession.getMock();
+ mockSession.replay();
+
+ MockControl mockDestinationResolver = MockControl.createControl(DestinationResolver.class);
+ DestinationResolver dynamicResolver = (DestinationResolver) mockDestinationResolver.getMock();
+ mockDestinationResolver.replay();
+
+ final JndiDestinationResolver resolver = new JndiDestinationResolver() {
+ protected Object lookup(String jndiName, Class requiredClass) throws NamingException {
+ throw new NamingException();
+ }
+ };
+ resolver.setDynamicDestinationResolver(dynamicResolver);
+
+ new AssertThrows(DestinationResolutionException.class) {
+ public void test() throws Exception {
+ resolver.resolveDestinationName(session, DESTINATION_NAME, true);
+ }
+ }.runTest();
+
+ mockSession.verify();
+ mockDestinationResolver.verify();
+ }
+
+
+ private static class OneTimeLookupJndiDestinationResolver extends JndiDestinationResolver {
+
+ private boolean called;
+
+ protected Object lookup(String jndiName, Class requiredType) throws NamingException {
+ if (called) {
+ fail("Must not be delegating to lookup(..), must be resolving from cache.");
+ }
+ assertEquals(DESTINATION_NAME, jndiName);
+ called = true;
+ return DESTINATION;
+ }
+ }
+
+ private static class CountingCannedJndiDestinationResolver extends JndiDestinationResolver {
+
+ private int callCount;
+
+ public int getCallCount() {
+ return this.callCount;
+ }
+
+ protected Object lookup(String jndiName, Class requiredType) throws NamingException {
+ ++this.callCount;
+ return DESTINATION;
+ }
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/AbstractJmxTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/AbstractJmxTests.java
new file mode 100644
index 00000000000..bb94cbe364a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/AbstractJmxTests.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jmx;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+
+/**
+ * Base JMX test class that pre-loads an ApplicationContext from a user-configurable file. Override the
+ * {@link #getApplicationContextPath()} method to control the configuration file location.
+ *
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public abstract class AbstractJmxTests extends AbstractMBeanServerTests {
+
+ private ConfigurableApplicationContext ctx;
+
+
+ protected final void onSetUp() throws Exception {
+ ctx = loadContext(getApplicationContextPath());
+ }
+
+ protected final void onTearDown() throws Exception {
+ if (ctx != null) {
+ ctx.close();
+ }
+ }
+
+ protected String getApplicationContextPath() {
+ return "org/springframework/jmx/applicationContext.xml";
+ }
+
+ protected ApplicationContext getContext() {
+ return this.ctx;
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/AbstractMBeanServerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/AbstractMBeanServerTests.java
new file mode 100644
index 00000000000..5ea36a20042
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/AbstractMBeanServerTests.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jmx;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.support.GenericApplicationContext;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public abstract class AbstractMBeanServerTests extends TestCase {
+
+ protected MBeanServer server;
+
+ public final void setUp() throws Exception {
+ this.server = MBeanServerFactory.createMBeanServer();
+ try {
+ onSetUp();
+ }
+ catch (Exception ex) {
+ releaseServer();
+ throw ex;
+ }
+ }
+
+ protected ConfigurableApplicationContext loadContext(String configLocation) {
+ GenericApplicationContext ctx = new GenericApplicationContext();
+ new XmlBeanDefinitionReader(ctx).loadBeanDefinitions(configLocation);
+ ctx.getDefaultListableBeanFactory().registerSingleton("server", this.server);
+ ctx.refresh();
+ return ctx;
+ }
+
+ protected void tearDown() throws Exception {
+ releaseServer();
+ onTearDown();
+ }
+
+ private void releaseServer() {
+ MBeanServerFactory.releaseMBeanServer(getServer());
+ }
+
+ protected void onTearDown() throws Exception {
+ }
+
+ protected void onSetUp() throws Exception {
+ }
+
+ public MBeanServer getServer() {
+ return this.server;
+ }
+
+ protected void assertIsRegistered(String message, ObjectName objectName) {
+ assertTrue(message, getServer().isRegistered(objectName));
+ }
+
+ protected void assertIsNotRegistered(String message, ObjectName objectName) {
+ assertFalse(message, getServer().isRegistered(objectName));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/IJmxTestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/IJmxTestBean.java
new file mode 100644
index 00000000000..74d579fb8a7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/IJmxTestBean.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jmx;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public interface IJmxTestBean {
+
+ public int add(int x, int y);
+
+ public long myOperation();
+
+ public int getAge();
+
+ public void setAge(int age);
+
+ public void setName(String name) throws Exception;
+
+ public String getName();
+
+ // used to test invalid methods that exist in the proxy interface
+ public void dontExposeMe();
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/JmxTestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/JmxTestBean.java
new file mode 100644
index 00000000000..e73f6106c76
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/JmxTestBean.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jmx;
+
+import java.io.IOException;
+
+/**
+ * @@org.springframework.jmx.export.metadata.ManagedResource
+ * (description="My Managed Bean", objectName="spring:bean=test",
+ * log=true, logFile="jmx.log", currencyTimeLimit=15, persistPolicy="OnUpdate",
+ * persistPeriod=200, persistLocation="./foo", persistName="bar.jmx")
+ * @@org.springframework.jmx.export.metadata.ManagedNotification
+ * (name="My Notification", description="A Notification", notificationType="type.foo,type.bar")
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class JmxTestBean implements IJmxTestBean {
+
+ private String name;
+
+ private String nickName;
+
+ private int age;
+
+ private boolean isSuperman;
+
+
+ /**
+ * @@org.springframework.jmx.export.metadata.ManagedAttribute
+ * (description="The Age Attribute", currencyTimeLimit=15)
+ */
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ /**
+ * @@org.springframework.jmx.export.metadata.ManagedOperation(currencyTimeLimit=30)
+ */
+ public long myOperation() {
+ return 1L;
+ }
+
+ /**
+ * @@org.springframework.jmx.export.metadata.ManagedAttribute
+ * (description="The Name Attribute", currencyTimeLimit=20,
+ * defaultValue="bar", persistPolicy="OnUpdate")
+ */
+ public void setName(String name) throws Exception {
+ if ("Juergen".equals(name)) {
+ throw new IllegalArgumentException("Juergen");
+ }
+ if ("Juergen Class".equals(name)) {
+ throw new ClassNotFoundException("Juergen");
+ }
+ if ("Juergen IO".equals(name)) {
+ throw new IOException("Juergen");
+ }
+ this.name = name;
+ }
+
+ /**
+ * @@org.springframework.jmx.export.metadata.ManagedAttribute
+ * (defaultValue="foo", persistPeriod=300)
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @@org.springframework.jmx.export.metadata.ManagedAttribute(description="The Nick
+ * Name
+ * Attribute")
+ */
+ public void setNickName(String nickName) {
+ this.nickName = nickName;
+ }
+
+ public String getNickName() {
+ return this.nickName;
+ }
+
+ public void setSuperman(boolean superman) {
+ this.isSuperman = superman;
+ }
+
+ /**
+ * @@org.springframework.jmx.export.metadata.ManagedAttribute(description="The Is
+ * Superman
+ * Attribute")
+ */
+ public boolean isSuperman() {
+ return isSuperman;
+ }
+
+ /**
+ * @@org.springframework.jmx.export.metadata.ManagedOperation(description="Add Two
+ * Numbers
+ * Together")
+ * @@org.springframework.jmx.export.metadata.ManagedOperationParameter(index=0, name="x", description="Left operand")
+ * @@org.springframework.jmx.export.metadata.ManagedOperationParameter(index=1, name="y", description="Right operand")
+ */
+ public int add(int x, int y) {
+ return x + y;
+ }
+
+ /**
+ * Test method that is not exposed by the MetadataAssembler.
+ */
+ public void dontExposeMe() {
+ throw new RuntimeException();
+ }
+
+ protected void someProtectedMethod() {
+ }
+
+ private void somePrivateMethod() {
+ }
+
+ protected void getSomething() {
+ }
+
+ private void getSomethingElse() {
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/access/CommonsAttributesMBeanProxyFactoryBeanTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/access/CommonsAttributesMBeanProxyFactoryBeanTests.java
new file mode 100644
index 00000000000..db05ccd709f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/access/CommonsAttributesMBeanProxyFactoryBeanTests.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jmx.access;
+
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.jmx.AbstractJmxTests;
+import org.springframework.jmx.IJmxTestBean;
+import org.springframework.jmx.support.ObjectNameManager;
+
+/**
+ * Tests creation of JMX MBean proxies.
+ *
+ * @author Rob Harrop
+ */
+public class CommonsAttributesMBeanProxyFactoryBeanTests extends AbstractJmxTests {
+
+ private static final String OBJECT_NAME = "bean:name=testBean1";
+
+ protected ObjectName getObjectName() throws Exception {
+ return ObjectNameManager.getInstance(OBJECT_NAME);
+ }
+
+ public void testProxyFactory() throws Exception {
+ MBeanProxyFactoryBean fb = getProxyFactory();
+ fb.setProxyInterface(IJmxTestBean.class);
+ fb.afterPropertiesSet();
+
+ IJmxTestBean bean = (IJmxTestBean) fb.getObject();
+ assertNotNull("Proxy should not be null", bean);
+ }
+
+ public void testInvalidJdkProxy() throws Exception {
+ MBeanProxyFactoryBean fb = getProxyFactory();
+ try {
+ fb.afterPropertiesSet();
+ fail("Should not be able to create JDK proxy with no proxy interfaces");
+ }
+ catch (Exception ex) {
+ // expected
+ }
+ }
+
+ public void testWithLocatedMBeanServer() throws Exception {
+ MBeanProxyFactoryBean fb = new MBeanProxyFactoryBean();
+ fb.setProxyInterface(IJmxTestBean.class);
+ fb.setObjectName(OBJECT_NAME);
+ fb.afterPropertiesSet();
+ IJmxTestBean proxy = (IJmxTestBean)fb.getObject();
+ assertNotNull("Proxy should not be null", proxy);
+ assertEquals("Incorrect name value", "TEST", proxy.getName());
+ }
+
+ public void testProxyFactoryBeanWithAutodetect() throws Exception {
+ try {
+ XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("proxyFactoryBean.xml", getClass()));
+ bf.preInstantiateSingletons();
+ }
+ catch (BeanCreationException ex) {
+ if (ex.getCause().getClass() == MBeanInfoRetrievalException.class) {
+ fail("MBeanProxyFactoryBean should be ignored by MBeanExporter when running autodetect process");
+ }
+ else {
+ throw ex;
+ }
+ }
+ }
+
+ private MBeanProxyFactoryBean getProxyFactory() throws MalformedObjectNameException {
+ MBeanProxyFactoryBean fb = new MBeanProxyFactoryBean();
+ fb.setServer(getServer());
+ fb.setObjectName(OBJECT_NAME);
+ return fb;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/access/MBeanClientInterceptorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/access/MBeanClientInterceptorTests.java
new file mode 100644
index 00000000000..bb8dd6619cb
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/access/MBeanClientInterceptorTests.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jmx.access;
+
+import java.beans.PropertyDescriptor;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.net.BindException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.management.Descriptor;
+import javax.management.MBeanServerConnection;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+
+import org.springframework.jmx.AbstractMBeanServerTests;
+import org.springframework.jmx.IJmxTestBean;
+import org.springframework.jmx.JmxException;
+import org.springframework.jmx.JmxTestBean;
+import org.springframework.jmx.export.MBeanExporter;
+import org.springframework.jmx.export.assembler.AbstractReflectiveMBeanInfoAssembler;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class MBeanClientInterceptorTests extends AbstractMBeanServerTests {
+
+ protected static final String OBJECT_NAME = "spring:test=proxy";
+
+ protected JmxTestBean target;
+
+ protected boolean runTests = true;
+
+ public void onSetUp() throws Exception {
+ target = new JmxTestBean();
+ target.setAge(100);
+ target.setName("Rob Harrop");
+
+ MBeanExporter adapter = new MBeanExporter();
+ Map beans = new HashMap();
+ beans.put(OBJECT_NAME, target);
+ adapter.setServer(getServer());
+ adapter.setBeans(beans);
+ adapter.setAssembler(new ProxyTestAssembler());
+ adapter.afterPropertiesSet();
+ }
+
+ protected MBeanServerConnection getServerConnection() throws Exception {
+ return getServer();
+ }
+
+ protected IJmxTestBean getProxy() throws Exception {
+ MBeanProxyFactoryBean factory = new MBeanProxyFactoryBean();
+ factory.setServer(getServerConnection());
+ factory.setProxyInterface(IJmxTestBean.class);
+ factory.setObjectName(OBJECT_NAME);
+ factory.afterPropertiesSet();
+ return (IJmxTestBean) factory.getObject();
+ }
+
+ public void testProxyClassIsDifferent() throws Exception {
+ if (!runTests) return;
+ IJmxTestBean proxy = getProxy();
+ assertTrue("The proxy class should be different than the base class",
+ (proxy.getClass() != IJmxTestBean.class));
+ }
+
+ public void testDifferentProxiesSameClass() throws Exception {
+ if (!runTests) return;
+ IJmxTestBean proxy1 = getProxy();
+ IJmxTestBean proxy2 = getProxy();
+
+ assertNotSame("The proxies should NOT be the same", proxy1, proxy2);
+ assertSame("The proxy classes should be the same", proxy1.getClass(), proxy2.getClass());
+ }
+
+ public void testGetAttributeValue() throws Exception {
+ if (!runTests) return;
+ IJmxTestBean proxy1 = getProxy();
+ int age = proxy1.getAge();
+ assertEquals("The age should be 100", 100, age);
+ }
+
+ public void testSetAttributeValue() throws Exception {
+ if (!runTests) return;
+ IJmxTestBean proxy = getProxy();
+ proxy.setName("Rob Harrop");
+ assertEquals("The name of the bean should have been updated", "Rob Harrop", target.getName());
+ }
+
+ public void testSetAttributeValueWithRuntimeException() throws Exception {
+ if (!runTests) return;
+ IJmxTestBean proxy = getProxy();
+ try {
+ proxy.setName("Juergen");
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ public void testSetAttributeValueWithCheckedException() throws Exception {
+ if (!runTests) return;
+ IJmxTestBean proxy = getProxy();
+ try {
+ proxy.setName("Juergen Class");
+ fail("Should have thrown ClassNotFoundException");
+ }
+ catch (ClassNotFoundException ex) {
+ // expected
+ }
+ }
+
+ public void testSetAttributeValueWithIOException() throws Exception {
+ if (!runTests) return;
+ IJmxTestBean proxy = getProxy();
+ try {
+ proxy.setName("Juergen IO");
+ fail("Should have thrown IOException");
+ }
+ catch (IOException ex) {
+ // expected
+ }
+ }
+
+ public void testSetReadOnlyAttribute() throws Exception {
+ if (!runTests) return;
+ IJmxTestBean proxy = getProxy();
+ try {
+ proxy.setAge(900);
+ fail("Should not be able to write to a read only attribute");
+ }
+ catch (InvalidInvocationException ex) {
+ // success
+ }
+ }
+
+ public void testInvokeNoArgs() throws Exception {
+ if (!runTests) return;
+ IJmxTestBean proxy = getProxy();
+ long result = proxy.myOperation();
+ assertEquals("The operation should return 1", 1, result);
+ }
+
+ public void testInvokeArgs() throws Exception {
+ if (!runTests) return;
+ IJmxTestBean proxy = getProxy();
+ int result = proxy.add(1, 2);
+ assertEquals("The operation should return 3", 3, result);
+ }
+
+ public void testInvokeUnexposedMethodWithException() throws Exception {
+ if (!runTests) return;
+ IJmxTestBean bean = getProxy();
+ try {
+ bean.dontExposeMe();
+ fail("Method dontExposeMe should throw an exception");
+ }
+ catch (InvalidInvocationException desired) {
+ // success
+ }
+ }
+
+ public void testLazyConnectionToRemote() throws Exception {
+ if (!runTests) return;
+
+ JMXServiceURL url = new JMXServiceURL("service:jmx:jmxmp://localhost:9876");
+ JMXConnectorServer connector = JMXConnectorServerFactory.newJMXConnectorServer(url, null, getServer());
+
+ MBeanProxyFactoryBean factory = new MBeanProxyFactoryBean();
+ factory.setServiceUrl(url.toString());
+ factory.setProxyInterface(IJmxTestBean.class);
+ factory.setObjectName(OBJECT_NAME);
+ factory.setConnectOnStartup(false);
+ factory.setRefreshOnConnectFailure(true);
+ // should skip connection to the server
+ factory.afterPropertiesSet();
+ IJmxTestBean bean = (IJmxTestBean) factory.getObject();
+
+ // now start the connector
+ try {
+ connector.start();
+ }
+ catch (BindException ex) {
+ // couldn't bind to local port 9876 - let's skip the remainder of this test
+ System.out.println(
+ "Skipping JMX LazyConnectionToRemote test because binding to local port 9876 failed: " +
+ ex.getMessage());
+ return;
+ }
+
+ // should now be able to access data via the lazy proxy
+ try {
+ assertEquals("Rob Harrop", bean.getName());
+ assertEquals(100, bean.getAge());
+ }
+ finally {
+ connector.stop();
+ }
+
+ try {
+ bean.getName();
+ }
+ catch (JmxException ex) {
+ // expected
+ }
+
+ connector = JMXConnectorServerFactory.newJMXConnectorServer(url, null, getServer());
+ connector.start();
+
+ // should now be able to access data via the lazy proxy
+ try {
+ assertEquals("Rob Harrop", bean.getName());
+ assertEquals(100, bean.getAge());
+ }
+ finally {
+ connector.stop();
+ }
+ }
+
+ // Commented out because of a side effect with the the started platform MBeanServer.
+ /*
+ public void testMXBeanAttributeAccess() throws Exception {
+ if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_15) {
+ return;
+ }
+
+ MBeanClientInterceptor interceptor = new MBeanClientInterceptor();
+ interceptor.setServer(ManagementFactory.getPlatformMBeanServer());
+ interceptor.setObjectName("java.lang:type=Memory");
+ interceptor.setManagementInterface(MemoryMXBean.class);
+ MemoryMXBean proxy = (MemoryMXBean) ProxyFactory.getProxy(MemoryMXBean.class, interceptor);
+ assertTrue(proxy.getHeapMemoryUsage().getMax() > 0);
+ }
+
+ public void testMXBeanOperationAccess() throws Exception {
+ if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_15) {
+ return;
+ }
+
+ MBeanClientInterceptor interceptor = new MBeanClientInterceptor();
+ interceptor.setServer(ManagementFactory.getPlatformMBeanServer());
+ interceptor.setObjectName("java.lang:type=Threading");
+ ThreadMXBean proxy = (ThreadMXBean) ProxyFactory.getProxy(ThreadMXBean.class, interceptor);
+ assertTrue(proxy.getThreadInfo(Thread.currentThread().getId()).getStackTrace() != null);
+ }
+ */
+
+
+ private static class ProxyTestAssembler extends AbstractReflectiveMBeanInfoAssembler {
+
+ protected boolean includeReadAttribute(Method method, String beanKey) {
+ return true;
+ }
+
+ protected boolean includeWriteAttribute(Method method, String beanKey) {
+ if ("setAge".equals(method.getName())) {
+ return false;
+ }
+ return true;
+ }
+
+ protected boolean includeOperation(Method method, String beanKey) {
+ if ("dontExposeMe".equals(method.getName())) {
+ return false;
+ }
+ return true;
+ }
+
+ protected String getOperationDescription(Method method) {
+ return method.getName();
+ }
+
+ protected String getAttributeDescription(PropertyDescriptor propertyDescriptor) {
+ return propertyDescriptor.getDisplayName();
+ }
+
+ protected void populateAttributeDescriptor(Descriptor descriptor, Method getter, Method setter) {
+
+ }
+
+ protected void populateOperationDescriptor(Descriptor descriptor, Method method) {
+
+ }
+
+ protected String getDescription(String beanKey, Class beanClass) {
+ return "";
+ }
+
+ protected void populateMBeanDescriptor(Descriptor mbeanDescriptor, String beanKey, Class beanClass) {
+
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/access/RemoteMBeanClientInterceptorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/access/RemoteMBeanClientInterceptorTests.java
new file mode 100644
index 00000000000..86d59b300a4
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/access/RemoteMBeanClientInterceptorTests.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jmx.access;
+
+import java.net.BindException;
+import java.net.MalformedURLException;
+
+import javax.management.MBeanServerConnection;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+
+/**
+ * @author Rob Harrop
+ */
+public class RemoteMBeanClientInterceptorTests extends MBeanClientInterceptorTests {
+
+ private static final String SERVICE_URL = "service:jmx:jmxmp://localhost:9876";
+
+ private JMXConnectorServer connectorServer;
+
+ private JMXConnector connector;
+
+ public void onSetUp() throws Exception {
+ super.onSetUp();
+ this.connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(getServiceUrl(), null, getServer());
+ try {
+ this.connectorServer.start();
+ }
+ catch (BindException ex) {
+ // skipping tests, server already running at this port
+ runTests = false;
+ }
+ }
+
+ private JMXServiceURL getServiceUrl() throws MalformedURLException {
+ return new JMXServiceURL(SERVICE_URL);
+ }
+
+ protected MBeanServerConnection getServerConnection() throws Exception {
+ this.connector = JMXConnectorFactory.connect(getServiceUrl());
+ return this.connector.getMBeanServerConnection();
+ }
+
+ public void tearDown() throws Exception {
+ if (this.connector != null) {
+ this.connector.close();
+ }
+ this.connectorServer.stop();
+ super.tearDown();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/access/proxyFactoryBean.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/access/proxyFactoryBean.xml
new file mode 100644
index 00000000000..d7d5254f1c3
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/access/proxyFactoryBean.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.springframework.jmx.IJmxTestBean
+
+
+ bean:name=proxyTestBean1
+
+
+
+
+
+ TEST
+
+
+ 100
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/applicationContext.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/applicationContext.xml
new file mode 100644
index 00000000000..d9a4d10cc79
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/applicationContext.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TEST
+
+
+ 100
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/CustomEditorConfigurerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/CustomEditorConfigurerTests.java
new file mode 100644
index 00000000000..24211666e19
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/CustomEditorConfigurerTests.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jmx.export;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import javax.management.ObjectName;
+
+import org.springframework.jmx.AbstractJmxTests;
+
+/**
+ * @author Rob Harrop
+ */
+public class CustomEditorConfigurerTests extends AbstractJmxTests {
+
+ private final SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd");
+
+ protected String getApplicationContextPath() {
+ return "org/springframework/jmx/export/customConfigurer.xml";
+ }
+
+ public void testDatesInJmx() throws Exception {
+ System.out.println(getServer().getClass().getName());
+ ObjectName oname = new ObjectName("bean:name=dateRange");
+
+ Date startJmx = (Date) getServer().getAttribute(oname, "StartDate");
+ Date endJmx = (Date) getServer().getAttribute(oname, "EndDate");
+
+ assertEquals("startDate ", getStartDate(), startJmx);
+ assertEquals("endDate ", getEndDate(), endJmx);
+ }
+
+ public void testGetDates() throws Exception {
+ DateRange dr = (DateRange) getContext().getBean("dateRange");
+
+ assertEquals("startDate ", getStartDate(), dr.getStartDate());
+ assertEquals("endDate ", getEndDate(), dr.getEndDate());
+ }
+
+ private Date getStartDate() throws ParseException {
+ Date start = df.parse("2004/10/12");
+ return start;
+ }
+
+ private Date getEndDate() throws ParseException {
+ Date end = df.parse("2004/11/13");
+ return end;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/DateRange.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/DateRange.java
new file mode 100644
index 00000000000..8b2feda1481
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/DateRange.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jmx.export;
+
+import java.util.Date;
+
+/**
+ * @author Rob Harrop
+ */
+public class DateRange {
+
+ private Date startDate;
+
+ private Date endDate;
+
+ public Date getStartDate() {
+ return startDate;
+ }
+
+ public void setStartDate(Date startDate) {
+ this.startDate = startDate;
+ }
+
+ public Date getEndDate() {
+ return endDate;
+ }
+
+ public void setEndDate(Date endDate) {
+ this.endDate = endDate;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/ExceptionOnInitBean.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/ExceptionOnInitBean.java
new file mode 100644
index 00000000000..4733ef89d9c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/ExceptionOnInitBean.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jmx.export;
+
+/**
+ * @author Rob Harrop
+ */
+public class ExceptionOnInitBean {
+
+ private boolean exceptOnInit = false;
+
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setExceptOnInit(boolean exceptOnInit) {
+ this.exceptOnInit = exceptOnInit;
+ }
+
+ public ExceptionOnInitBean() {
+ if (exceptOnInit) {
+ throw new RuntimeException("I am being init'd!");
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/LazyInitMBeanTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/LazyInitMBeanTests.java
new file mode 100644
index 00000000000..9410c609b01
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/LazyInitMBeanTests.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jmx.export;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import junit.framework.TestCase;
+
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.jmx.support.ObjectNameManager;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class LazyInitMBeanTests extends TestCase {
+
+ public void testLazyInit() {
+ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(getApplicationContextPath());
+ ctx.close();
+ }
+
+ public void testInvokeOnLazyInitBean() throws Exception {
+ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(getApplicationContextPath());
+ assertFalse(ctx.getBeanFactory().containsSingleton("testBean"));
+ assertFalse(ctx.getBeanFactory().containsSingleton("testBean2"));
+ try {
+ MBeanServer server = (MBeanServer) ctx.getBean("server");
+ ObjectName oname = ObjectNameManager.getInstance("bean:name=testBean2");
+ String name = (String) server.getAttribute(oname, "Name");
+ assertEquals("Invalid name returned", "foo", name);
+ }
+ finally {
+ ctx.close();
+ }
+ }
+
+ private String getApplicationContextPath() {
+ return "org/springframework/jmx/export/lazyInit.xml";
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/MBeanExporterOperationsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/MBeanExporterOperationsTests.java
new file mode 100644
index 00000000000..d95c6b4f28b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/MBeanExporterOperationsTests.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jmx.export;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+import javax.management.MBeanInfo;
+import javax.management.modelmbean.RequiredModelMBean;
+import javax.management.modelmbean.ModelMBeanInfo;
+import javax.management.modelmbean.ModelMBeanInfoSupport;
+
+import org.springframework.jmx.AbstractMBeanServerTests;
+import org.springframework.jmx.JmxTestBean;
+import org.springframework.jmx.export.naming.ObjectNamingStrategy;
+import org.springframework.jmx.support.ObjectNameManager;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class MBeanExporterOperationsTests extends AbstractMBeanServerTests {
+
+ public void testRegisterManagedResourceWithUserSuppliedObjectName() throws Exception {
+ ObjectName objectName = ObjectNameManager.getInstance("spring:name=Foo");
+
+ JmxTestBean bean = new JmxTestBean();
+ bean.setName("Rob Harrop");
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(getServer());
+ exporter.registerManagedResource(bean, objectName);
+
+ String name = (String) getServer().getAttribute(objectName, "Name");
+ assertEquals("Incorrect name on MBean", name, bean.getName());
+ }
+
+ public void testRegisterExistingMBeanWithUserSuppliedObjectName() throws Exception {
+ ObjectName objectName = ObjectNameManager.getInstance("spring:name=Foo");
+ ModelMBeanInfo info = new ModelMBeanInfoSupport("myClass", "myDescription", null, null, null, null);
+ RequiredModelMBean bean = new RequiredModelMBean(info);
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(getServer());
+ exporter.registerManagedResource(bean, objectName);
+
+ MBeanInfo infoFromServer = getServer().getMBeanInfo(objectName);
+ assertEquals(info, infoFromServer);
+ }
+
+ public void testRegisterManagedResourceWithGeneratedObjectName() throws Exception {
+ final ObjectName objectNameTemplate = ObjectNameManager.getInstance("spring:type=Test");
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(getServer());
+ exporter.setNamingStrategy(new ObjectNamingStrategy() {
+ public ObjectName getObjectName(Object managedBean, String beanKey) {
+ return objectNameTemplate;
+ }
+ });
+
+ JmxTestBean bean1 = new JmxTestBean();
+ JmxTestBean bean2 = new JmxTestBean();
+
+ ObjectName reg1 = exporter.registerManagedResource(bean1);
+ ObjectName reg2 = exporter.registerManagedResource(bean2);
+
+ assertIsRegistered("Bean 1 not registered with MBeanServer", reg1);
+ assertIsRegistered("Bean 2 not registered with MBeanServer", reg2);
+
+ assertObjectNameMatchesTemplate(objectNameTemplate, reg1);
+ assertObjectNameMatchesTemplate(objectNameTemplate, reg2);
+ }
+
+ public void testRegisterManagedResourceWithGeneratedObjectNameWithoutUniqueness() throws Exception {
+ final ObjectName objectNameTemplate = ObjectNameManager.getInstance("spring:type=Test");
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(getServer());
+ exporter.setEnsureUniqueRuntimeObjectNames(false);
+ exporter.setNamingStrategy(new ObjectNamingStrategy() {
+ public ObjectName getObjectName(Object managedBean, String beanKey) {
+ return objectNameTemplate;
+ }
+ });
+
+ JmxTestBean bean1 = new JmxTestBean();
+ JmxTestBean bean2 = new JmxTestBean();
+
+ ObjectName reg1 = exporter.registerManagedResource(bean1);
+ assertIsRegistered("Bean 1 not registered with MBeanServer", reg1);
+
+ try {
+ exporter.registerManagedResource(bean2);
+ fail("Shouldn't be able to register a runtime MBean with a reused ObjectName.");
+ }
+ catch (MBeanExportException e) {
+ assertEquals("Incorrect root cause", InstanceAlreadyExistsException.class, e.getCause().getClass());
+ }
+ }
+
+ private void assertObjectNameMatchesTemplate(ObjectName objectNameTemplate, ObjectName registeredName) {
+ assertEquals("Domain is incorrect", objectNameTemplate.getDomain(), registeredName.getDomain());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/MBeanExporterTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/MBeanExporterTests.java
new file mode 100644
index 00000000000..1005694df80
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/MBeanExporterTests.java
@@ -0,0 +1,760 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jmx.export;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.management.Attribute;
+import javax.management.InstanceNotFoundException;
+import javax.management.JMException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+import javax.management.modelmbean.ModelMBeanInfo;
+
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.aop.interceptor.NopInterceptor;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.jmx.AbstractMBeanServerTests;
+import org.springframework.jmx.IJmxTestBean;
+import org.springframework.jmx.JmxTestBean;
+import org.springframework.jmx.export.assembler.AutodetectCapableMBeanInfoAssembler;
+import org.springframework.jmx.export.assembler.MBeanInfoAssembler;
+import org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler;
+import org.springframework.jmx.export.naming.SelfNaming;
+import org.springframework.jmx.support.ObjectNameManager;
+
+/**
+ * Integration tests for the MBeanExporter class.
+ *
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ * @author Mark Fisher
+ */
+public class MBeanExporterTests extends AbstractMBeanServerTests {
+
+ private static final String OBJECT_NAME = "spring:test=jmxMBeanAdaptor";
+
+
+ public void testRegisterNonNotificationListenerType() throws Exception {
+ Map listeners = new HashMap();
+ // put a non-NotificationListener instance in as a value...
+ listeners.put("*", this);
+ MBeanExporter exporter = new MBeanExporter();
+ try {
+ exporter.setNotificationListenerMappings(listeners);
+ fail("Must have thrown an IllegalArgumentException when registering a non-NotificationListener instance as a NotificationListener.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testRegisterNullNotificationListenerType() throws Exception {
+ Map listeners = new HashMap();
+ // put null in as a value...
+ listeners.put("*", null);
+ MBeanExporter exporter = new MBeanExporter();
+ try {
+ exporter.setNotificationListenerMappings(listeners);
+ fail("Must have thrown an IllegalArgumentException when registering a null instance as a NotificationListener.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testRegisterNotificationListenerForNonExistentMBean() throws Exception {
+ Map listeners = new HashMap();
+ NotificationListener dummyListener = new NotificationListener() {
+ public void handleNotification(Notification notification, Object handback) {
+ throw new UnsupportedOperationException();
+ }
+ };
+ // the MBean with the supplied object name does not exist...
+ listeners.put("spring:type=Test", dummyListener);
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setBeans(getBeanMap());
+ exporter.setServer(server);
+ exporter.setNotificationListenerMappings(listeners);
+ try {
+ exporter.afterPropertiesSet();
+ fail("Must have thrown an MBeanExportException when registering a NotificationListener on a non-existent MBean.");
+ }
+ catch (MBeanExportException expected) {
+ assertTrue(expected.contains(InstanceNotFoundException.class));
+ }
+ }
+
+ public void testWithSuppliedMBeanServer() throws Exception {
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setBeans(getBeanMap());
+ exporter.setServer(server);
+ exporter.afterPropertiesSet();
+ assertIsRegistered("The bean was not registered with the MBeanServer", ObjectNameManager.getInstance(OBJECT_NAME));
+ }
+
+ /** Fails if JVM platform MBean server has been started already
+ public void testWithLocatedMBeanServer() throws Exception {
+ MBeanExporter adaptor = new MBeanExporter();
+ adaptor.setBeans(getBeanMap());
+ adaptor.afterPropertiesSet();
+ assertIsRegistered("The bean was not registered with the MBeanServer", ObjectNameManager.getInstance(OBJECT_NAME));
+ server.unregisterMBean(new ObjectName(OBJECT_NAME));
+ }
+ */
+
+ public void testUserCreatedMBeanRegWithDynamicMBean() throws Exception {
+ Map map = new HashMap();
+ map.put("spring:name=dynBean", new TestDynamicMBean());
+
+ InvokeDetectAssembler asm = new InvokeDetectAssembler();
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(server);
+ exporter.setBeans(map);
+ exporter.setAssembler(asm);
+ exporter.afterPropertiesSet();
+
+ Object name = server.getAttribute(ObjectNameManager.getInstance("spring:name=dynBean"), "Name");
+ assertEquals("The name attribute is incorrect", "Rob Harrop", name);
+ assertFalse("Assembler should not have been invoked", asm.invoked);
+ }
+
+ public void testAutodetectMBeans() throws Exception {
+ XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("autodetectMBeans.xml", getClass()));
+ try {
+ bf.getBean("exporter");
+ MBeanServer server = (MBeanServer) bf.getBean("server");
+ ObjectInstance instance = server.getObjectInstance(ObjectNameManager.getInstance("spring:mbean=true"));
+ assertNotNull(instance);
+ instance = server.getObjectInstance(ObjectNameManager.getInstance("spring:mbean2=true"));
+ assertNotNull(instance);
+ instance = server.getObjectInstance(ObjectNameManager.getInstance("spring:mbean3=true"));
+ assertNotNull(instance);
+ }
+ finally {
+ bf.destroySingletons();
+ }
+ }
+
+ public void testAutodetectWithExclude() throws Exception {
+ XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("autodetectMBeans.xml", getClass()));
+ try {
+ bf.getBean("exporter");
+ MBeanServer server = (MBeanServer) bf.getBean("server");
+ ObjectInstance instance = server.getObjectInstance(ObjectNameManager.getInstance("spring:mbean=true"));
+ assertNotNull(instance);
+
+ try {
+ server.getObjectInstance(ObjectNameManager.getInstance("spring:mbean=false"));
+ fail("MBean with name spring:mbean=false should have been excluded");
+ }
+ catch (InstanceNotFoundException expected) {
+ }
+ }
+ finally {
+ bf.destroySingletons();
+ }
+ }
+
+ public void testAutodetectLazyMBeans() throws Exception {
+ XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("autodetectLazyMBeans.xml", getClass()));
+ try {
+ bf.getBean("exporter");
+ MBeanServer server = (MBeanServer) bf.getBean("server");
+
+ ObjectName oname = ObjectNameManager.getInstance("spring:mbean=true");
+ assertNotNull(server.getObjectInstance(oname));
+ String name = (String) server.getAttribute(oname, "Name");
+ assertEquals("Invalid name returned", "Rob Harrop", name);
+
+ oname = ObjectNameManager.getInstance("spring:mbean=another");
+ assertNotNull(server.getObjectInstance(oname));
+ name = (String) server.getAttribute(oname, "Name");
+ assertEquals("Invalid name returned", "Juergen Hoeller", name);
+ }
+ finally {
+ bf.destroySingletons();
+ }
+ }
+
+ public void testAutodetectNoMBeans() throws Exception {
+ XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("autodetectNoMBeans.xml", getClass()));
+ try {
+ bf.getBean("exporter");
+ }
+ finally {
+ bf.destroySingletons();
+ }
+ }
+
+ public void testWithMBeanExporterListeners() throws Exception {
+ MockMBeanExporterListener listener1 = new MockMBeanExporterListener();
+ MockMBeanExporterListener listener2 = new MockMBeanExporterListener();
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setBeans(getBeanMap());
+ exporter.setServer(server);
+ exporter.setListeners(new MBeanExporterListener[] {listener1, listener2});
+ exporter.afterPropertiesSet();
+ exporter.destroy();
+
+ assertListener(listener1);
+ assertListener(listener2);
+ }
+
+ public void testExportJdkProxy() throws Exception {
+ JmxTestBean bean = new JmxTestBean();
+ bean.setName("Rob Harrop");
+
+ ProxyFactory factory = new ProxyFactory();
+ factory.setTarget(bean);
+ factory.addAdvice(new NopInterceptor());
+ factory.setInterfaces(new Class[]{IJmxTestBean.class});
+
+ IJmxTestBean proxy = (IJmxTestBean) factory.getProxy();
+ String name = "bean:mmm=whatever";
+
+ Map beans = new HashMap();
+ beans.put(name, proxy);
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(server);
+ exporter.setBeans(beans);
+ exporter.registerBeans();
+
+ ObjectName oname = ObjectName.getInstance(name);
+ Object nameValue = server.getAttribute(oname, "Name");
+ assertEquals("Rob Harrop", nameValue);
+ }
+
+ public void testSelfNaming() throws Exception {
+ ObjectName objectName = ObjectNameManager.getInstance(OBJECT_NAME);
+ SelfNamingTestBean testBean = new SelfNamingTestBean();
+ testBean.setObjectName(objectName);
+
+ Map beans = new HashMap();
+ beans.put("foo", testBean);
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(server);
+ exporter.setBeans(beans);
+
+ exporter.afterPropertiesSet();
+
+ ObjectInstance instance = server.getObjectInstance(objectName);
+ assertNotNull(instance);
+ }
+
+ public void testRegisterIgnoreExisting() throws Exception {
+ ObjectName objectName = ObjectNameManager.getInstance(OBJECT_NAME);
+
+ Person preRegistered = new Person();
+ preRegistered.setName("Rob Harrop");
+
+ server.registerMBean(preRegistered, objectName);
+
+ Person springRegistered = new Person();
+ springRegistered.setName("Sally Greenwood");
+
+ String objectName2 = "spring:test=equalBean";
+
+ Map beans = new HashMap();
+ beans.put(objectName.toString(), springRegistered);
+ beans.put(objectName2, springRegistered);
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(server);
+ exporter.setBeans(beans);
+ exporter.setRegistrationBehavior(MBeanExporter.REGISTRATION_IGNORE_EXISTING);
+
+ exporter.afterPropertiesSet();
+
+ ObjectInstance instance = server.getObjectInstance(objectName);
+ assertNotNull(instance);
+ ObjectInstance instance2 = server.getObjectInstance(new ObjectName(objectName2));
+ assertNotNull(instance2);
+
+ // should still be the first bean with name Rob Harrop
+ assertEquals("Rob Harrop", server.getAttribute(objectName, "Name"));
+ }
+
+ public void testRegisterReplaceExisting() throws Exception {
+ ObjectName objectName = ObjectNameManager.getInstance(OBJECT_NAME);
+
+ Person preRegistered = new Person();
+ preRegistered.setName("Rob Harrop");
+
+ server.registerMBean(preRegistered, objectName);
+
+ Person springRegistered = new Person();
+ springRegistered.setName("Sally Greenwood");
+
+ Map beans = new HashMap();
+ beans.put(objectName.toString(), springRegistered);
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(server);
+ exporter.setBeans(beans);
+ exporter.setRegistrationBehavior(MBeanExporter.REGISTRATION_REPLACE_EXISTING);
+
+ exporter.afterPropertiesSet();
+
+ ObjectInstance instance = server.getObjectInstance(objectName);
+ assertNotNull(instance);
+
+ // should still be the new bean with name Sally Greenwood
+ assertEquals("Sally Greenwood", server.getAttribute(objectName, "Name"));
+ }
+
+ public void testWithExposeClassLoader() throws Exception {
+ String name = "Rob Harrop";
+ String otherName = "Juergen Hoeller";
+
+ JmxTestBean bean = new JmxTestBean();
+ bean.setName(name);
+ ObjectName objectName = ObjectNameManager.getInstance("spring:type=Test");
+
+ Map beans = new HashMap();
+ beans.put(objectName.toString(), bean);
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(getServer());
+ exporter.setBeans(beans);
+ exporter.setExposeManagedResourceClassLoader(true);
+ exporter.afterPropertiesSet();
+
+ assertIsRegistered("Bean instance not registered", objectName);
+
+ Object result = server.invoke(objectName, "add",
+ new Object[]{new Integer(2), new Integer(3)},
+ new String[]{int.class.getName(), int.class.getName()});
+
+ assertEquals("Incorrect result return from add", result, new Integer(5));
+ assertEquals("Incorrect attribute value", name, server.getAttribute(objectName, "Name"));
+
+ server.setAttribute(objectName, new Attribute("Name", otherName));
+ assertEquals("Incorrect updated name.", otherName, bean.getName());
+ }
+
+ public void testBonaFideMBeanIsNotExportedWhenAutodetectIsTotallyTurnedOff() throws Exception {
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(Person.class);
+ DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
+ factory.registerBeanDefinition("^&_invalidObjectName_(*", builder.getBeanDefinition());
+ String exportedBeanName = "export.me.please";
+ factory.registerSingleton(exportedBeanName, new TestBean());
+
+ MBeanExporter exporter = new MBeanExporter();
+ Map beansToExport = new HashMap();
+ beansToExport.put(OBJECT_NAME, exportedBeanName);
+ exporter.setBeans(beansToExport);
+ exporter.setServer(getServer());
+ exporter.setBeanFactory(factory);
+ exporter.setAutodetectMode(MBeanExporter.AUTODETECT_NONE);
+ // MBean has a bad ObjectName, so if said MBean is autodetected, an exception will be thrown...
+ exporter.afterPropertiesSet();
+ }
+
+ public void testOnlyBonaFideMBeanIsExportedWhenAutodetectIsMBeanOnly() throws Exception {
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(Person.class);
+ DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
+ factory.registerBeanDefinition(OBJECT_NAME, builder.getBeanDefinition());
+ String exportedBeanName = "spring:type=TestBean";
+ factory.registerSingleton(exportedBeanName, new TestBean());
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(getServer());
+ exporter.setAssembler(new NamedBeanAutodetectCapableMBeanInfoAssemblerStub(exportedBeanName));
+ exporter.setBeanFactory(factory);
+ exporter.setAutodetectMode(MBeanExporter.AUTODETECT_MBEAN);
+ exporter.afterPropertiesSet();
+ assertIsRegistered("Bona fide MBean not autodetected in AUTODETECT_MBEAN mode",
+ ObjectNameManager.getInstance(OBJECT_NAME));
+ assertIsNotRegistered("Bean autodetected and (only) AUTODETECT_MBEAN mode is on",
+ ObjectNameManager.getInstance(exportedBeanName));
+ }
+
+ public void testBonaFideMBeanAndRegularBeanExporterWithAutodetectAll() throws Exception {
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(Person.class);
+ DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
+ factory.registerBeanDefinition(OBJECT_NAME, builder.getBeanDefinition());
+ String exportedBeanName = "spring:type=TestBean";
+ factory.registerSingleton(exportedBeanName, new TestBean());
+ String notToBeExportedBeanName = "spring:type=NotToBeExported";
+ factory.registerSingleton(notToBeExportedBeanName, new TestBean());
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(getServer());
+ exporter.setAssembler(new NamedBeanAutodetectCapableMBeanInfoAssemblerStub(exportedBeanName));
+ exporter.setBeanFactory(factory);
+ exporter.setAutodetectMode(MBeanExporter.AUTODETECT_ALL);
+ exporter.afterPropertiesSet();
+ assertIsRegistered("Bona fide MBean not autodetected in (AUTODETECT_ALL) mode",
+ ObjectNameManager.getInstance(OBJECT_NAME));
+ assertIsRegistered("Bean not autodetected in (AUTODETECT_ALL) mode",
+ ObjectNameManager.getInstance(exportedBeanName));
+ assertIsNotRegistered("Bean autodetected and did not satisfy the autodetect info assembler",
+ ObjectNameManager.getInstance(notToBeExportedBeanName));
+ }
+
+ public void testBonaFideMBeanIsNotExportedWithAutodetectAssembler() throws Exception {
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(Person.class);
+ DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
+ factory.registerBeanDefinition(OBJECT_NAME, builder.getBeanDefinition());
+ String exportedBeanName = "spring:type=TestBean";
+ factory.registerSingleton(exportedBeanName, new TestBean());
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(getServer());
+ exporter.setAssembler(new NamedBeanAutodetectCapableMBeanInfoAssemblerStub(exportedBeanName));
+ exporter.setBeanFactory(factory);
+ exporter.setAutodetectMode(MBeanExporter.AUTODETECT_ASSEMBLER);
+ exporter.afterPropertiesSet();
+ assertIsNotRegistered("Bona fide MBean was autodetected in AUTODETECT_ASSEMBLER mode - must not have been",
+ ObjectNameManager.getInstance(OBJECT_NAME));
+ assertIsRegistered("Bean not autodetected in AUTODETECT_ASSEMBLER mode",
+ ObjectNameManager.getInstance(exportedBeanName));
+ }
+
+ /**
+ * Want to ensure that said MBean is not exported twice.
+ */
+ public void testBonaFideMBeanExplicitlyExportedAndAutodetectionIsOn() throws Exception {
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(Person.class);
+ DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
+ factory.registerBeanDefinition(OBJECT_NAME, builder.getBeanDefinition());
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(getServer());
+ Map beansToExport = new HashMap();
+ beansToExport.put(OBJECT_NAME, OBJECT_NAME);
+ exporter.setBeans(beansToExport);
+ exporter.setAssembler(new NamedBeanAutodetectCapableMBeanInfoAssemblerStub(OBJECT_NAME));
+ exporter.setBeanFactory(factory);
+ exporter.setAutodetectMode(MBeanExporter.AUTODETECT_ASSEMBLER);
+ exporter.afterPropertiesSet();
+ assertIsRegistered("Explicitly exported bona fide MBean obviously not exported.",
+ ObjectNameManager.getInstance(OBJECT_NAME));
+ }
+
+ public void testSetAutodetectModeToOutOfRangeNegativeValue() throws Exception {
+ try {
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setAutodetectMode(-1);
+ fail("Must have failed when supplying an invalid negative out-of-range autodetect mode");
+ }
+ catch (IllegalArgumentException expected) {}
+ }
+
+ public void testSetAutodetectModeToOutOfRangePositiveValue() throws Exception {
+ try {
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setAutodetectMode(5);
+ fail("Must have failed when supplying an invalid positive out-of-range autodetect mode");
+ }
+ catch (IllegalArgumentException expected) {}
+ }
+
+ public void testSetAutodetectModeNameToNull() throws Exception {
+ try {
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setAutodetectModeName(null);
+ fail("Must have failed when supplying a null autodetect mode name");
+ }
+ catch (IllegalArgumentException expected) {}
+ }
+
+ public void testSetAutodetectModeNameToAnEmptyString() throws Exception {
+ try {
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setAutodetectModeName("");
+ fail("Must have failed when supplying an empty autodetect mode name");
+ }
+ catch (IllegalArgumentException expected) {}
+ }
+
+ public void testSetAutodetectModeNameToAWhitespacedString() throws Exception {
+ try {
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setAutodetectModeName(" \t");
+ fail("Must have failed when supplying a whitespace-only autodetect mode name");
+ }
+ catch (IllegalArgumentException expected) {}
+ }
+
+ public void testSetAutodetectModeNameToARubbishValue() throws Exception {
+ try {
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setAutodetectModeName("That Hansel is... *sssooo* hot right now!");
+ fail("Must have failed when supplying a whitespace-only autodetect mode name");
+ }
+ catch (IllegalArgumentException expected) {}
+ }
+
+ public void testNotRunningInBeanFactoryAndPassedBeanNameToExport() throws Exception {
+ try {
+ MBeanExporter exporter = new MBeanExporter();
+ Map beans = new HashMap();
+ beans.put(OBJECT_NAME, "beanName");
+ exporter.setBeans(beans);
+ exporter.afterPropertiesSet();
+ fail("Expecting exception because MBeanExporter is not running in a BeanFactory and was passed bean name to (lookup and then) export");
+ }
+ catch (MBeanExportException expected) {}
+ }
+
+ public void testNotRunningInBeanFactoryAndAutodetectionIsOn() throws Exception {
+ try {
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setAutodetectMode(MBeanExporter.AUTODETECT_ALL);
+ exporter.afterPropertiesSet();
+ fail("Expecting exception because MBeanExporter is not running in a BeanFactory and was configured to autodetect beans");
+ }
+ catch (MBeanExportException expected) {}
+ }
+
+ /**
+ * SPR-2158
+ */
+ public void testMBeanIsNotUnregisteredSpuriouslyIfSomeExternalProcessHasUnregisteredMBean() throws Exception {
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setBeans(getBeanMap());
+ exporter.setServer(this.server);
+ MockMBeanExporterListener listener = new MockMBeanExporterListener();
+ exporter.setListeners(new MBeanExporterListener[]{listener});
+ exporter.afterPropertiesSet();
+ assertIsRegistered("The bean was not registered with the MBeanServer", ObjectNameManager.getInstance(OBJECT_NAME));
+
+ this.server.unregisterMBean(new ObjectName(OBJECT_NAME));
+ exporter.destroy();
+ assertEquals("Listener should not have been invoked (MBean previously unregistered by external agent)", 0, listener.getUnregistered().size());
+ }
+
+ /**
+ * SPR-3302
+ */
+ public void testBeanNameCanBeUsedInNotificationListenersMap() throws Exception {
+ String beanName = "charlesDexterWard";
+ BeanDefinitionBuilder testBean = BeanDefinitionBuilder.rootBeanDefinition(JmxTestBean.class);
+
+ DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
+ factory.registerBeanDefinition(beanName, testBean.getBeanDefinition());
+ factory.preInstantiateSingletons();
+ Object testBeanInstance = factory.getBean(beanName);
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(getServer());
+ Map beansToExport = new HashMap();
+ beansToExport.put("test:what=ever", testBeanInstance);
+ exporter.setBeans(beansToExport);
+ exporter.setBeanFactory(factory);
+ StubNotificationListener listener = new StubNotificationListener();
+ exporter.setNotificationListenerMappings(Collections.singletonMap(beanName, listener));
+
+ exporter.afterPropertiesSet();
+ }
+
+ public void testWildcardCanBeUsedInNotificationListenersMap() throws Exception {
+ String beanName = "charlesDexterWard";
+ BeanDefinitionBuilder testBean = BeanDefinitionBuilder.rootBeanDefinition(JmxTestBean.class);
+
+ DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
+ factory.registerBeanDefinition(beanName, testBean.getBeanDefinition());
+ factory.preInstantiateSingletons();
+ Object testBeanInstance = factory.getBean(beanName);
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(getServer());
+ Map beansToExport = new HashMap();
+ beansToExport.put("test:what=ever", testBeanInstance);
+ exporter.setBeans(beansToExport);
+ exporter.setBeanFactory(factory);
+ StubNotificationListener listener = new StubNotificationListener();
+ exporter.setNotificationListenerMappings(Collections.singletonMap("*", listener));
+
+ exporter.afterPropertiesSet();
+ }
+
+ /*
+ * SPR-3625
+ */
+ public void testMBeanIsUnregisteredForRuntimeExceptionDuringInitialization() throws Exception {
+ BeanDefinitionBuilder builder1 = BeanDefinitionBuilder.rootBeanDefinition(Person.class);
+ BeanDefinitionBuilder builder2 = BeanDefinitionBuilder.rootBeanDefinition(RuntimeExceptionThrowingConstructorBean.class);
+
+ String objectName1 = "spring:test=bean1";
+ String objectName2 = "spring:test=bean2";
+
+ DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
+ factory.registerBeanDefinition(objectName1, builder1.getBeanDefinition());
+ factory.registerBeanDefinition(objectName2, builder2.getBeanDefinition());
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(getServer());
+ Map beansToExport = new HashMap();
+ beansToExport.put(objectName1, objectName1);
+ beansToExport.put(objectName2, objectName2);
+ exporter.setBeans(beansToExport);
+ exporter.setBeanFactory(factory);
+
+ try {
+ exporter.afterPropertiesSet();
+ fail("Must have failed during creation of RuntimeExceptionThrowingConstructorBean");
+ }
+ catch (RuntimeException expected) {
+ }
+
+ assertIsNotRegistered("Must have unregistered all previously registered MBeans due to RuntimeException",
+ ObjectNameManager.getInstance(objectName1));
+ assertIsNotRegistered("Must have never registered this MBean due to RuntimeException",
+ ObjectNameManager.getInstance(objectName2));
+ }
+
+
+ private Map getBeanMap() {
+ Map map = new HashMap();
+ map.put(OBJECT_NAME, new JmxTestBean());
+ return map;
+ }
+
+ private void assertListener(MockMBeanExporterListener listener) throws MalformedObjectNameException {
+ ObjectName desired = ObjectNameManager.getInstance(OBJECT_NAME);
+ assertEquals("Incorrect number of registrations", 1, listener.getRegistered().size());
+ assertEquals("Incorrect number of unregistrations", 1, listener.getUnregistered().size());
+ assertEquals("Incorrect ObjectName in register", desired, listener.getRegistered().get(0));
+ assertEquals("Incorrect ObjectName in unregister", desired, listener.getUnregistered().get(0));
+ }
+
+
+ private static class InvokeDetectAssembler implements MBeanInfoAssembler {
+
+ private boolean invoked = false;
+
+ public ModelMBeanInfo getMBeanInfo(Object managedResource, String beanKey) throws JMException {
+ invoked = true;
+ return null;
+ }
+ }
+
+
+ private static class MockMBeanExporterListener implements MBeanExporterListener {
+
+ private List registered = new ArrayList();
+
+ private List unregistered = new ArrayList();
+
+ public void mbeanRegistered(ObjectName objectName) {
+ registered.add(objectName);
+ }
+
+ public void mbeanUnregistered(ObjectName objectName) {
+ unregistered.add(objectName);
+ }
+
+ public List getRegistered() {
+ return registered;
+ }
+
+ public List getUnregistered() {
+ return unregistered;
+ }
+ }
+
+
+ private static class SelfNamingTestBean implements SelfNaming {
+
+ private ObjectName objectName;
+
+ public void setObjectName(ObjectName objectName) {
+ this.objectName = objectName;
+ }
+
+ public ObjectName getObjectName() throws MalformedObjectNameException {
+ return this.objectName;
+ }
+ }
+
+
+ public static interface PersonMBean {
+
+ String getName();
+ }
+
+
+ public static class Person implements PersonMBean {
+
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+ }
+
+
+ public static final class StubNotificationListener implements NotificationListener {
+
+ private List notifications = new ArrayList();
+
+ public void handleNotification(Notification notification, Object handback) {
+ this.notifications.add(notification);
+ }
+
+ public List getNotifications() {
+ return this.notifications;
+ }
+ }
+
+
+ private static class RuntimeExceptionThrowingConstructorBean {
+
+ public RuntimeExceptionThrowingConstructorBean() {
+ throw new RuntimeException();
+ }
+ }
+
+
+ private static final class NamedBeanAutodetectCapableMBeanInfoAssemblerStub
+ extends SimpleReflectiveMBeanInfoAssembler
+ implements AutodetectCapableMBeanInfoAssembler {
+
+ private String namedBean;
+
+ public NamedBeanAutodetectCapableMBeanInfoAssemblerStub(String namedBean) {
+ this.namedBean = namedBean;
+ }
+
+ public boolean includeBean(Class beanClass, String beanName) {
+ return this.namedBean.equals(beanName);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/NotificationListenerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/NotificationListenerTests.java
new file mode 100644
index 00000000000..d38ea2ac74b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/NotificationListenerTests.java
@@ -0,0 +1,482 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jmx.export;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.management.Attribute;
+import javax.management.AttributeChangeNotification;
+import javax.management.MalformedObjectNameException;
+import javax.management.Notification;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.jmx.AbstractMBeanServerTests;
+import org.springframework.jmx.JmxTestBean;
+import org.springframework.jmx.access.NotificationListenerRegistrar;
+import org.springframework.jmx.export.naming.SelfNaming;
+import org.springframework.jmx.support.ObjectNameManager;
+
+/**
+ * @author Rob Harrop
+ * @author Mark Fisher
+ */
+public class NotificationListenerTests extends AbstractMBeanServerTests {
+
+ public void testRegisterNotificationListenerForMBean() throws Exception {
+ ObjectName objectName = ObjectName.getInstance("spring:name=Test");
+ JmxTestBean bean = new JmxTestBean();
+
+ Map beans = new HashMap();
+ beans.put(objectName, bean);
+
+ CountingAttributeChangeNotificationListener listener = new CountingAttributeChangeNotificationListener();
+
+ Map notificationListeners = new HashMap();
+ notificationListeners.put(objectName, listener);
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(server);
+ exporter.setBeans(beans);
+ exporter.setNotificationListenerMappings(notificationListeners);
+ exporter.afterPropertiesSet();
+
+ // update the attribute
+ String attributeName = "Name";
+ server.setAttribute(objectName, new Attribute(attributeName, "Rob Harrop"));
+ assertEquals("Listener not notified", 1, listener.getCount(attributeName));
+ }
+
+ public void testRegisterNotificationListenerWithWildcard() throws Exception {
+ ObjectName objectName = ObjectName.getInstance("spring:name=Test");
+ JmxTestBean bean = new JmxTestBean();
+
+ Map beans = new HashMap();
+ beans.put(objectName, bean);
+
+ CountingAttributeChangeNotificationListener listener = new CountingAttributeChangeNotificationListener();
+
+ Map notificationListeners = new HashMap();
+ notificationListeners.put("*", listener);
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(server);
+ exporter.setBeans(beans);
+ exporter.setNotificationListenerMappings(notificationListeners);
+ exporter.afterPropertiesSet();
+
+ // update the attribute
+ String attributeName = "Name";
+ server.setAttribute(objectName, new Attribute(attributeName, "Rob Harrop"));
+ assertEquals("Listener not notified", 1, listener.getCount(attributeName));
+ }
+
+ public void testRegisterNotificationListenerWithHandback() throws Exception {
+ String objectName = "spring:name=Test";
+ JmxTestBean bean = new JmxTestBean();
+
+ Map beans = new HashMap();
+ beans.put(objectName, bean);
+
+ CountingAttributeChangeNotificationListener listener = new CountingAttributeChangeNotificationListener();
+ Object handback = new Object();
+
+ NotificationListenerBean listenerBean = new NotificationListenerBean();
+ listenerBean.setNotificationListener(listener);
+ listenerBean.setMappedObjectName("spring:name=Test");
+ listenerBean.setHandback(handback);
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(server);
+ exporter.setBeans(beans);
+ exporter.setNotificationListeners(new NotificationListenerBean[]{listenerBean});
+ exporter.afterPropertiesSet();
+
+ // update the attribute
+ String attributeName = "Name";
+ server.setAttribute(ObjectNameManager.getInstance("spring:name=Test"), new Attribute(attributeName, "Rob Harrop"));
+
+ assertEquals("Listener not notified", 1, listener.getCount(attributeName));
+ assertEquals("Handback object not transmitted correctly", handback, listener.getLastHandback(attributeName));
+ }
+
+ public void testRegisterNotificationListenerForAllMBeans() throws Exception {
+ ObjectName objectName = ObjectName.getInstance("spring:name=Test");
+ JmxTestBean bean = new JmxTestBean();
+
+ Map beans = new HashMap();
+ beans.put(objectName, bean);
+
+ CountingAttributeChangeNotificationListener listener = new CountingAttributeChangeNotificationListener();
+
+ NotificationListenerBean listenerBean = new NotificationListenerBean();
+ listenerBean.setNotificationListener(listener);
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(server);
+ exporter.setBeans(beans);
+ exporter.setNotificationListeners(new NotificationListenerBean[]{listenerBean});
+ exporter.afterPropertiesSet();
+
+ // update the attribute
+ String attributeName = "Name";
+ server.setAttribute(objectName, new Attribute(attributeName, "Rob Harrop"));
+
+ assertEquals("Listener not notified", 1, listener.getCount(attributeName));
+ }
+
+ public void testRegisterNotificationListenerWithFilter() throws Exception {
+ ObjectName objectName = ObjectName.getInstance("spring:name=Test");
+ JmxTestBean bean = new JmxTestBean();
+
+ Map beans = new HashMap();
+ beans.put(objectName, bean);
+
+ CountingAttributeChangeNotificationListener listener = new CountingAttributeChangeNotificationListener();
+
+ NotificationListenerBean listenerBean = new NotificationListenerBean();
+ listenerBean.setNotificationListener(listener);
+ listenerBean.setNotificationFilter(new NotificationFilter() {
+ public boolean isNotificationEnabled(Notification notification) {
+ if (notification instanceof AttributeChangeNotification) {
+ AttributeChangeNotification changeNotification = (AttributeChangeNotification) notification;
+ return "Name".equals(changeNotification.getAttributeName());
+ }
+ else {
+ return false;
+ }
+ }
+ });
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(server);
+ exporter.setBeans(beans);
+ exporter.setNotificationListeners(new NotificationListenerBean[]{listenerBean});
+ exporter.afterPropertiesSet();
+
+ // update the attributes
+ String nameAttribute = "Name";
+ String ageAttribute = "Age";
+
+ server.setAttribute(objectName, new Attribute(nameAttribute, "Rob Harrop"));
+ server.setAttribute(objectName, new Attribute(ageAttribute, new Integer(90)));
+
+ assertEquals("Listener not notified for Name", 1, listener.getCount(nameAttribute));
+ assertEquals("Listener incorrectly notified for Age", 0, listener.getCount(ageAttribute));
+ }
+
+ public void testCreationWithNoNotificationListenerSet() {
+ try {
+ new NotificationListenerBean().afterPropertiesSet();
+ fail("Must have thrown an IllegalArgumentException (no NotificationListener supplied)");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testRegisterNotificationListenerWithBeanNameAndBeanNameInBeansMap() throws Exception {
+ String beanName = "testBean";
+ ObjectName objectName = ObjectName.getInstance("spring:name=Test");
+
+ SelfNamingTestBean testBean = new SelfNamingTestBean();
+ testBean.setObjectName(objectName);
+
+ DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
+ factory.registerSingleton(beanName, testBean);
+
+ Map beans = new HashMap();
+ beans.put(beanName, beanName);
+
+ Map listenerMappings = new HashMap();
+ CountingAttributeChangeNotificationListener listener = new CountingAttributeChangeNotificationListener();
+ listenerMappings.put(beanName, listener);
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(server);
+ exporter.setBeans(beans);
+ exporter.setNotificationListenerMappings(listenerMappings);
+ exporter.setBeanFactory(factory);
+ exporter.afterPropertiesSet();
+ assertIsRegistered("Should have registered MBean", objectName);
+
+ server.setAttribute(objectName, new Attribute("Age", new Integer(77)));
+ assertEquals("Listener not notified", 1, listener.getCount("Age"));
+ }
+
+ public void testRegisterNotificationListenerWithBeanNameAndBeanInstanceInBeansMap() throws Exception {
+ String beanName = "testBean";
+ ObjectName objectName = ObjectName.getInstance("spring:name=Test");
+
+ SelfNamingTestBean testBean = new SelfNamingTestBean();
+ testBean.setObjectName(objectName);
+
+ DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
+ factory.registerSingleton(beanName, testBean);
+
+ Map beans = new HashMap();
+ beans.put(beanName, testBean);
+
+ Map listenerMappings = new HashMap();
+ CountingAttributeChangeNotificationListener listener = new CountingAttributeChangeNotificationListener();
+ listenerMappings.put(beanName, listener);
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(server);
+ exporter.setBeans(beans);
+ exporter.setNotificationListenerMappings(listenerMappings);
+ exporter.setBeanFactory(factory);
+ exporter.afterPropertiesSet();
+ assertIsRegistered("Should have registered MBean", objectName);
+
+ server.setAttribute(objectName, new Attribute("Age", new Integer(77)));
+ assertEquals("Listener not notified", 1, listener.getCount("Age"));
+ }
+
+ public void testRegisterNotificationListenerWithBeanNameBeforeObjectNameMappedToSameBeanInstance() throws Exception {
+ String beanName = "testBean";
+ ObjectName objectName = ObjectName.getInstance("spring:name=Test");
+
+ SelfNamingTestBean testBean = new SelfNamingTestBean();
+ testBean.setObjectName(objectName);
+
+ DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
+ factory.registerSingleton(beanName, testBean);
+
+ Map beans = new HashMap();
+ beans.put(beanName, testBean);
+
+ Map listenerMappings = new HashMap();
+ CountingAttributeChangeNotificationListener listener = new CountingAttributeChangeNotificationListener();
+ listenerMappings.put(beanName, listener);
+ listenerMappings.put(objectName, listener);
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(server);
+ exporter.setBeans(beans);
+ exporter.setNotificationListenerMappings(listenerMappings);
+ exporter.setBeanFactory(factory);
+ exporter.afterPropertiesSet();
+ assertIsRegistered("Should have registered MBean", objectName);
+
+ server.setAttribute(objectName, new Attribute("Age", new Integer(77)));
+ assertEquals("Listener should have been notified exactly once", 1, listener.getCount("Age"));
+ }
+
+ public void testRegisterNotificationListenerWithObjectNameBeforeBeanNameMappedToSameBeanInstance() throws Exception {
+ String beanName = "testBean";
+ ObjectName objectName = ObjectName.getInstance("spring:name=Test");
+
+ SelfNamingTestBean testBean = new SelfNamingTestBean();
+ testBean.setObjectName(objectName);
+
+ DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
+ factory.registerSingleton(beanName, testBean);
+
+ Map beans = new HashMap();
+ beans.put(beanName, testBean);
+
+ Map listenerMappings = new HashMap();
+ CountingAttributeChangeNotificationListener listener = new CountingAttributeChangeNotificationListener();
+ listenerMappings.put(objectName, listener);
+ listenerMappings.put(beanName, listener);
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(server);
+ exporter.setBeans(beans);
+ exporter.setNotificationListenerMappings(listenerMappings);
+ exporter.setBeanFactory(factory);
+ exporter.afterPropertiesSet();
+ assertIsRegistered("Should have registered MBean", objectName);
+
+ server.setAttribute(objectName, new Attribute("Age", new Integer(77)));
+ assertEquals("Listener should have been notified exactly once", 1, listener.getCount("Age"));
+ }
+
+ public void testRegisterNotificationListenerWithTwoBeanNamesMappedToDifferentBeanInstances() throws Exception {
+ String beanName1 = "testBean1";
+ String beanName2 = "testBean2";
+
+ ObjectName objectName1 = ObjectName.getInstance("spring:name=Test1");
+ ObjectName objectName2 = ObjectName.getInstance("spring:name=Test2");
+
+ SelfNamingTestBean testBean1 = new SelfNamingTestBean();
+ testBean1.setObjectName(objectName1);
+
+ SelfNamingTestBean testBean2 = new SelfNamingTestBean();
+ testBean2.setObjectName(objectName2);
+
+ DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
+ factory.registerSingleton(beanName1, testBean1);
+ factory.registerSingleton(beanName2, testBean2);
+
+ Map beans = new HashMap();
+ beans.put(beanName1, testBean1);
+ beans.put(beanName2, testBean2);
+
+ Map listenerMappings = new HashMap();
+ CountingAttributeChangeNotificationListener listener = new CountingAttributeChangeNotificationListener();
+ listenerMappings.put(beanName1, listener);
+ listenerMappings.put(beanName2, listener);
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(server);
+ exporter.setBeans(beans);
+ exporter.setNotificationListenerMappings(listenerMappings);
+ exporter.setBeanFactory(factory);
+ exporter.afterPropertiesSet();
+ assertIsRegistered("Should have registered MBean", objectName1);
+ assertIsRegistered("Should have registered MBean", objectName2);
+
+ server.setAttribute(ObjectNameManager.getInstance(objectName1), new Attribute("Age", new Integer(77)));
+ assertEquals("Listener not notified for testBean1", 1, listener.getCount("Age"));
+
+ server.setAttribute(ObjectNameManager.getInstance(objectName2), new Attribute("Age", new Integer(33)));
+ assertEquals("Listener not notified for testBean2", 2, listener.getCount("Age"));
+ }
+
+ public void testNotificationListenerRegistrar() throws Exception {
+ ObjectName objectName = ObjectName.getInstance("spring:name=Test");
+ JmxTestBean bean = new JmxTestBean();
+
+ Map beans = new HashMap();
+ beans.put(objectName, bean);
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(server);
+ exporter.setBeans(beans);
+ exporter.afterPropertiesSet();
+
+ CountingAttributeChangeNotificationListener listener = new CountingAttributeChangeNotificationListener();
+
+ NotificationListenerRegistrar registrar = new NotificationListenerRegistrar();
+ registrar.setServer(server);
+ registrar.setNotificationListener(listener);
+ registrar.setMappedObjectName(objectName);
+ registrar.afterPropertiesSet();
+
+ // update the attribute
+ String attributeName = "Name";
+ server.setAttribute(objectName, new Attribute(attributeName, "Rob Harrop"));
+ assertEquals("Listener not notified", 1, listener.getCount(attributeName));
+
+ registrar.destroy();
+
+ // try to update the attribute again
+ server.setAttribute(objectName, new Attribute(attributeName, "Rob Harrop"));
+ assertEquals("Listener notified after destruction", 1, listener.getCount(attributeName));
+ }
+
+ public void testNotificationListenerRegistrarWithMultipleNames() throws Exception {
+ ObjectName objectName = ObjectName.getInstance("spring:name=Test");
+ ObjectName objectName2 = ObjectName.getInstance("spring:name=Test2");
+ JmxTestBean bean = new JmxTestBean();
+ JmxTestBean bean2 = new JmxTestBean();
+
+ Map beans = new HashMap();
+ beans.put(objectName, bean);
+ beans.put(objectName2, bean2);
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setServer(server);
+ exporter.setBeans(beans);
+ exporter.afterPropertiesSet();
+
+ CountingAttributeChangeNotificationListener listener = new CountingAttributeChangeNotificationListener();
+
+ NotificationListenerRegistrar registrar = new NotificationListenerRegistrar();
+ registrar.setServer(server);
+ registrar.setNotificationListener(listener);
+ //registrar.setMappedObjectNames(new Object[] {objectName, objectName2});
+ registrar.setMappedObjectNames(new String[] {"spring:name=Test", "spring:name=Test2"});
+ registrar.afterPropertiesSet();
+
+ // update the attribute
+ String attributeName = "Name";
+ server.setAttribute(objectName, new Attribute(attributeName, "Rob Harrop"));
+ assertEquals("Listener not notified", 1, listener.getCount(attributeName));
+
+ registrar.destroy();
+
+ // try to update the attribute again
+ server.setAttribute(objectName, new Attribute(attributeName, "Rob Harrop"));
+ assertEquals("Listener notified after destruction", 1, listener.getCount(attributeName));
+ }
+
+
+ private static class CountingAttributeChangeNotificationListener implements NotificationListener {
+
+ private Map attributeCounts = new HashMap();
+
+ private Map attributeHandbacks = new HashMap();
+
+ public void handleNotification(Notification notification, Object handback) {
+ if (notification instanceof AttributeChangeNotification) {
+ AttributeChangeNotification attNotification = (AttributeChangeNotification) notification;
+ String attributeName = attNotification.getAttributeName();
+
+ Integer currentCount = (Integer) this.attributeCounts.get(attributeName);
+
+ if (currentCount != null) {
+ int count = currentCount.intValue() + 1;
+ this.attributeCounts.put(attributeName, new Integer(count));
+ }
+ else {
+ this.attributeCounts.put(attributeName, new Integer(1));
+ }
+
+ this.attributeHandbacks.put(attributeName, handback);
+ }
+ }
+
+ public int getCount(String attribute) {
+ Integer count = (Integer) this.attributeCounts.get(attribute);
+ return (count == null) ? 0 : count.intValue();
+ }
+
+ public Object getLastHandback(String attributeName) {
+ return this.attributeHandbacks.get(attributeName);
+ }
+ }
+
+
+ public static class SelfNamingTestBean implements SelfNaming {
+
+ private ObjectName objectName;
+
+ private int age;
+
+ public void setObjectName(ObjectName objectName) {
+ this.objectName = objectName;
+ }
+
+ public ObjectName getObjectName() throws MalformedObjectNameException {
+ return this.objectName;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ public int getAge() {
+ return this.age;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/NotificationPublisherTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/NotificationPublisherTests.java
new file mode 100644
index 00000000000..5df30638c20
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/NotificationPublisherTests.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jmx.export;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.DynamicMBean;
+import javax.management.InvalidAttributeValueException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanConstructorInfo;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.NotificationListener;
+import javax.management.ReflectionException;
+
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.jmx.AbstractMBeanServerTests;
+import org.springframework.jmx.export.notification.NotificationPublisher;
+import org.springframework.jmx.export.notification.NotificationPublisherAware;
+import org.springframework.jmx.support.ObjectNameManager;
+
+/**
+ * Integration tests for the Spring JMX {@link NotificationPublisher} functionality.
+ *
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class NotificationPublisherTests extends AbstractMBeanServerTests {
+
+ private CountingNotificationListener listener = new CountingNotificationListener();
+
+
+ public void testSimpleBean() throws Exception {
+ // start the MBeanExporter
+ ConfigurableApplicationContext ctx = loadContext("org/springframework/jmx/export/notificationPublisherTests.xml");
+ this.server.addNotificationListener(ObjectNameManager.getInstance("spring:type=Publisher"), listener, null, null);
+
+ MyNotificationPublisher publisher = (MyNotificationPublisher) ctx.getBean("publisher");
+ assertNotNull("NotificationPublisher should not be null", publisher.getNotificationPublisher());
+ publisher.sendNotification();
+ assertEquals("Notification not sent", 1, listener.count);
+ }
+
+ public void testSimpleBeanRegisteredManually() throws Exception {
+ // start the MBeanExporter
+ ConfigurableApplicationContext ctx = loadContext("org/springframework/jmx/export/notificationPublisherTests.xml");
+ MBeanExporter exporter = (MBeanExporter) ctx.getBean("exporter");
+ MyNotificationPublisher publisher = new MyNotificationPublisher();
+ exporter.registerManagedResource(publisher, ObjectNameManager.getInstance("spring:type=Publisher2"));
+ this.server.addNotificationListener(ObjectNameManager.getInstance("spring:type=Publisher2"), listener, null, null);
+
+ assertNotNull("NotificationPublisher should not be null", publisher.getNotificationPublisher());
+ publisher.sendNotification();
+ assertEquals("Notification not sent", 1, listener.count);
+ }
+
+ public void testMBean() throws Exception {
+ // start the MBeanExporter
+ ConfigurableApplicationContext ctx = loadContext("org/springframework/jmx/export/notificationPublisherTests.xml");
+ this.server.addNotificationListener(ObjectNameManager.getInstance("spring:type=PublisherMBean"), listener, null, null);
+
+ MyNotificationPublisherMBean publisher = (MyNotificationPublisherMBean) ctx.getBean("publisherMBean");
+ publisher.sendNotification();
+ assertEquals("Notification not sent", 1, listener.count);
+ }
+
+ /*
+ public void testStandardMBean() throws Exception {
+ // start the MBeanExporter
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("org/springframework/jmx/export/notificationPublisherTests.xml");
+ this.server.addNotificationListener(ObjectNameManager.getInstance("spring:type=PublisherStandardMBean"), listener, null, null);
+
+ MyNotificationPublisherStandardMBean publisher = (MyNotificationPublisherStandardMBean) ctx.getBean("publisherStandardMBean");
+ publisher.sendNotification();
+ assertEquals("Notification not sent", 1, listener.count);
+ }
+ */
+
+ public void testLazyInit() throws Exception {
+ // start the MBeanExporter
+ ConfigurableApplicationContext ctx = loadContext("org/springframework/jmx/export/notificationPublisherLazyTests.xml");
+ assertFalse("Should not have instantiated the bean yet", ctx.getBeanFactory().containsSingleton("publisher"));
+
+ // need to touch the MBean proxy
+ server.getAttribute(ObjectNameManager.getInstance("spring:type=Publisher"), "Name");
+ this.server.addNotificationListener(ObjectNameManager.getInstance("spring:type=Publisher"), listener, null, null);
+
+ MyNotificationPublisher publisher = (MyNotificationPublisher) ctx.getBean("publisher");
+ assertNotNull("NotificationPublisher should not be null", publisher.getNotificationPublisher());
+ publisher.sendNotification();
+ assertEquals("Notification not sent", 1, listener.count);
+ }
+
+
+ private static class CountingNotificationListener implements NotificationListener {
+
+ private int count;
+
+ private Notification lastNotification;
+
+ public void handleNotification(Notification notification, Object handback) {
+ this.lastNotification = notification;
+ this.count++;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public Notification getLastNotification() {
+ return lastNotification;
+ }
+ }
+
+
+ public static class MyNotificationPublisher implements NotificationPublisherAware {
+
+ private NotificationPublisher notificationPublisher;
+
+ public void setNotificationPublisher(NotificationPublisher notificationPublisher) {
+ this.notificationPublisher = notificationPublisher;
+ }
+
+ public NotificationPublisher getNotificationPublisher() {
+ return notificationPublisher;
+ }
+
+ public void sendNotification() {
+ this.notificationPublisher.sendNotification(new Notification("test", this, 1));
+ }
+
+ public String getName() {
+ return "Rob Harrop";
+ }
+ }
+
+
+ public static class MyNotificationPublisherMBean extends NotificationBroadcasterSupport implements DynamicMBean {
+
+ public Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException {
+ return null;
+ }
+
+ public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
+ }
+
+ public AttributeList getAttributes(String[] attributes) {
+ return null;
+ }
+
+ public AttributeList setAttributes(AttributeList attributes) {
+ return null;
+ }
+
+ public Object invoke(String actionName, Object params[], String signature[]) throws MBeanException, ReflectionException {
+ return null;
+ }
+
+ public MBeanInfo getMBeanInfo() {
+ return new MBeanInfo(
+ MyNotificationPublisherMBean.class.getName(), "",
+ new MBeanAttributeInfo[0],
+ new MBeanConstructorInfo[0],
+ new MBeanOperationInfo[0],
+ new MBeanNotificationInfo[0]);
+ }
+
+ public void sendNotification() {
+ sendNotification(new Notification("test", this, 1));
+ }
+ }
+
+
+ public static class MyNotificationPublisherStandardMBean extends NotificationBroadcasterSupport implements MyMBean {
+
+ public void sendNotification() {
+ sendNotification(new Notification("test", this, 1));
+ }
+ }
+
+
+ public interface MyMBean {
+
+ void sendNotification();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/PropertyPlaceholderConfigurerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/PropertyPlaceholderConfigurerTests.java
new file mode 100644
index 00000000000..3f5e82ab58e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/PropertyPlaceholderConfigurerTests.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jmx.export;
+
+import javax.management.ObjectName;
+
+import org.springframework.jmx.AbstractJmxTests;
+import org.springframework.jmx.IJmxTestBean;
+
+/**
+ * @author Rob Harrop
+ */
+public class PropertyPlaceholderConfigurerTests extends AbstractJmxTests {
+
+ protected String getApplicationContextPath() {
+ return "org/springframework/jmx/export/propertyPlaceholderConfigurer.xml";
+ }
+
+ public void testPropertiesReplaced() {
+ IJmxTestBean bean = (IJmxTestBean) getContext().getBean("testBean");
+
+ assertEquals("Name is incorrect", "Rob Harrop", bean.getName());
+ assertEquals("Age is incorrect", 100, bean.getAge());
+ }
+
+ public void testPropertiesCorrectInJmx() throws Exception {
+ ObjectName oname = new ObjectName("bean:name=proxyTestBean1");
+ Object name = getServer().getAttribute(oname, "Name");
+ Integer age = (Integer) getServer().getAttribute(oname, "Age");
+
+ assertEquals("Name is incorrect in JMX", "Rob Harrop", name);
+ assertEquals("Age is incorrect in JMX", 100, age.intValue());
+ }
+
+}
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/TestDynamicMBean.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/TestDynamicMBean.java
new file mode 100644
index 00000000000..a52d6a7e78c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/TestDynamicMBean.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jmx.export;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.DynamicMBean;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanConstructorInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanOperationInfo;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class TestDynamicMBean implements DynamicMBean {
+
+ public void setFailOnInit(boolean failOnInit) {
+ if (failOnInit) {
+ throw new IllegalArgumentException("Failing on initialization");
+ }
+ }
+
+ public Object getAttribute(String attribute) {
+ if ("Name".equals(attribute)) {
+ return "Rob Harrop";
+ }
+ return null;
+ }
+
+ public void setAttribute(Attribute attribute) {
+ }
+
+ public AttributeList getAttributes(String[] attributes) {
+ return null;
+ }
+
+ public AttributeList setAttributes(AttributeList attributes) {
+ return null;
+ }
+
+ public Object invoke(String actionName, Object[] params, String[] signature) {
+ return null;
+ }
+
+ public MBeanInfo getMBeanInfo() {
+ MBeanAttributeInfo attr = new MBeanAttributeInfo("name", "java.lang.String", "", true, false, false);
+ return new MBeanInfo(
+ TestDynamicMBean.class.getName(), "",
+ new MBeanAttributeInfo[]{attr},
+ new MBeanConstructorInfo[0],
+ new MBeanOperationInfo[0],
+ new MBeanNotificationInfo[0]);
+ }
+
+ public boolean equals(Object obj) {
+ return (obj instanceof TestDynamicMBean);
+ }
+
+ public int hashCode() {
+ return TestDynamicMBean.class.hashCode();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/AbstractAutodetectTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/AbstractAutodetectTests.java
new file mode 100644
index 00000000000..c2da24872bb
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/AbstractAutodetectTests.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jmx.export.assembler;
+
+import junit.framework.TestCase;
+
+import org.springframework.jmx.JmxTestBean;
+
+/**
+ * @author Rob Harrop
+ */
+public abstract class AbstractAutodetectTests extends TestCase {
+
+ public void testAutodetect() throws Exception {
+ JmxTestBean bean = new JmxTestBean();
+
+ AutodetectCapableMBeanInfoAssembler assembler = getAssembler();
+ assertTrue("The bean should be included", assembler.includeBean(bean.getClass(), "testBean"));
+ }
+
+ protected abstract AutodetectCapableMBeanInfoAssembler getAssembler();
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/AbstractJmxAssemblerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/AbstractJmxAssemblerTests.java
new file mode 100644
index 00000000000..9a3ba369028
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/AbstractJmxAssemblerTests.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jmx.export.assembler;
+
+import javax.management.Attribute;
+import javax.management.Descriptor;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+import javax.management.modelmbean.ModelMBeanAttributeInfo;
+import javax.management.modelmbean.ModelMBeanInfo;
+import javax.management.modelmbean.ModelMBeanOperationInfo;
+
+import org.springframework.jmx.AbstractJmxTests;
+import org.springframework.jmx.IJmxTestBean;
+import org.springframework.jmx.support.ObjectNameManager;
+
+/**
+ * @author Rob Harrop
+ */
+public abstract class AbstractJmxAssemblerTests extends AbstractJmxTests {
+
+ protected static final String AGE_ATTRIBUTE = "Age";
+
+ protected static final String NAME_ATTRIBUTE = "Name";
+
+ protected abstract String getObjectName();
+
+ public void testMBeanRegistration() throws Exception {
+ // beans are registered at this point - just grab them from the server
+ ObjectInstance instance = getObjectInstance();
+ assertNotNull("Bean should not be null", instance);
+ }
+
+ public void testRegisterOperations() throws Exception {
+ IJmxTestBean bean = getBean();
+ MBeanInfo inf = getMBeanInfo();
+ assertEquals("Incorrect number of operations registered",
+ getExpectedOperationCount(), inf.getOperations().length);
+ }
+
+ public void testRegisterAttributes() throws Exception {
+ IJmxTestBean bean = getBean();
+ MBeanInfo inf = getMBeanInfo();
+ assertEquals("Incorrect number of attributes registered",
+ getExpectedAttributeCount(), inf.getAttributes().length);
+ }
+
+ public void testGetMBeanInfo() throws Exception {
+ ModelMBeanInfo info = getMBeanInfoFromAssembler();
+ assertNotNull("MBeanInfo should not be null", info);
+ }
+
+ public void testGetMBeanAttributeInfo() throws Exception {
+ ModelMBeanInfo info = getMBeanInfoFromAssembler();
+ MBeanAttributeInfo[] inf = info.getAttributes();
+ assertEquals("Invalid number of Attributes returned",
+ getExpectedAttributeCount(), inf.length);
+
+ for (int x = 0; x < inf.length; x++) {
+ assertNotNull("MBeanAttributeInfo should not be null", inf[x]);
+ assertNotNull(
+ "Description for MBeanAttributeInfo should not be null",
+ inf[x].getDescription());
+ }
+ }
+
+ public void testGetMBeanOperationInfo() throws Exception {
+ ModelMBeanInfo info = getMBeanInfoFromAssembler();
+ MBeanOperationInfo[] inf = info.getOperations();
+ assertEquals("Invalid number of Operations returned",
+ getExpectedOperationCount(), inf.length);
+
+ for (int x = 0; x < inf.length; x++) {
+ assertNotNull("MBeanOperationInfo should not be null", inf[x]);
+ assertNotNull(
+ "Description for MBeanOperationInfo should not be null",
+ inf[x].getDescription());
+ }
+ }
+
+ public void testDescriptionNotNull() throws Exception {
+ ModelMBeanInfo info = getMBeanInfoFromAssembler();
+
+ assertNotNull("The MBean description should not be null",
+ info.getDescription());
+ }
+
+ public void testSetAttribute() throws Exception {
+ ObjectName objectName = ObjectNameManager.getInstance(getObjectName());
+ getServer().setAttribute(objectName, new Attribute(NAME_ATTRIBUTE, "Rob Harrop"));
+ IJmxTestBean bean = (IJmxTestBean) getContext().getBean("testBean");
+ assertEquals("Rob Harrop", bean.getName());
+ }
+
+ public void testGetAttribute() throws Exception {
+ ObjectName objectName = ObjectNameManager.getInstance(getObjectName());
+ getBean().setName("John Smith");
+ Object val = getServer().getAttribute(objectName, NAME_ATTRIBUTE);
+ assertEquals("Incorrect result", "John Smith", val);
+ }
+
+ public void testOperationInvocation() throws Exception{
+ ObjectName objectName = ObjectNameManager.getInstance(getObjectName());
+ Object result = getServer().invoke(objectName, "add",
+ new Object[] {new Integer(20), new Integer(30)}, new String[] {"int", "int"});
+ assertEquals("Incorrect result", new Integer(50), result);
+ }
+
+ public void testAttributeInfoHasDescriptors() throws Exception {
+ ModelMBeanInfo info = getMBeanInfoFromAssembler();
+
+ ModelMBeanAttributeInfo attr = info.getAttribute(NAME_ATTRIBUTE);
+ Descriptor desc = attr.getDescriptor();
+ assertNotNull("getMethod field should not be null",
+ desc.getFieldValue("getMethod"));
+ assertNotNull("setMethod field should not be null",
+ desc.getFieldValue("setMethod"));
+ assertEquals("getMethod field has incorrect value", "getName",
+ desc.getFieldValue("getMethod"));
+ assertEquals("setMethod field has incorrect value", "setName",
+ desc.getFieldValue("setMethod"));
+ }
+
+ public void testAttributeHasCorrespondingOperations() throws Exception {
+ ModelMBeanInfo info = getMBeanInfoFromAssembler();
+
+ ModelMBeanOperationInfo get = info.getOperation("getName");
+ assertNotNull("get operation should not be null", get);
+ assertEquals("get operation should have visibility of four",
+ (Integer) get.getDescriptor().getFieldValue("visibility"),
+ new Integer(4));
+ assertEquals("get operation should have role \"getter\"", "getter", get.getDescriptor().getFieldValue("role"));
+
+ ModelMBeanOperationInfo set = info.getOperation("setName");
+ assertNotNull("set operation should not be null", set);
+ assertEquals("set operation should have visibility of four",
+ (Integer) set.getDescriptor().getFieldValue("visibility"),
+ new Integer(4));
+ assertEquals("set operation should have role \"setter\"", "setter", set.getDescriptor().getFieldValue("role"));
+ }
+
+ public void testNotificationMetadata() throws Exception {
+ ModelMBeanInfo info = (ModelMBeanInfo) getMBeanInfo();
+ MBeanNotificationInfo[] notifications = info.getNotifications();
+ assertEquals("Incorrect number of notifications", 1, notifications.length);
+ assertEquals("Incorrect notification name", "My Notification", notifications[0].getName());
+
+ String[] notifTypes = notifications[0].getNotifTypes();
+
+ assertEquals("Incorrect number of notification types", 2, notifTypes.length);
+ assertEquals("Notification type.foo not found", "type.foo", notifTypes[0]);
+ assertEquals("Notification type.bar not found", "type.bar", notifTypes[1]);
+ }
+
+ protected ModelMBeanInfo getMBeanInfoFromAssembler() throws Exception {
+ IJmxTestBean bean = getBean();
+ ModelMBeanInfo info = getAssembler().getMBeanInfo(bean, getObjectName());
+ return info;
+ }
+
+ protected IJmxTestBean getBean() {
+ Object bean = getContext().getBean("testBean");
+ return (IJmxTestBean) bean;
+ }
+
+ protected MBeanInfo getMBeanInfo() throws Exception {
+ return getServer().getMBeanInfo(ObjectNameManager.getInstance(getObjectName()));
+ }
+
+ protected ObjectInstance getObjectInstance() throws Exception {
+ return getServer().getObjectInstance(ObjectNameManager.getInstance(getObjectName()));
+ }
+
+ protected abstract int getExpectedOperationCount();
+
+ protected abstract int getExpectedAttributeCount();
+
+ protected abstract MBeanInfoAssembler getAssembler() throws Exception;
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/AbstractMetadataAssemblerAutodetectTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/AbstractMetadataAssemblerAutodetectTests.java
new file mode 100644
index 00000000000..2a5bfc77a9e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/AbstractMetadataAssemblerAutodetectTests.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jmx.export.assembler;
+
+import org.springframework.jmx.export.metadata.JmxAttributeSource;
+
+/**
+ * @author Rob Harrop
+ */
+public abstract class AbstractMetadataAssemblerAutodetectTests extends AbstractAutodetectTests {
+
+ protected AutodetectCapableMBeanInfoAssembler getAssembler() {
+ MetadataMBeanInfoAssembler assembler = new MetadataMBeanInfoAssembler();
+ assembler.setAttributeSource(getAttributeSource());
+ return assembler;
+ }
+
+ protected abstract JmxAttributeSource getAttributeSource();
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/AbstractMetadataAssemblerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/AbstractMetadataAssemblerTests.java
new file mode 100644
index 00000000000..daa055567ce
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/AbstractMetadataAssemblerTests.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jmx.export.assembler;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.management.Descriptor;
+import javax.management.MBeanInfo;
+import javax.management.MBeanParameterInfo;
+import javax.management.modelmbean.ModelMBeanAttributeInfo;
+import javax.management.modelmbean.ModelMBeanInfo;
+import javax.management.modelmbean.ModelMBeanOperationInfo;
+
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.aop.interceptor.NopInterceptor;
+import org.springframework.jmx.IJmxTestBean;
+import org.springframework.jmx.JmxTestBean;
+import org.springframework.jmx.export.MBeanExporter;
+import org.springframework.jmx.export.metadata.JmxAttributeSource;
+import org.springframework.jmx.support.ObjectNameManager;
+
+/**
+ * @author Rob Harrop
+ */
+public abstract class AbstractMetadataAssemblerTests extends AbstractJmxAssemblerTests {
+
+ public void testDescription() throws Exception {
+ ModelMBeanInfo info = getMBeanInfoFromAssembler();
+ assertEquals("The descriptions are not the same", "My Managed Bean",
+ info.getDescription());
+ }
+
+ public void testAttributeDescriptionOnSetter() throws Exception {
+ ModelMBeanInfo inf = getMBeanInfoFromAssembler();
+ ModelMBeanAttributeInfo attr = inf.getAttribute(AGE_ATTRIBUTE);
+ assertEquals("The description for the age attribute is incorrect",
+ "The Age Attribute", attr.getDescription());
+ }
+
+ public void testAttributeDescriptionOnGetter() throws Exception {
+ ModelMBeanInfo inf = getMBeanInfoFromAssembler();
+ ModelMBeanAttributeInfo attr = inf.getAttribute(NAME_ATTRIBUTE);
+ assertEquals("The description for the name attribute is incorrect",
+ "The Name Attribute", attr.getDescription());
+ }
+
+ /**
+ * Tests the situation where the attribute is only defined on the getter.
+ */
+ public void testReadOnlyAttribute() throws Exception {
+ ModelMBeanInfo inf = getMBeanInfoFromAssembler();
+ ModelMBeanAttributeInfo attr = inf.getAttribute(AGE_ATTRIBUTE);
+ assertFalse("The age attribute should not be writable", attr.isWritable());
+ }
+
+ public void testReadWriteAttribute() throws Exception {
+ ModelMBeanInfo inf = getMBeanInfoFromAssembler();
+ ModelMBeanAttributeInfo attr = inf.getAttribute(NAME_ATTRIBUTE);
+ assertTrue("The name attribute should be writable", attr.isWritable());
+ assertTrue("The name attribute should be readable", attr.isReadable());
+ }
+
+ /**
+ * Tests the situation where the property only has a getter.
+ */
+ public void testWithOnlySetter() throws Exception {
+ ModelMBeanInfo inf = getMBeanInfoFromAssembler();
+ ModelMBeanAttributeInfo attr = inf.getAttribute("NickName");
+ assertNotNull("Attribute should not be null", attr);
+ }
+
+ /**
+ * Tests the situation where the property only has a setter.
+ */
+ public void testWithOnlyGetter() throws Exception {
+ ModelMBeanInfo info = getMBeanInfoFromAssembler();
+ ModelMBeanAttributeInfo attr = info.getAttribute("Superman");
+ assertNotNull("Attribute should not be null", attr);
+ }
+
+ public void testManagedResourceDescriptor() throws Exception {
+ ModelMBeanInfo info = getMBeanInfoFromAssembler();
+ Descriptor desc = info.getMBeanDescriptor();
+
+ assertEquals("Logging should be set to true", "true", desc.getFieldValue("log"));
+ assertEquals("Log file should be jmx.log", "jmx.log", desc.getFieldValue("logFile"));
+ assertEquals("Currency Time Limit should be 15", "15", desc.getFieldValue("currencyTimeLimit"));
+ assertEquals("Persist Policy should be OnUpdate", "OnUpdate", desc.getFieldValue("persistPolicy"));
+ assertEquals("Persist Period should be 200", "200", desc.getFieldValue("persistPeriod"));
+ assertEquals("Persist Location should be foo", "./foo", desc.getFieldValue("persistLocation"));
+ assertEquals("Persist Name should be bar", "bar.jmx", desc.getFieldValue("persistName"));
+ }
+
+ public void testAttributeDescriptor() throws Exception {
+ ModelMBeanInfo info = getMBeanInfoFromAssembler();
+ Descriptor desc = info.getAttribute(NAME_ATTRIBUTE).getDescriptor();
+
+ assertEquals("Default value should be foo", "foo", desc.getFieldValue("default"));
+ assertEquals("Currency Time Limit should be 20", "20", desc.getFieldValue("currencyTimeLimit"));
+ assertEquals("Persist Policy should be OnUpdate", "OnUpdate", desc.getFieldValue("persistPolicy"));
+ assertEquals("Persist Period should be 300", "300", desc.getFieldValue("persistPeriod"));
+ }
+
+ public void testOperationDescriptor() throws Exception {
+ ModelMBeanInfo info = getMBeanInfoFromAssembler();
+ Descriptor desc = info.getOperation("myOperation").getDescriptor();
+
+ assertEquals("Currency Time Limit should be 30", "30", desc.getFieldValue("currencyTimeLimit"));
+ assertEquals("Role should be \"operation\"", "operation", desc.getFieldValue("role"));
+ }
+
+ public void testOperationParameterMetadata() throws Exception {
+ ModelMBeanInfo info = getMBeanInfoFromAssembler();
+ ModelMBeanOperationInfo oper = info.getOperation("add");
+ MBeanParameterInfo[] params = oper.getSignature();
+
+ assertEquals("Invalid number of params", 2, params.length);
+ assertEquals("Incorrect name for x param", "x", params[0].getName());
+ assertEquals("Incorrect type for x param", int.class.getName(), params[0].getType());
+
+ assertEquals("Incorrect name for y param", "y", params[1].getName());
+ assertEquals("Incorrect type for y param", int.class.getName(), params[1].getType());
+ }
+
+ public void testWithCglibProxy() throws Exception {
+ IJmxTestBean tb = createJmxTestBean();
+ ProxyFactory pf = new ProxyFactory();
+ pf.setTarget(tb);
+ pf.addAdvice(new NopInterceptor());
+ Object proxy = pf.getProxy();
+
+ MetadataMBeanInfoAssembler assembler = (MetadataMBeanInfoAssembler) getAssembler();
+
+ MBeanExporter exporter = new MBeanExporter();
+ exporter.setBeanFactory(getContext());
+ exporter.setAssembler(assembler);
+
+ String objectName = "spring:bean=test,proxy=true";
+
+ Map beans = new HashMap();
+ beans.put(objectName, proxy);
+ exporter.setBeans(beans);
+ exporter.afterPropertiesSet();
+
+ MBeanInfo inf = getServer().getMBeanInfo(ObjectNameManager.getInstance(objectName));
+ assertEquals("Incorrect number of operations", getExpectedOperationCount(), inf.getOperations().length);
+ assertEquals("Incorrect number of attributes", getExpectedAttributeCount(), inf.getAttributes().length);
+
+ assertTrue("Not included in autodetection", assembler.includeBean(proxy.getClass(), "some bean name"));
+ }
+
+ protected abstract String getObjectName();
+
+ protected int getExpectedAttributeCount() {
+ return 4;
+ }
+
+ protected int getExpectedOperationCount() {
+ return 7;
+ }
+
+ protected IJmxTestBean createJmxTestBean() {
+ return new JmxTestBean();
+ }
+
+ protected MBeanInfoAssembler getAssembler() {
+ MetadataMBeanInfoAssembler assembler = new MetadataMBeanInfoAssembler();
+ assembler.setAttributeSource(getAttributeSource());
+ return assembler;
+ }
+
+ protected abstract JmxAttributeSource getAttributeSource();
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/IAdditionalTestMethods.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/IAdditionalTestMethods.java
new file mode 100644
index 00000000000..4c7e41c7472
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/IAdditionalTestMethods.java
@@ -0,0 +1,13 @@
+
+package org.springframework.jmx.export.assembler;
+
+/**
+ * @author Rob Harrop
+ */
+public interface IAdditionalTestMethods {
+
+ String getNickName();
+
+ void setNickName(String nickName);
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/ICustomBase.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/ICustomBase.java
new file mode 100644
index 00000000000..c78d8193ab6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/ICustomBase.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jmx.export.assembler;
+
+/**
+ * @author Juergen Hoeller
+ */
+public interface ICustomBase {
+
+ int add(int x, int y);
+
+ long myOperation();
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/ICustomJmxBean.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/ICustomJmxBean.java
new file mode 100644
index 00000000000..5d3621fe3f9
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/ICustomJmxBean.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jmx.export.assembler;
+
+/**
+ * @author Rob Harrop
+ */
+public interface ICustomJmxBean extends ICustomBase {
+
+ String getName();
+
+ void setName(String name);
+
+ int getAge();
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/InterfaceBasedMBeanInfoAssemblerCustomTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/InterfaceBasedMBeanInfoAssemblerCustomTests.java
new file mode 100644
index 00000000000..5977597c1ff
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/InterfaceBasedMBeanInfoAssemblerCustomTests.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jmx.export.assembler;
+
+import javax.management.modelmbean.ModelMBeanAttributeInfo;
+import javax.management.modelmbean.ModelMBeanInfo;
+
+/**
+ * @author Rob Harrop
+ */
+public class InterfaceBasedMBeanInfoAssemblerCustomTests extends AbstractJmxAssemblerTests {
+
+ protected static final String OBJECT_NAME = "bean:name=testBean5";
+
+ protected String getObjectName() {
+ return OBJECT_NAME;
+ }
+
+ protected int getExpectedOperationCount() {
+ return 5;
+ }
+
+ protected int getExpectedAttributeCount() {
+ return 2;
+ }
+
+ protected MBeanInfoAssembler getAssembler() {
+ InterfaceBasedMBeanInfoAssembler assembler = new InterfaceBasedMBeanInfoAssembler();
+ assembler.setManagedInterfaces(new Class[] {ICustomJmxBean.class});
+ return assembler;
+ }
+
+ public void testGetAgeIsReadOnly() throws Exception {
+ ModelMBeanInfo info = getMBeanInfoFromAssembler();
+ ModelMBeanAttributeInfo attr = info.getAttribute(AGE_ATTRIBUTE);
+
+ assertTrue(attr.isReadable());
+ assertFalse(attr.isWritable());
+ }
+
+ protected String getApplicationContextPath() {
+ return "org/springframework/jmx/export/assembler/interfaceAssemblerCustom.xml";
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/InterfaceBasedMBeanInfoAssemblerMappedTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/InterfaceBasedMBeanInfoAssemblerMappedTests.java
new file mode 100644
index 00000000000..87693fc924f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/InterfaceBasedMBeanInfoAssemblerMappedTests.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jmx.export.assembler;
+
+import java.util.Properties;
+
+import javax.management.MBeanAttributeInfo;
+import javax.management.modelmbean.ModelMBeanAttributeInfo;
+import javax.management.modelmbean.ModelMBeanInfo;
+
+/**
+ * @author Rob Harrop
+ */
+public class InterfaceBasedMBeanInfoAssemblerMappedTests extends AbstractJmxAssemblerTests {
+
+ protected static final String OBJECT_NAME = "bean:name=testBean4";
+
+ public void testGetAgeIsReadOnly() throws Exception {
+ ModelMBeanInfo info = getMBeanInfoFromAssembler();
+ ModelMBeanAttributeInfo attr = info.getAttribute(AGE_ATTRIBUTE);
+
+ assertTrue("Age is not readable", attr.isReadable());
+ assertFalse("Age is not writable", attr.isWritable());
+ }
+
+ public void testWithUnknownClass() throws Exception {
+ try {
+ InterfaceBasedMBeanInfoAssembler assembler = getWithMapping("com.foo.bar.Unknown");
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ public void testWithNonInterface() throws Exception {
+ try {
+ InterfaceBasedMBeanInfoAssembler assembler = getWithMapping("JmxTestBean");
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ public void testWithFallThrough() throws Exception {
+ InterfaceBasedMBeanInfoAssembler assembler =
+ getWithMapping("foobar", "org.springframework.jmx.export.assembler.ICustomJmxBean");
+ assembler.setManagedInterfaces(new Class[] {IAdditionalTestMethods.class});
+
+ ModelMBeanInfo inf = assembler.getMBeanInfo(getBean(), getObjectName());
+ MBeanAttributeInfo attr = inf.getAttribute("NickName");
+
+ assertNickName(attr);
+ }
+
+ public void testNickNameIsExposed() throws Exception {
+ ModelMBeanInfo inf = (ModelMBeanInfo) getMBeanInfo();
+ MBeanAttributeInfo attr = inf.getAttribute("NickName");
+
+ assertNickName(attr);
+ }
+
+ protected String getObjectName() {
+ return OBJECT_NAME;
+ }
+
+ protected int getExpectedOperationCount() {
+ return 7;
+ }
+
+ protected int getExpectedAttributeCount() {
+ return 3;
+ }
+
+ protected MBeanInfoAssembler getAssembler() throws Exception {
+ return getWithMapping(
+ "org.springframework.jmx.export.assembler.IAdditionalTestMethods, " +
+ "org.springframework.jmx.export.assembler.ICustomJmxBean");
+ }
+
+ protected String getApplicationContextPath() {
+ return "org/springframework/jmx/export/assembler/interfaceAssemblerMapped.xml";
+ }
+
+ private InterfaceBasedMBeanInfoAssembler getWithMapping(String mapping) {
+ return getWithMapping(OBJECT_NAME, mapping);
+ }
+
+ private InterfaceBasedMBeanInfoAssembler getWithMapping(String name, String mapping) {
+ InterfaceBasedMBeanInfoAssembler assembler = new InterfaceBasedMBeanInfoAssembler();
+ Properties props = new Properties();
+ props.setProperty(name, mapping);
+ assembler.setInterfaceMappings(props);
+ assembler.afterPropertiesSet();
+ return assembler;
+ }
+
+ private void assertNickName(MBeanAttributeInfo attr) {
+ assertNotNull("Nick Name should not be null", attr);
+ assertTrue("Nick Name should be writable", attr.isWritable());
+ assertTrue("Nick Name should be readab;e", attr.isReadable());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/InterfaceBasedMBeanInfoAssemblerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/InterfaceBasedMBeanInfoAssemblerTests.java
new file mode 100644
index 00000000000..6d8266b4aca
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/InterfaceBasedMBeanInfoAssemblerTests.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jmx.export.assembler;
+
+/**
+ * @author Rob Harrop
+ */
+public class InterfaceBasedMBeanInfoAssemblerTests extends AbstractJmxAssemblerTests {
+
+ protected String getObjectName() {
+ return "bean:name=testBean4";
+ }
+
+ protected int getExpectedOperationCount() {
+ return 7;
+ }
+
+ protected int getExpectedAttributeCount() {
+ return 2;
+ }
+
+ protected MBeanInfoAssembler getAssembler() {
+ return new InterfaceBasedMBeanInfoAssembler();
+ }
+
+ protected String getApplicationContextPath() {
+ return "org/springframework/jmx/export/assembler/interfaceAssembler.xml";
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/MethodExclusionMBeanInfoAssemblerComboTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/MethodExclusionMBeanInfoAssemblerComboTests.java
new file mode 100644
index 00000000000..73d4fb56f51
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/MethodExclusionMBeanInfoAssemblerComboTests.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jmx.export.assembler;
+
+import java.util.Properties;
+
+import javax.management.MBeanAttributeInfo;
+import javax.management.modelmbean.ModelMBeanAttributeInfo;
+import javax.management.modelmbean.ModelMBeanInfo;
+
+/**
+ * @author Juergen Hoeller
+ * @author Rob Harrop
+ */
+public class MethodExclusionMBeanInfoAssemblerComboTests extends AbstractJmxAssemblerTests {
+
+ protected static final String OBJECT_NAME = "bean:name=testBean4";
+
+ public void testGetAgeIsReadOnly() throws Exception {
+ ModelMBeanInfo info = getMBeanInfoFromAssembler();
+ ModelMBeanAttributeInfo attr = info.getAttribute(AGE_ATTRIBUTE);
+ assertTrue("Age is not readable", attr.isReadable());
+ assertFalse("Age is not writable", attr.isWritable());
+ }
+
+ public void testNickNameIsExposed() throws Exception {
+ ModelMBeanInfo inf = (ModelMBeanInfo) getMBeanInfo();
+ MBeanAttributeInfo attr = inf.getAttribute("NickName");
+ assertNotNull("Nick Name should not be null", attr);
+ assertTrue("Nick Name should be writable", attr.isWritable());
+ assertTrue("Nick Name should be readable", attr.isReadable());
+ }
+
+ protected String getObjectName() {
+ return OBJECT_NAME;
+ }
+
+ protected int getExpectedOperationCount() {
+ return 7;
+ }
+
+ protected int getExpectedAttributeCount() {
+ return 3;
+ }
+
+ protected String getApplicationContextPath() {
+ return "org/springframework/jmx/export/assembler/methodExclusionAssemblerCombo.xml";
+ }
+
+ protected MBeanInfoAssembler getAssembler() throws Exception {
+ MethodExclusionMBeanInfoAssembler assembler = new MethodExclusionMBeanInfoAssembler();
+ Properties props = new Properties();
+ props.setProperty(OBJECT_NAME, "setAge,isSuperman,setSuperman,dontExposeMe");
+ assembler.setIgnoredMethodMappings(props);
+ assembler.setIgnoredMethods(new String[] {"someMethod"});
+ return assembler;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/MethodExclusionMBeanInfoAssemblerMappedTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/MethodExclusionMBeanInfoAssemblerMappedTests.java
new file mode 100644
index 00000000000..a3f11f9fef6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/MethodExclusionMBeanInfoAssemblerMappedTests.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jmx.export.assembler;
+
+import java.util.Properties;
+
+import javax.management.MBeanAttributeInfo;
+import javax.management.modelmbean.ModelMBeanAttributeInfo;
+import javax.management.modelmbean.ModelMBeanInfo;
+
+/**
+ * @author Rob Harrop
+ */
+public class MethodExclusionMBeanInfoAssemblerMappedTests extends AbstractJmxAssemblerTests {
+
+ protected static final String OBJECT_NAME = "bean:name=testBean4";
+
+ public void testGetAgeIsReadOnly() throws Exception {
+ ModelMBeanInfo info = getMBeanInfoFromAssembler();
+ ModelMBeanAttributeInfo attr = info.getAttribute(AGE_ATTRIBUTE);
+ assertTrue("Age is not readable", attr.isReadable());
+ assertFalse("Age is not writable", attr.isWritable());
+ }
+
+ public void testNickNameIsExposed() throws Exception {
+ ModelMBeanInfo inf = (ModelMBeanInfo) getMBeanInfo();
+ MBeanAttributeInfo attr = inf.getAttribute("NickName");
+ assertNotNull("Nick Name should not be null", attr);
+ assertTrue("Nick Name should be writable", attr.isWritable());
+ assertTrue("Nick Name should be readable", attr.isReadable());
+ }
+
+ protected String getObjectName() {
+ return OBJECT_NAME;
+ }
+
+ protected int getExpectedOperationCount() {
+ return 7;
+ }
+
+ protected int getExpectedAttributeCount() {
+ return 3;
+ }
+
+ protected String getApplicationContextPath() {
+ return "org/springframework/jmx/export/assembler/methodExclusionAssemblerMapped.xml";
+ }
+
+ protected MBeanInfoAssembler getAssembler() throws Exception {
+ MethodExclusionMBeanInfoAssembler assembler = new MethodExclusionMBeanInfoAssembler();
+ Properties props = new Properties();
+ props.setProperty(OBJECT_NAME, "setAge,isSuperman,setSuperman,dontExposeMe");
+ assembler.setIgnoredMethodMappings(props);
+ return assembler;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/MethodExclusionMBeanInfoAssemblerNotMappedTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/MethodExclusionMBeanInfoAssemblerNotMappedTests.java
new file mode 100644
index 00000000000..c19ef5969da
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/MethodExclusionMBeanInfoAssemblerNotMappedTests.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jmx.export.assembler;
+
+import java.util.Properties;
+
+import javax.management.MBeanAttributeInfo;
+import javax.management.modelmbean.ModelMBeanAttributeInfo;
+import javax.management.modelmbean.ModelMBeanInfo;
+
+/**
+ * @author Juergen Hoeller
+ * @author Rob Harrop
+ */
+public class MethodExclusionMBeanInfoAssemblerNotMappedTests extends AbstractJmxAssemblerTests {
+
+ protected static final String OBJECT_NAME = "bean:name=testBean4";
+
+ public void testGetAgeIsReadOnly() throws Exception {
+ ModelMBeanInfo info = getMBeanInfoFromAssembler();
+ ModelMBeanAttributeInfo attr = info.getAttribute(AGE_ATTRIBUTE);
+ assertTrue("Age is not readable", attr.isReadable());
+ assertTrue("Age is not writable", attr.isWritable());
+ }
+
+ public void testNickNameIsExposed() throws Exception {
+ ModelMBeanInfo inf = (ModelMBeanInfo) getMBeanInfo();
+ MBeanAttributeInfo attr = inf.getAttribute("NickName");
+ assertNotNull("Nick Name should not be null", attr);
+ assertTrue("Nick Name should be writable", attr.isWritable());
+ assertTrue("Nick Name should be readable", attr.isReadable());
+ }
+
+ protected String getObjectName() {
+ return OBJECT_NAME;
+ }
+
+ protected int getExpectedOperationCount() {
+ return 11;
+ }
+
+ protected int getExpectedAttributeCount() {
+ return 4;
+ }
+
+ protected String getApplicationContextPath() {
+ return "org/springframework/jmx/export/assembler/methodExclusionAssemblerNotMapped.xml";
+ }
+
+ protected MBeanInfoAssembler getAssembler() throws Exception {
+ MethodExclusionMBeanInfoAssembler assembler = new MethodExclusionMBeanInfoAssembler();
+ Properties props = new Properties();
+ props.setProperty("bean:name=testBean5", "setAge,isSuperman,setSuperman,dontExposeMe");
+ assembler.setIgnoredMethodMappings(props);
+ return assembler;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/MethodExclusionMBeanInfoAssemblerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/MethodExclusionMBeanInfoAssemblerTests.java
new file mode 100644
index 00000000000..64c6bb7f395
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/MethodExclusionMBeanInfoAssemblerTests.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jmx.export.assembler;
+
+import java.lang.reflect.Method;
+import java.util.Properties;
+
+import javax.management.modelmbean.ModelMBeanAttributeInfo;
+import javax.management.modelmbean.ModelMBeanInfo;
+
+import org.springframework.jmx.JmxTestBean;
+
+/**
+ * @author Rob Harrop
+ * @author Rick Evans
+ */
+public class MethodExclusionMBeanInfoAssemblerTests extends AbstractJmxAssemblerTests {
+
+ private static final String OBJECT_NAME = "bean:name=testBean5";
+
+
+ protected String getObjectName() {
+ return OBJECT_NAME;
+ }
+
+ protected int getExpectedOperationCount() {
+ return 9;
+ }
+
+ protected int getExpectedAttributeCount() {
+ return 4;
+ }
+
+ protected String getApplicationContextPath() {
+ return "org/springframework/jmx/export/assembler/methodExclusionAssembler.xml";
+ }
+
+ protected MBeanInfoAssembler getAssembler() {
+ MethodExclusionMBeanInfoAssembler assembler = new MethodExclusionMBeanInfoAssembler();
+ assembler.setIgnoredMethods(new String[] {"dontExposeMe", "setSuperman"});
+ return assembler;
+ }
+
+ public void testSupermanIsReadOnly() throws Exception {
+ ModelMBeanInfo info = getMBeanInfoFromAssembler();
+ ModelMBeanAttributeInfo attr = info.getAttribute("Superman");
+
+ assertTrue(attr.isReadable());
+ assertFalse(attr.isWritable());
+ }
+
+ /*
+ * http://opensource.atlassian.com/projects/spring/browse/SPR-2754
+ */
+ public void testIsNotIgnoredDoesntIgnoreUnspecifiedBeanMethods() throws Exception {
+ final String beanKey = "myTestBean";
+ MethodExclusionMBeanInfoAssembler assembler = new MethodExclusionMBeanInfoAssembler();
+ Properties ignored = new Properties();
+ ignored.setProperty(beanKey, "dontExposeMe,setSuperman");
+ assembler.setIgnoredMethodMappings(ignored);
+ Method method = JmxTestBean.class.getMethod("dontExposeMe", null);
+ assertFalse(assembler.isNotIgnored(method, beanKey));
+ // this bean does not have any ignored methods on it, so must obviously not be ignored...
+ assertTrue(assembler.isNotIgnored(method, "someOtherBeanKey"));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/MethodNameBasedMBeanInfoAssemblerMappedTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/MethodNameBasedMBeanInfoAssemblerMappedTests.java
new file mode 100644
index 00000000000..71bbbad39ed
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/MethodNameBasedMBeanInfoAssemblerMappedTests.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jmx.export.assembler;
+
+import javax.management.MBeanAttributeInfo;
+import javax.management.modelmbean.ModelMBeanAttributeInfo;
+import javax.management.modelmbean.ModelMBeanInfo;
+import java.util.Properties;
+
+/**
+ * @author Rob Harrop
+ */
+public class MethodNameBasedMBeanInfoAssemblerMappedTests extends AbstractJmxAssemblerTests {
+
+ protected static final String OBJECT_NAME = "bean:name=testBean4";
+
+ public void testGetAgeIsReadOnly() throws Exception {
+ ModelMBeanInfo info = getMBeanInfoFromAssembler();
+ ModelMBeanAttributeInfo attr = info.getAttribute(AGE_ATTRIBUTE);
+
+ assertTrue("Age is not readable", attr.isReadable());
+ assertFalse("Age is not writable", attr.isWritable());
+ }
+
+ public void testWithFallThrough() throws Exception {
+ MethodNameBasedMBeanInfoAssembler assembler =
+ getWithMapping("foobar", "add,myOperation,getName,setName,getAge");
+ assembler.setManagedMethods(new String[]{"getNickName", "setNickName"});
+
+ ModelMBeanInfo inf = assembler.getMBeanInfo(getBean(), getObjectName());
+ MBeanAttributeInfo attr = inf.getAttribute("NickName");
+
+ assertNickName(attr);
+ }
+
+ public void testNickNameIsExposed() throws Exception {
+ ModelMBeanInfo inf = (ModelMBeanInfo) getMBeanInfo();
+ MBeanAttributeInfo attr = inf.getAttribute("NickName");
+
+ assertNickName(attr);
+ }
+
+ protected String getObjectName() {
+ return OBJECT_NAME;
+ }
+
+ protected int getExpectedOperationCount() {
+ return 7;
+ }
+
+ protected int getExpectedAttributeCount() {
+ return 3;
+ }
+
+ protected MBeanInfoAssembler getAssembler() throws Exception {
+ return getWithMapping("getNickName,setNickName,add,myOperation,getName,setName,getAge");
+ }
+
+ protected String getApplicationContextPath() {
+ return "org/springframework/jmx/export/assembler/methodNameAssemblerMapped.xml";
+ }
+
+ private MethodNameBasedMBeanInfoAssembler getWithMapping(String mapping) {
+ return getWithMapping(OBJECT_NAME, mapping);
+ }
+
+ private MethodNameBasedMBeanInfoAssembler getWithMapping(String name, String mapping) {
+ MethodNameBasedMBeanInfoAssembler assembler = new MethodNameBasedMBeanInfoAssembler();
+ Properties props = new Properties();
+ props.setProperty(name, mapping);
+ assembler.setMethodMappings(props);
+ return assembler;
+ }
+
+ private void assertNickName(MBeanAttributeInfo attr) {
+ assertNotNull("Nick Name should not be null", attr);
+ assertTrue("Nick Name should be writable", attr.isWritable());
+ assertTrue("Nick Name should be readable", attr.isReadable());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/MethodNameBasedMBeanInfoAssemblerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/MethodNameBasedMBeanInfoAssemblerTests.java
new file mode 100644
index 00000000000..049c7fde5f7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/MethodNameBasedMBeanInfoAssemblerTests.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jmx.export.assembler;
+
+import javax.management.modelmbean.ModelMBeanAttributeInfo;
+import javax.management.modelmbean.ModelMBeanInfo;
+
+/**
+ * @author Rob Harrop
+ */
+public class MethodNameBasedMBeanInfoAssemblerTests extends AbstractJmxAssemblerTests {
+
+ protected static final String OBJECT_NAME = "bean:name=testBean5";
+
+ protected String getObjectName() {
+ return OBJECT_NAME;
+ }
+
+ protected int getExpectedOperationCount() {
+ return 5;
+ }
+
+ protected int getExpectedAttributeCount() {
+ return 2;
+ }
+
+ protected MBeanInfoAssembler getAssembler() {
+ MethodNameBasedMBeanInfoAssembler assembler = new MethodNameBasedMBeanInfoAssembler();
+ assembler.setManagedMethods(new String[] {"add", "myOperation", "getName", "setName", "getAge"});
+ return assembler;
+ }
+
+ public void testGetAgeIsReadOnly() throws Exception {
+ ModelMBeanInfo info = getMBeanInfoFromAssembler();
+ ModelMBeanAttributeInfo attr = info.getAttribute(AGE_ATTRIBUTE);
+
+ assertTrue(attr.isReadable());
+ assertFalse(attr.isWritable());
+ }
+
+ protected String getApplicationContextPath() {
+ return "org/springframework/jmx/export/assembler/methodNameAssembler.xml";
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/ReflectiveAssemblerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/ReflectiveAssemblerTests.java
new file mode 100644
index 00000000000..c231561fc91
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/ReflectiveAssemblerTests.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jmx.export.assembler;
+
+
+
+
+/**
+ * @author Rob Harrop
+ */
+public class ReflectiveAssemblerTests extends AbstractJmxAssemblerTests {
+
+ protected static final String OBJECT_NAME = "bean:name=testBean1";
+
+ protected String getObjectName() {
+ return OBJECT_NAME;
+ }
+
+ protected int getExpectedOperationCount() {
+ return 11;
+ }
+
+ protected int getExpectedAttributeCount() {
+ return 4;
+ }
+
+ protected MBeanInfoAssembler getAssembler() {
+ return new SimpleReflectiveMBeanInfoAssembler();
+ }
+
+ protected String getApplicationContextPath() {
+ return "org/springframework/jmx/export/assembler/reflectiveAssembler.xml";
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/interfaceAssembler.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/interfaceAssembler.xml
new file mode 100644
index 00000000000..0e0ca9a6f3a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/interfaceAssembler.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TEST
+
+
+ 100
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/interfaceAssemblerCustom.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/interfaceAssemblerCustom.xml
new file mode 100644
index 00000000000..5246986ac05
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/interfaceAssemblerCustom.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.springframework.jmx.export.assembler.ICustomJmxBean
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TEST
+
+
+ 100
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/interfaceAssemblerMapped.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/interfaceAssemblerMapped.xml
new file mode 100644
index 00000000000..1d8df62050b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/interfaceAssemblerMapped.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.springframework.jmx.export.assembler.IAdditionalTestMethods,
+ org.springframework.jmx.export.assembler.ICustomJmxBean
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TEST
+
+
+ 100
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/metadata-autodetect.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/metadata-autodetect.xml
new file mode 100644
index 00000000000..c90c5284c21
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/metadata-autodetect.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TEST
+
+
+ 100
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/metadataAssembler.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/metadataAssembler.xml
new file mode 100644
index 00000000000..c43e200a596
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/metadataAssembler.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TEST
+
+
+ 100
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/methodExclusionAssembler.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/methodExclusionAssembler.xml
new file mode 100644
index 00000000000..5a4c3585a7f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/methodExclusionAssembler.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/methodExclusionAssemblerCombo.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/methodExclusionAssemblerCombo.xml
new file mode 100644
index 00000000000..b2fb2536840
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/methodExclusionAssemblerCombo.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ setAge,isSuperman,setSuperman,dontExposeMe
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/methodExclusionAssemblerMapped.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/methodExclusionAssemblerMapped.xml
new file mode 100644
index 00000000000..16f4290a8f3
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/methodExclusionAssemblerMapped.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ setAge,isSuperman,setSuperman,dontExposeMe
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/methodExclusionAssemblerNotMapped.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/methodExclusionAssemblerNotMapped.xml
new file mode 100644
index 00000000000..7dcf380c525
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/methodExclusionAssemblerNotMapped.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ setAge,isSuperman,setSuperman,dontExposeMe
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/methodNameAssembler.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/methodNameAssembler.xml
new file mode 100644
index 00000000000..20554a2a311
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/methodNameAssembler.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ add,myOperation,getName,setName,getAge
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TEST
+
+
+ 100
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/methodNameAssemblerMapped.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/methodNameAssemblerMapped.xml
new file mode 100644
index 00000000000..98944a99845
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/methodNameAssemblerMapped.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ getNickName,setNickName,add,myOperation,getName,setName,getAge
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TEST
+
+
+ 100
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/reflectiveAssembler.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/reflectiveAssembler.xml
new file mode 100644
index 00000000000..e61a8eb0ad2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/assembler/reflectiveAssembler.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TEST
+
+
+ 100
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/autodetectLazyMBeans.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/autodetectLazyMBeans.xml
new file mode 100644
index 00000000000..960a57b12cb
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/autodetectLazyMBeans.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/autodetectMBeans.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/autodetectMBeans.xml
new file mode 100644
index 00000000000..c45205909b9
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/autodetectMBeans.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/autodetectNoMBeans.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/autodetectNoMBeans.xml
new file mode 100644
index 00000000000..66c6033611c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/autodetectNoMBeans.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/customConfigurer.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/customConfigurer.xml
new file mode 100644
index 00000000000..dea76ccada0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/customConfigurer.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ yyyy/MM/dd
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+ 2004/10/12
+
+
+ 2004/11/13
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/excludedBeans.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/excludedBeans.xml
new file mode 100644
index 00000000000..6dc3aba71f9
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/excludedBeans.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/lazyInit.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/lazyInit.xml
new file mode 100644
index 00000000000..ddc1fb1da89
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/lazyInit.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/naming/AbstractNamingStrategyTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/naming/AbstractNamingStrategyTests.java
new file mode 100644
index 00000000000..0007e7ef703
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/naming/AbstractNamingStrategyTests.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jmx.export.naming;
+
+import javax.management.ObjectName;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rob Harrop
+ */
+public abstract class AbstractNamingStrategyTests extends TestCase {
+
+ public void testNaming() throws Exception {
+ ObjectNamingStrategy strat = getStrategy();
+ ObjectName objectName = strat.getObjectName(getManagedResource(), getKey());
+ assertEquals(objectName.getCanonicalName(), getCorrectObjectName());
+ }
+
+ protected abstract ObjectNamingStrategy getStrategy() throws Exception;
+
+ protected abstract Object getManagedResource() throws Exception;
+
+ protected abstract String getKey();
+
+ protected abstract String getCorrectObjectName();
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/naming/IdentityNamingStrategyTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/naming/IdentityNamingStrategyTests.java
new file mode 100644
index 00000000000..a62755bd0f0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/naming/IdentityNamingStrategyTests.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jmx.export.naming;
+
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+
+import junit.framework.TestCase;
+
+import org.springframework.jmx.JmxTestBean;
+import org.springframework.util.ClassUtils;
+import org.springframework.util.ObjectUtils;
+
+/**
+ * @author Rob Harrop
+ */
+public class IdentityNamingStrategyTests extends TestCase {
+
+ public void testNaming() throws MalformedObjectNameException {
+ JmxTestBean bean = new JmxTestBean();
+ IdentityNamingStrategy strategy = new IdentityNamingStrategy();
+ ObjectName objectName = strategy.getObjectName(bean, "null");
+ assertEquals("Domain is incorrect", bean.getClass().getPackage().getName(),
+ objectName.getDomain());
+ assertEquals("Type property is incorrect", ClassUtils.getShortName(bean.getClass()),
+ objectName.getKeyProperty(IdentityNamingStrategy.TYPE_KEY));
+ assertEquals("HashCode property is incorrect", ObjectUtils.getIdentityHexString(bean),
+ objectName.getKeyProperty(IdentityNamingStrategy.HASH_CODE_KEY));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/naming/KeyNamingStrategyTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/naming/KeyNamingStrategyTests.java
new file mode 100644
index 00000000000..9fa33e73ed4
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/naming/KeyNamingStrategyTests.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jmx.export.naming;
+
+/**
+ * @author Rob Harrop
+ */
+public class KeyNamingStrategyTests extends AbstractNamingStrategyTests {
+
+ private static final String OBJECT_NAME = "spring:name=test";
+
+ protected ObjectNamingStrategy getStrategy() throws Exception {
+ return new KeyNamingStrategy();
+ }
+
+ protected Object getManagedResource() {
+ return new Object();
+ }
+
+ protected String getKey() {
+ return OBJECT_NAME;
+ }
+
+ protected String getCorrectObjectName() {
+ return OBJECT_NAME;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/naming/PropertiesFileNamingStrategyTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/naming/PropertiesFileNamingStrategyTests.java
new file mode 100644
index 00000000000..9011c372967
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/naming/PropertiesFileNamingStrategyTests.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jmx.export.naming;
+
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class PropertiesFileNamingStrategyTests extends PropertiesNamingStrategyTests {
+
+ protected ObjectNamingStrategy getStrategy() throws Exception {
+ KeyNamingStrategy strat = new KeyNamingStrategy();
+ strat.setMappingLocation(new ClassPathResource("jmx-names.properties", getClass()));
+ strat.afterPropertiesSet();
+ return strat;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/naming/PropertiesNamingStrategyTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/naming/PropertiesNamingStrategyTests.java
new file mode 100644
index 00000000000..7ce9e2ecde1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/naming/PropertiesNamingStrategyTests.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jmx.export.naming;
+
+import java.util.Properties;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class PropertiesNamingStrategyTests extends AbstractNamingStrategyTests {
+
+ private static final String OBJECT_NAME = "bean:name=namingTest";
+
+ protected ObjectNamingStrategy getStrategy() throws Exception {
+ KeyNamingStrategy strat = new KeyNamingStrategy();
+ Properties mappings = new Properties();
+ mappings.setProperty("namingTest", "bean:name=namingTest");
+ strat.setMappings(mappings);
+ strat.afterPropertiesSet();
+ return strat;
+ }
+
+ protected Object getManagedResource() {
+ return new Object();
+ }
+
+ protected String getKey() {
+ return "namingTest";
+ }
+
+ protected String getCorrectObjectName() {
+ return OBJECT_NAME;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/naming/jmx-names.properties b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/naming/jmx-names.properties
new file mode 100644
index 00000000000..9239236b2be
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/naming/jmx-names.properties
@@ -0,0 +1 @@
+namingTest = bean:name=namingTest
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/notification/ModelMBeanNotificationPublisherTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/notification/ModelMBeanNotificationPublisherTests.java
new file mode 100644
index 00000000000..486a35df6e0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/notification/ModelMBeanNotificationPublisherTests.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jmx.export.notification;
+
+import javax.management.AttributeChangeNotification;
+import javax.management.MBeanException;
+import javax.management.MalformedObjectNameException;
+import javax.management.Notification;
+import javax.management.ObjectName;
+import javax.management.RuntimeOperationsException;
+
+import junit.framework.TestCase;
+
+import org.springframework.jmx.export.SpringModelMBean;
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Rick Evans
+ */
+public final class ModelMBeanNotificationPublisherTests extends TestCase {
+
+ public void testCtorWithNullMBean() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new ModelMBeanNotificationPublisher(null, createObjectName(), this);
+ }
+ }.runTest();
+ }
+
+ public void testCtorWithNullObjectName() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new ModelMBeanNotificationPublisher(new SpringModelMBean(), null, this);
+ }
+ }.runTest();
+ }
+
+ public void testCtorWithNullManagedResource() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new ModelMBeanNotificationPublisher(new SpringModelMBean(), createObjectName(), null);
+ }
+ }.runTest();
+ }
+
+ public void testSendNullNotification() throws Exception {
+ final NotificationPublisher publisher
+ = new ModelMBeanNotificationPublisher(new SpringModelMBean(), createObjectName(), this);
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ publisher.sendNotification(null);
+ }
+ }.runTest();
+ }
+
+ public void testSendVanillaNotification() throws Exception {
+ StubSpringModelMBean mbean = new StubSpringModelMBean();
+ Notification notification = new Notification("network.alarm.router", mbean, 1872);
+ ObjectName objectName = createObjectName();
+
+ NotificationPublisher publisher = new ModelMBeanNotificationPublisher(mbean, objectName, mbean);
+ publisher.sendNotification(notification);
+
+ assertNotNull(mbean.getActualNotification());
+ assertSame("The exact same Notification is not being passed through from the publisher to the mbean.", notification, mbean.getActualNotification());
+ assertSame("The 'source' property of the Notification is not being set to the ObjectName of the associated MBean.", objectName, mbean.getActualNotification().getSource());
+ }
+
+ public void testSendAttributeChangeNotification() throws Exception {
+ StubSpringModelMBean mbean = new StubSpringModelMBean();
+ Notification notification = new AttributeChangeNotification(mbean, 1872, System.currentTimeMillis(), "Shall we break for some tea?", "agree", "java.lang.Boolean", Boolean.FALSE, Boolean.TRUE);
+ ObjectName objectName = createObjectName();
+
+ NotificationPublisher publisher = new ModelMBeanNotificationPublisher(mbean, objectName, mbean);
+ publisher.sendNotification(notification);
+
+ assertNotNull(mbean.getActualNotification());
+ assertTrue(mbean.getActualNotification() instanceof AttributeChangeNotification);
+ assertSame("The exact same Notification is not being passed through from the publisher to the mbean.", notification, mbean.getActualNotification());
+ assertSame("The 'source' property of the Notification is not being set to the ObjectName of the associated MBean.", objectName, mbean.getActualNotification().getSource());
+ }
+
+ public void testSendAttributeChangeNotificationWhereSourceIsNotTheManagedResource() throws Exception {
+ StubSpringModelMBean mbean = new StubSpringModelMBean();
+ Notification notification = new AttributeChangeNotification(this, 1872, System.currentTimeMillis(), "Shall we break for some tea?", "agree", "java.lang.Boolean", Boolean.FALSE, Boolean.TRUE);
+ ObjectName objectName = createObjectName();
+
+ NotificationPublisher publisher = new ModelMBeanNotificationPublisher(mbean, objectName, mbean);
+ publisher.sendNotification(notification);
+
+ assertNotNull(mbean.getActualNotification());
+ assertTrue(mbean.getActualNotification() instanceof AttributeChangeNotification);
+ assertSame("The exact same Notification is not being passed through from the publisher to the mbean.", notification, mbean.getActualNotification());
+ assertSame("The 'source' property of the Notification is *wrongly* being set to the ObjectName of the associated MBean.", this, mbean.getActualNotification().getSource());
+ }
+
+ private static ObjectName createObjectName() throws MalformedObjectNameException {
+ return ObjectName.getInstance("foo:type=bar");
+ }
+
+
+ private static class StubSpringModelMBean extends SpringModelMBean {
+
+ private Notification actualNotification;
+
+ public StubSpringModelMBean() throws MBeanException, RuntimeOperationsException {
+ }
+
+ public Notification getActualNotification() {
+ return this.actualNotification;
+ }
+
+ public void sendNotification(Notification notification) throws RuntimeOperationsException {
+ this.actualNotification = notification;
+ }
+
+ public void sendAttributeChangeNotification(AttributeChangeNotification notification) throws RuntimeOperationsException {
+ this.actualNotification = notification;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/notificationPublisherLazyTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/notificationPublisherLazyTests.xml
new file mode 100644
index 00000000000..9489f7bfe18
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/notificationPublisherLazyTests.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/notificationPublisherTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/notificationPublisherTests.xml
new file mode 100644
index 00000000000..459820c27dc
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/notificationPublisherTests.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/propertyPlaceholderConfigurer.xml b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/propertyPlaceholderConfigurer.xml
new file mode 100644
index 00000000000..b108c30e01d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/export/propertyPlaceholderConfigurer.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+ Rob Harrop
+ 100
+ myScope
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${testBean.name}
+
+
+ ${testBean.age}
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/support/ConnectorServerFactoryBeanTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/support/ConnectorServerFactoryBeanTests.java
new file mode 100644
index 00000000000..8525535ef8f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/support/ConnectorServerFactoryBeanTests.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jmx.support;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+
+import org.springframework.jmx.AbstractMBeanServerTests;
+
+/**
+ * @author Rob Harrop
+ */
+public class ConnectorServerFactoryBeanTests extends AbstractMBeanServerTests {
+
+ private static final String OBJECT_NAME = "spring:type=connector,name=test";
+
+ public void testStartupWithLocatedServer() throws Exception {
+ ConnectorServerFactoryBean bean = new ConnectorServerFactoryBean();
+ bean.afterPropertiesSet();
+
+ try {
+ checkServerConnection(getServer());
+ }
+ finally {
+ bean.destroy();
+ }
+ }
+
+ public void testStartupWithSuppliedServer() throws Exception {
+ //Added a brief snooze here - seems to fix occasional
+ //java.net.BindException: Address already in use errors
+ Thread.sleep(1);
+
+ ConnectorServerFactoryBean bean = new ConnectorServerFactoryBean();
+ bean.setServer(getServer());
+ bean.afterPropertiesSet();
+
+ try {
+ checkServerConnection(getServer());
+ }
+ finally {
+ bean.destroy();
+ }
+ }
+
+ public void testRegisterWithMBeanServer() throws Exception {
+ //Added a brief snooze here - seems to fix occasional
+ //java.net.BindException: Address already in use errors
+ Thread.sleep(1);
+ ConnectorServerFactoryBean bean = new ConnectorServerFactoryBean();
+ bean.setObjectName(OBJECT_NAME);
+ bean.afterPropertiesSet();
+
+ try {
+ // Try to get the connector bean.
+ ObjectInstance instance = getServer().getObjectInstance(ObjectName.getInstance(OBJECT_NAME));
+ assertNotNull("ObjectInstance should not be null", instance);
+ }
+ finally {
+ bean.destroy();
+ }
+ }
+
+ public void testNoRegisterWithMBeanServer() throws Exception {
+ ConnectorServerFactoryBean bean = new ConnectorServerFactoryBean();
+ bean.afterPropertiesSet();
+
+ try {
+ // Try to get the connector bean.
+ getServer().getObjectInstance(ObjectName.getInstance(OBJECT_NAME));
+ fail("Instance should not be found");
+ }
+ catch (InstanceNotFoundException ex) {
+ // expected
+ }
+ finally {
+ bean.destroy();
+ }
+ }
+
+ private void checkServerConnection(MBeanServer hostedServer) throws IOException, MalformedURLException {
+ // Try to connect using client.
+ JMXServiceURL serviceURL = new JMXServiceURL(ConnectorServerFactoryBean.DEFAULT_SERVICE_URL);
+ JMXConnector connector = JMXConnectorFactory.connect(serviceURL);
+
+ assertNotNull("Client Connector should not be null", connector);
+
+ // Get the MBean server connection.
+ MBeanServerConnection connection = connector.getMBeanServerConnection();
+ assertNotNull("MBeanServerConnection should not be null", connection);
+
+ // Test for MBean server equality.
+ assertEquals("Registered MBean count should be the same",
+ hostedServer.getMBeanCount(), connection.getMBeanCount());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/support/JmxUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/support/JmxUtilsTests.java
new file mode 100644
index 00000000000..0bc2bebdd01
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/support/JmxUtilsTests.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jmx.support;
+
+import java.beans.PropertyDescriptor;
+
+import javax.management.DynamicMBean;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+import javax.management.StandardMBean;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.BeanWrapperImpl;
+import org.springframework.core.JdkVersion;
+import org.springframework.jmx.IJmxTestBean;
+import org.springframework.jmx.JmxTestBean;
+import org.springframework.jmx.export.TestDynamicMBean;
+import org.springframework.util.ObjectUtils;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class JmxUtilsTests extends TestCase {
+
+ public void testIsMBeanWithDynamicMBean() throws Exception {
+ DynamicMBean mbean = new TestDynamicMBean();
+ assertTrue("Dynamic MBean not detected correctly", JmxUtils.isMBean(mbean.getClass()));
+ }
+
+ public void testIsMBeanWithStandardMBeanWrapper() throws Exception {
+ StandardMBean mbean = new StandardMBean(new JmxTestBean(), IJmxTestBean.class);
+ assertTrue("Standard MBean not detected correctly", JmxUtils.isMBean(mbean.getClass()));
+ }
+
+ public void testIsMBeanWithStandardMBeanInherited() throws Exception {
+ StandardMBean mbean = new StandardMBeanImpl();
+ assertTrue("Standard MBean not detected correctly", JmxUtils.isMBean(mbean.getClass()));
+ }
+
+ public void testNotAnMBean() throws Exception {
+ assertFalse("Object incorrectly identified as an MBean", JmxUtils.isMBean(Object.class));
+ }
+
+ public void testSimpleMBean() throws Exception {
+ Foo foo = new Foo();
+ assertTrue("Simple MBean not detected correctly", JmxUtils.isMBean(foo.getClass()));
+ }
+
+ public void testSimpleMXBean() throws Exception {
+ FooX foo = new FooX();
+ assertTrue("Simple MXBean not detected correctly", JmxUtils.isMBean(foo.getClass()));
+ }
+
+ public void testSimpleMBeanThroughInheritance() throws Exception {
+ Bar bar = new Bar();
+ Abc abc = new Abc();
+ assertTrue("Simple MBean (through inheritance) not detected correctly",
+ JmxUtils.isMBean(bar.getClass()));
+ assertTrue("Simple MBean (through 2 levels of inheritance) not detected correctly",
+ JmxUtils.isMBean(abc.getClass()));
+ }
+
+ public void testGetAttributeNameWithStrictCasing() {
+ PropertyDescriptor pd = new BeanWrapperImpl(AttributeTest.class).getPropertyDescriptor("name");
+ String attributeName = JmxUtils.getAttributeName(pd, true);
+ assertEquals("Incorrect casing on attribute name", "Name", attributeName);
+ }
+
+ public void testGetAttributeNameWithoutStrictCasing() {
+ PropertyDescriptor pd = new BeanWrapperImpl(AttributeTest.class).getPropertyDescriptor("name");
+ String attributeName = JmxUtils.getAttributeName(pd, false);
+ assertEquals("Incorrect casing on attribute name", "name", attributeName);
+ }
+
+ public void testAppendIdentityToObjectName() throws MalformedObjectNameException {
+ ObjectName objectName = ObjectNameManager.getInstance("spring:type=Test");
+ Object managedResource = new Object();
+ ObjectName uniqueName = JmxUtils.appendIdentityToObjectName(objectName, managedResource);
+
+ String typeProperty = "type";
+
+ assertEquals("Domain of transformed name is incorrect", objectName.getDomain(), uniqueName.getDomain());
+ assertEquals("Type key is incorrect", objectName.getKeyProperty(typeProperty), uniqueName.getKeyProperty("type"));
+ assertEquals("Identity key is incorrect", ObjectUtils.getIdentityHexString(managedResource), uniqueName.getKeyProperty(JmxUtils.IDENTITY_OBJECT_NAME_KEY));
+ }
+
+ public void testLocatePlatformMBeanServer() {
+ if(JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_15) {
+ return;
+ }
+
+ MBeanServer server = null;
+ try {
+ server = JmxUtils.locateMBeanServer();
+ }
+ finally {
+ if (server != null) {
+ MBeanServerFactory.releaseMBeanServer(server);
+ }
+ }
+ }
+
+ public void testIsMBean() {
+ // Correctly returns true for a class
+ assertTrue(JmxUtils.isMBean(JmxClassTest.class));
+
+ // Correctly returns false since JmxUtils won't navigate to the extended interface
+ assertFalse(JmxUtils.isMBean(SpecializedJmxInterfaceTest.class));
+
+ // Incorrectly returns true since it doesn't detect that this is an interface
+ assertFalse(JmxUtils.isMBean(JmxInterfaceTest.class));
+ }
+
+
+ public static class AttributeTest {
+
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+ }
+
+
+ public static class StandardMBeanImpl extends StandardMBean implements IJmxTestBean {
+
+ public StandardMBeanImpl() throws NotCompliantMBeanException {
+ super(IJmxTestBean.class);
+ }
+
+ public int add(int x, int y) {
+ return 0;
+ }
+
+ public long myOperation() {
+ return 0;
+ }
+
+ public int getAge() {
+ return 0;
+ }
+
+ public void setAge(int age) {
+ }
+
+ public void setName(String name) {
+ }
+
+ public String getName() {
+ return null;
+ }
+
+ public void dontExposeMe() {
+ }
+ }
+
+
+ public static interface FooMBean {
+
+ String getName();
+ }
+
+
+ public static class Foo implements FooMBean {
+
+ public String getName() {
+ return "Rob Harrop";
+ }
+ }
+
+
+ public static interface FooMXBean {
+
+ String getName();
+ }
+
+
+ public static class FooX implements FooMXBean {
+
+ public String getName() {
+ return "Rob Harrop";
+ }
+ }
+
+
+ public static class Bar extends Foo {
+
+ }
+
+
+ public static class Abc extends Bar {
+
+ }
+
+
+ private static interface JmxInterfaceTestMBean {
+
+ }
+
+
+ private static interface JmxInterfaceTest extends JmxInterfaceTestMBean {
+
+ }
+
+
+ private static interface SpecializedJmxInterfaceTest extends JmxInterfaceTest {
+
+ }
+
+
+ private static interface JmxClassTestMBean {
+
+ }
+
+
+ private static class JmxClassTest implements JmxClassTestMBean {
+
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/support/MBeanServerConnectionFactoryBeanTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/support/MBeanServerConnectionFactoryBeanTests.java
new file mode 100644
index 00000000000..5c0e2d917e9
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/support/MBeanServerConnectionFactoryBeanTests.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.jmx.support;
+
+import java.net.MalformedURLException;
+
+import javax.management.MBeanServerConnection;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+
+import org.springframework.aop.support.AopUtils;
+import org.springframework.jmx.AbstractMBeanServerTests;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class MBeanServerConnectionFactoryBeanTests extends AbstractMBeanServerTests {
+
+ private static final String SERVICE_URL = "service:jmx:jmxmp://localhost:9876";
+
+ private JMXServiceURL getServiceUrl() throws MalformedURLException {
+ return new JMXServiceURL(SERVICE_URL);
+ }
+
+ private JMXConnectorServer getConnectorServer() throws Exception {
+ return JMXConnectorServerFactory.newJMXConnectorServer(getServiceUrl(), null, getServer());
+ }
+
+ public void testValidConnection() throws Exception {
+ JMXConnectorServer connectorServer = getConnectorServer();
+ connectorServer.start();
+
+ try {
+ MBeanServerConnectionFactoryBean bean = new MBeanServerConnectionFactoryBean();
+ bean.setServiceUrl(SERVICE_URL);
+ bean.afterPropertiesSet();
+
+ try {
+ MBeanServerConnection connection = (MBeanServerConnection) bean.getObject();
+ assertNotNull("Connection should not be null", connection);
+
+ // perform simple MBean count test
+ assertEquals("MBean count should be the same", getServer().getMBeanCount(), connection.getMBeanCount());
+ }
+ finally {
+ bean.destroy();
+ }
+ }
+ finally {
+ connectorServer.stop();
+ }
+ }
+
+ public void testWithNoServiceUrl() throws Exception {
+ MBeanServerConnectionFactoryBean bean = new MBeanServerConnectionFactoryBean();
+ try {
+ bean.afterPropertiesSet();
+ fail("IllegalArgumentException should be raised when no service url is provided");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ public void testWithLazyConnection() throws Exception {
+ MBeanServerConnectionFactoryBean bean = new MBeanServerConnectionFactoryBean();
+ bean.setServiceUrl(SERVICE_URL);
+ bean.setConnectOnStartup(false);
+ bean.afterPropertiesSet();
+
+ MBeanServerConnection connection = (MBeanServerConnection) bean.getObject();
+ assertTrue(AopUtils.isAopProxy(connection));
+
+ JMXConnectorServer connector = null;
+ try {
+ connector = getConnectorServer();
+ connector.start();
+ assertEquals("Incorrect MBean count", getServer().getMBeanCount(), connection.getMBeanCount());
+ }
+ finally {
+ bean.destroy();
+ if (connector != null) {
+ connector.stop();
+ }
+ }
+ }
+
+ public void testWithLazyConnectionAndNoAccess() throws Exception {
+ MBeanServerConnectionFactoryBean bean = new MBeanServerConnectionFactoryBean();
+ bean.setServiceUrl(SERVICE_URL);
+ bean.setConnectOnStartup(false);
+ bean.afterPropertiesSet();
+
+ MBeanServerConnection connection = (MBeanServerConnection) bean.getObject();
+ assertTrue(AopUtils.isAopProxy(connection));
+ bean.destroy();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jmx/support/MBeanServerFactoryBeanTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jmx/support/MBeanServerFactoryBeanTests.java
new file mode 100644
index 00000000000..c12ecf5f8ec
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jmx/support/MBeanServerFactoryBeanTests.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jmx.support;
+
+import java.util.List;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rob Harrop
+ */
+public class MBeanServerFactoryBeanTests extends TestCase {
+
+ public void testGetObject() throws Exception {
+ MBeanServerFactoryBean bean = new MBeanServerFactoryBean();
+ bean.afterPropertiesSet();
+ try {
+ MBeanServer server = (MBeanServer) bean.getObject();
+ assertNotNull("The MBeanServer should not be null", server);
+ }
+ finally {
+ bean.destroy();
+ }
+ }
+
+ public void testDefaultDomain() throws Exception {
+ MBeanServerFactoryBean bean = new MBeanServerFactoryBean();
+ bean.setDefaultDomain("foo");
+ bean.afterPropertiesSet();
+ try {
+ MBeanServer server = (MBeanServer) bean.getObject();
+ assertEquals("The default domain should be foo", "foo", server.getDefaultDomain());
+ }
+ finally {
+ bean.destroy();
+ }
+ }
+
+ public void testWithLocateExistingAndExistingServer() {
+ MBeanServer server = MBeanServerFactory.createMBeanServer();
+ try {
+ MBeanServerFactoryBean bean = new MBeanServerFactoryBean();
+ bean.setLocateExistingServerIfPossible(true);
+ bean.afterPropertiesSet();
+ try {
+ MBeanServer otherServer = (MBeanServer) bean.getObject();
+ assertSame("Existing MBeanServer not located", server, otherServer);
+ }
+ finally {
+ bean.destroy();
+ }
+ }
+ finally {
+ MBeanServerFactory.releaseMBeanServer(server);
+ }
+ }
+
+ public void testWithLocateExistingAndNoExistingServer() {
+ MBeanServerFactoryBean bean = new MBeanServerFactoryBean();
+ bean.setLocateExistingServerIfPossible(true);
+ bean.afterPropertiesSet();
+ try {
+ assertNotNull("MBeanServer not created", bean.getObject());
+ }
+ finally {
+ bean.destroy();
+ }
+ }
+
+ public void testCreateMBeanServer() throws Exception {
+ testCreation(true, "The server should be available in the list");
+ }
+
+ public void testNewMBeanServer() throws Exception {
+ testCreation(false, "The server should not be available in the list");
+ }
+
+ private void testCreation(boolean referenceShouldExist, String failMsg) throws Exception {
+ MBeanServerFactoryBean bean = new MBeanServerFactoryBean();
+ bean.setRegisterWithFactory(referenceShouldExist);
+ bean.afterPropertiesSet();
+
+ try {
+ MBeanServer server = (MBeanServer) bean.getObject();
+ List servers = MBeanServerFactory.findMBeanServer(null);
+
+ boolean found = false;
+ for (int x = 0; x < servers.size(); x++) {
+ if (servers.get(x) == server) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!(found == referenceShouldExist)) {
+ fail(failMsg);
+ }
+ }
+ finally {
+ bean.destroy();
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jndi/JndiObjectFactoryBeanTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jndi/JndiObjectFactoryBeanTests.java
new file mode 100644
index 00000000000..a685cfae906
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jndi/JndiObjectFactoryBeanTests.java
@@ -0,0 +1,385 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jndi;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.beans.DerivedTestBean;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.mock.jndi.ExpectedLookupTemplate;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public class JndiObjectFactoryBeanTests extends TestCase {
+
+ public void testNoJndiName() throws NamingException {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ try {
+ jof.afterPropertiesSet();
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ }
+ }
+
+ public void testLookupWithFullNameAndResourceRefTrue() throws Exception {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ Object o = new Object();
+ jof.setJndiTemplate(new ExpectedLookupTemplate("java:comp/env/foo", o));
+ jof.setJndiName("java:comp/env/foo");
+ jof.setResourceRef(true);
+ jof.afterPropertiesSet();
+ assertTrue(jof.getObject() == o);
+ }
+
+ public void testLookupWithFullNameAndResourceRefFalse() throws Exception {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ Object o = new Object();
+ jof.setJndiTemplate(new ExpectedLookupTemplate("java:comp/env/foo", o));
+ jof.setJndiName("java:comp/env/foo");
+ jof.setResourceRef(false);
+ jof.afterPropertiesSet();
+ assertTrue(jof.getObject() == o);
+ }
+
+ public void testLookupWithSchemeNameAndResourceRefTrue() throws Exception {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ Object o = new Object();
+ jof.setJndiTemplate(new ExpectedLookupTemplate("java:foo", o));
+ jof.setJndiName("java:foo");
+ jof.setResourceRef(true);
+ jof.afterPropertiesSet();
+ assertTrue(jof.getObject() == o);
+ }
+
+ public void testLookupWithSchemeNameAndResourceRefFalse() throws Exception {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ Object o = new Object();
+ jof.setJndiTemplate(new ExpectedLookupTemplate("java:foo", o));
+ jof.setJndiName("java:foo");
+ jof.setResourceRef(false);
+ jof.afterPropertiesSet();
+ assertTrue(jof.getObject() == o);
+ }
+
+ public void testLookupWithShortNameAndResourceRefTrue() throws Exception {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ Object o = new Object();
+ jof.setJndiTemplate(new ExpectedLookupTemplate("java:comp/env/foo", o));
+ jof.setJndiName("foo");
+ jof.setResourceRef(true);
+ jof.afterPropertiesSet();
+ assertTrue(jof.getObject() == o);
+ }
+
+ public void testLookupWithShortNameAndResourceRefFalse() throws Exception {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ Object o = new Object();
+ jof.setJndiTemplate(new ExpectedLookupTemplate("java:comp/env/foo", o));
+ jof.setJndiName("foo");
+ jof.setResourceRef(false);
+ try {
+ jof.afterPropertiesSet();
+ fail("Should have thrown NamingException");
+ }
+ catch (NamingException ex) {
+ // expected
+ }
+ }
+
+ public void testLookupWithArbitraryNameAndResourceRefFalse() throws Exception {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ Object o = new Object();
+ jof.setJndiTemplate(new ExpectedLookupTemplate("foo", o));
+ jof.setJndiName("foo");
+ jof.setResourceRef(false);
+ jof.afterPropertiesSet();
+ assertTrue(jof.getObject() == o);
+ }
+
+ public void testLookupWithExpectedTypeAndMatch() throws Exception {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ String s = "";
+ jof.setJndiTemplate(new ExpectedLookupTemplate("foo", s));
+ jof.setJndiName("foo");
+ jof.setExpectedType(String.class);
+ jof.afterPropertiesSet();
+ assertTrue(jof.getObject() == s);
+ }
+
+ public void testLookupWithExpectedTypeAndNoMatch() throws Exception {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ Object o = new Object();
+ jof.setJndiTemplate(new ExpectedLookupTemplate("foo", o));
+ jof.setJndiName("foo");
+ jof.setExpectedType(String.class);
+ try {
+ jof.afterPropertiesSet();
+ fail("Should have thrown NamingException");
+ }
+ catch (NamingException ex) {
+ assertTrue(ex.getMessage().indexOf("java.lang.String") != -1);
+ }
+ }
+
+ public void testLookupWithDefaultObject() throws Exception {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ String s = "";
+ jof.setJndiTemplate(new ExpectedLookupTemplate("foo", s));
+ jof.setJndiName("myFoo");
+ jof.setExpectedType(String.class);
+ jof.setDefaultObject("myString");
+ jof.afterPropertiesSet();
+ assertEquals("myString", jof.getObject());
+ }
+
+ public void testLookupWithDefaultObjectAndExpectedType() throws Exception {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ String s = "";
+ jof.setJndiTemplate(new ExpectedLookupTemplate("foo", s));
+ jof.setJndiName("myFoo");
+ jof.setExpectedType(String.class);
+ jof.setDefaultObject("myString");
+ jof.afterPropertiesSet();
+ assertEquals("myString", jof.getObject());
+ }
+
+ public void testLookupWithDefaultObjectAndExpectedTypeNoMatch() throws Exception {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ String s = "";
+ jof.setJndiTemplate(new ExpectedLookupTemplate("foo", s));
+ jof.setJndiName("myFoo");
+ jof.setExpectedType(String.class);
+ jof.setDefaultObject(Boolean.TRUE);
+ try {
+ jof.afterPropertiesSet();
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ public void testLookupWithProxyInterface() throws Exception {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ TestBean tb = new TestBean();
+ jof.setJndiTemplate(new ExpectedLookupTemplate("foo", tb));
+ jof.setJndiName("foo");
+ jof.setProxyInterface(ITestBean.class);
+ jof.afterPropertiesSet();
+ assertTrue(jof.getObject() instanceof ITestBean);
+ ITestBean proxy = (ITestBean) jof.getObject();
+ assertEquals(0, tb.getAge());
+ proxy.setAge(99);
+ assertEquals(99, tb.getAge());
+ }
+
+ public void testLookupWithProxyInterfaceAndDefaultObject() throws Exception {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ TestBean tb = new TestBean();
+ jof.setJndiTemplate(new ExpectedLookupTemplate("foo", tb));
+ jof.setJndiName("myFoo");
+ jof.setProxyInterface(ITestBean.class);
+ jof.setDefaultObject(Boolean.TRUE);
+ try {
+ jof.afterPropertiesSet();
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ public void testLookupWithProxyInterfaceAndLazyLookup() throws Exception {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ final TestBean tb = new TestBean();
+ jof.setJndiTemplate(new JndiTemplate() {
+ public Object lookup(String name) {
+ if ("foo".equals(name)) {
+ tb.setName("tb");
+ return tb;
+ }
+ return null;
+ }
+ });
+ jof.setJndiName("foo");
+ jof.setProxyInterface(ITestBean.class);
+ jof.setLookupOnStartup(false);
+ jof.afterPropertiesSet();
+ assertTrue(jof.getObject() instanceof ITestBean);
+ ITestBean proxy = (ITestBean) jof.getObject();
+ assertNull(tb.getName());
+ assertEquals(0, tb.getAge());
+ proxy.setAge(99);
+ assertEquals("tb", tb.getName());
+ assertEquals(99, tb.getAge());
+ }
+
+ public void testLookupWithProxyInterfaceWithNotCache() throws Exception {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ final TestBean tb = new TestBean();
+ jof.setJndiTemplate(new JndiTemplate() {
+ public Object lookup(String name) {
+ if ("foo".equals(name)) {
+ tb.setName("tb");
+ tb.setAge(tb.getAge() + 1);
+ return tb;
+ }
+ return null;
+ }
+ });
+ jof.setJndiName("foo");
+ jof.setProxyInterface(ITestBean.class);
+ jof.setCache(false);
+ jof.afterPropertiesSet();
+ assertTrue(jof.getObject() instanceof ITestBean);
+ ITestBean proxy = (ITestBean) jof.getObject();
+ assertEquals("tb", tb.getName());
+ assertEquals(1, tb.getAge());
+ proxy.returnsThis();
+ assertEquals(2, tb.getAge());
+ proxy.haveBirthday();
+ assertEquals(4, tb.getAge());
+ }
+
+ public void testLookupWithProxyInterfaceWithLazyLookupAndNotCache() throws Exception {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ final TestBean tb = new TestBean();
+ jof.setJndiTemplate(new JndiTemplate() {
+ public Object lookup(String name) {
+ if ("foo".equals(name)) {
+ tb.setName("tb");
+ tb.setAge(tb.getAge() + 1);
+ return tb;
+ }
+ return null;
+ }
+ });
+ jof.setJndiName("foo");
+ jof.setProxyInterface(ITestBean.class);
+ jof.setLookupOnStartup(false);
+ jof.setCache(false);
+ jof.afterPropertiesSet();
+ assertTrue(jof.getObject() instanceof ITestBean);
+ ITestBean proxy = (ITestBean) jof.getObject();
+ assertNull(tb.getName());
+ assertEquals(0, tb.getAge());
+ proxy.returnsThis();
+ assertEquals("tb", tb.getName());
+ assertEquals(1, tb.getAge());
+ proxy.returnsThis();
+ assertEquals(2, tb.getAge());
+ proxy.haveBirthday();
+ assertEquals(4, tb.getAge());
+ }
+
+ public void testLazyLookupWithoutProxyInterface() throws NamingException {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ jof.setJndiName("foo");
+ jof.setLookupOnStartup(false);
+ try {
+ jof.afterPropertiesSet();
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ public void testNotCacheWithoutProxyInterface() throws NamingException {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ jof.setJndiName("foo");
+ jof.setCache(false);
+ jof.setLookupOnStartup(false);
+ try {
+ jof.afterPropertiesSet();
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ public void testLookupWithProxyInterfaceAndExpectedTypeAndMatch() throws Exception {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ TestBean tb = new TestBean();
+ jof.setJndiTemplate(new ExpectedLookupTemplate("foo", tb));
+ jof.setJndiName("foo");
+ jof.setExpectedType(TestBean.class);
+ jof.setProxyInterface(ITestBean.class);
+ jof.afterPropertiesSet();
+ assertTrue(jof.getObject() instanceof ITestBean);
+ ITestBean proxy = (ITestBean) jof.getObject();
+ assertEquals(0, tb.getAge());
+ proxy.setAge(99);
+ assertEquals(99, tb.getAge());
+ }
+
+ public void testLookupWithProxyInterfaceAndExpectedTypeAndNoMatch() throws Exception {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ TestBean tb = new TestBean();
+ jof.setJndiTemplate(new ExpectedLookupTemplate("foo", tb));
+ jof.setJndiName("foo");
+ jof.setExpectedType(DerivedTestBean.class);
+ jof.setProxyInterface(ITestBean.class);
+ try {
+ jof.afterPropertiesSet();
+ fail("Should have thrown NamingException");
+ }
+ catch (NamingException ex) {
+ assertTrue(ex.getMessage().indexOf("org.springframework.beans.DerivedTestBean") != -1);
+ }
+ }
+
+ public void testLookupWithExposeAccessContext() throws Exception {
+ JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
+ TestBean tb = new TestBean();
+ MockControl ctxControl = MockControl.createControl(Context.class);
+ final Context mockCtx = (Context) ctxControl.getMock();
+ mockCtx.lookup("foo");
+ ctxControl.setReturnValue(tb);
+ mockCtx.close();
+ ctxControl.setVoidCallable(2);
+ ctxControl.replay();
+ jof.setJndiTemplate(new JndiTemplate() {
+ protected Context createInitialContext() {
+ return mockCtx;
+ }
+ });
+ jof.setJndiName("foo");
+ jof.setProxyInterface(ITestBean.class);
+ jof.setExposeAccessContext(true);
+ jof.afterPropertiesSet();
+ assertTrue(jof.getObject() instanceof ITestBean);
+ ITestBean proxy = (ITestBean) jof.getObject();
+ assertEquals(0, tb.getAge());
+ proxy.setAge(99);
+ assertEquals(99, tb.getAge());
+ proxy.equals(proxy);
+ proxy.hashCode();
+ proxy.toString();
+ ctxControl.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jndi/JndiTemplateEditorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jndi/JndiTemplateEditorTests.java
new file mode 100644
index 00000000000..eb4b239cc87
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jndi/JndiTemplateEditorTests.java
@@ -0,0 +1,56 @@
+
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.jndi;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rod Johnson
+ */
+public class JndiTemplateEditorTests extends TestCase {
+
+ public void testNullIsIllegalArgument() {
+ try {
+ new JndiTemplateEditor().setAsText(null);
+ fail("Null is illegal");
+ }
+ catch (IllegalArgumentException ex) {
+ // OK
+ }
+ }
+
+ public void testEmptyStringMeansNullEnvironment() {
+ JndiTemplateEditor je = new JndiTemplateEditor();
+ je.setAsText("");
+ JndiTemplate jt = (JndiTemplate) je.getValue();
+ assertTrue(jt.getEnvironment() == null);
+ }
+
+ public void testCustomEnvironment() {
+ JndiTemplateEditor je = new JndiTemplateEditor();
+ // These properties are meaningless for JNDI, but we don't worry about that:
+ // the underlying JNDI implementation will throw exceptions when the user tries
+ // to look anything up
+ je.setAsText("jndiInitialSomethingOrOther=org.springframework.myjndi.CompleteRubbish\nfoo=bar");
+ JndiTemplate jt = (JndiTemplate) je.getValue();
+ assertTrue(jt.getEnvironment().size() == 2);
+ assertTrue(jt.getEnvironment().getProperty("jndiInitialSomethingOrOther").equals("org.springframework.myjndi.CompleteRubbish"));
+ assertTrue(jt.getEnvironment().getProperty("foo").equals("bar"));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jndi/JndiTemplateTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jndi/JndiTemplateTests.java
new file mode 100644
index 00000000000..6b8fda62af5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jndi/JndiTemplateTests.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.jndi;
+
+import javax.naming.Context;
+import javax.naming.NameNotFoundException;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @since 08.07.2003
+ */
+public class JndiTemplateTests extends TestCase {
+
+ public void testLookupSucceeds() throws Exception {
+ Object o = new Object();
+ String name = "foo";
+ MockControl mc = MockControl.createControl(Context.class);
+ final Context mock = (Context) mc.getMock();
+ mock.lookup(name);
+ mc.setReturnValue(o);
+ mock.close();
+ mc.setVoidCallable(1);
+ mc.replay();
+
+ JndiTemplate jt = new JndiTemplate() {
+ protected Context createInitialContext() {
+ return mock;
+ }
+ };
+
+ Object o2 = jt.lookup(name);
+ assertEquals(o, o2);
+ mc.verify();
+ }
+
+ public void testLookupFails() throws Exception {
+ NameNotFoundException ne = new NameNotFoundException();
+ String name = "foo";
+ MockControl mc = MockControl.createControl(Context.class);
+ final Context mock = (Context) mc.getMock();
+ mock.lookup(name);
+ mc.setThrowable(ne);
+ mock.close();
+ mc.setVoidCallable(1);
+ mc.replay();
+
+ JndiTemplate jt = new JndiTemplate() {
+ protected Context createInitialContext() {
+ return mock;
+ }
+ };
+
+ try {
+ jt.lookup(name);
+ fail("Should have thrown NamingException");
+ }
+ catch (NameNotFoundException ex) {
+ // Ok
+ }
+ mc.verify();
+ }
+
+ public void testLookupReturnsNull() throws Exception {
+ String name = "foo";
+ MockControl mc = MockControl.createControl(Context.class);
+ final Context mock = (Context) mc.getMock();
+ mock.lookup(name);
+ mc.setReturnValue(null);
+ mock.close();
+ mc.setVoidCallable(1);
+ mc.replay();
+
+ JndiTemplate jt = new JndiTemplate() {
+ protected Context createInitialContext() {
+ return mock;
+ }
+ };
+
+ try {
+ jt.lookup(name);
+ fail("Should have thrown NamingException");
+ }
+ catch (NameNotFoundException ex) {
+ // Ok
+ }
+ mc.verify();
+ }
+
+ public void testLookupFailsWithTypeMismatch() throws Exception {
+ Object o = new Object();
+ String name = "foo";
+ MockControl mc = MockControl.createControl(Context.class);
+ final Context mock = (Context) mc.getMock();
+ mock.lookup(name);
+ mc.setReturnValue(o);
+ mock.close();
+ mc.setVoidCallable(1);
+ mc.replay();
+
+ JndiTemplate jt = new JndiTemplate() {
+ protected Context createInitialContext() {
+ return mock;
+ }
+ };
+
+ try {
+ jt.lookup(name, String.class);
+ fail("Should have thrown TypeMismatchNamingException");
+ }
+ catch (TypeMismatchNamingException ex) {
+ // Ok
+ }
+ mc.verify();
+ }
+
+ public void testBind() throws Exception {
+ Object o = new Object();
+ String name = "foo";
+ MockControl mc = MockControl.createControl(Context.class);
+ final Context mock = (Context) mc.getMock();
+ mock.bind(name, o);
+ mc.setVoidCallable(1);
+ mock.close();
+ mc.setVoidCallable(1);
+ mc.replay();
+
+ JndiTemplate jt = new JndiTemplate() {
+ protected Context createInitialContext() {
+ return mock;
+ }
+ };
+
+ jt.bind(name, o);
+ mc.verify();
+ }
+
+ public void testRebind() throws Exception {
+ Object o = new Object();
+ String name = "foo";
+ MockControl mc = MockControl.createControl(Context.class);
+ final Context mock = (Context) mc.getMock();
+ mock.rebind(name, o);
+ mc.setVoidCallable(1);
+ mock.close();
+ mc.setVoidCallable(1);
+ mc.replay();
+
+ JndiTemplate jt = new JndiTemplate() {
+ protected Context createInitialContext() {
+ return mock;
+ }
+ };
+
+ jt.rebind(name, o);
+ mc.verify();
+ }
+
+ public void testUnbind() throws Exception {
+ String name = "something";
+ MockControl mc = MockControl.createControl(Context.class);
+ final Context mock = (Context) mc.getMock();
+ mock.unbind(name);
+ mc.setVoidCallable(1);
+ mock.close();
+ mc.setVoidCallable(1);
+ mc.replay();
+
+ JndiTemplate jt = new JndiTemplate() {
+ protected Context createInitialContext() {
+ return mock;
+ }
+ };
+
+ jt.unbind(name);
+ mc.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/jndi/SimpleNamingContextTests.java b/org.springframework.testsuite/src/test/java/org/springframework/jndi/SimpleNamingContextTests.java
new file mode 100644
index 00000000000..d2be1268f97
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/jndi/SimpleNamingContextTests.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.jndi;
+
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import javax.naming.Binding;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NameClassPair;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.spi.InitialContextFactory;
+import javax.sql.DataSource;
+
+import junit.framework.TestCase;
+
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+import org.springframework.mock.jndi.SimpleNamingContext;
+import org.springframework.mock.jndi.SimpleNamingContextBuilder;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class SimpleNamingContextTests extends TestCase {
+
+ public void testNamingContextBuilder() throws NamingException {
+ SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
+ InitialContextFactory factory = builder.createInitialContextFactory(null);
+
+ DataSource ds = new DriverManagerDataSource();
+ builder.bind("java:comp/env/jdbc/myds", ds);
+ Object obj = new Object();
+ builder.bind("myobject", obj);
+
+ Context context1 = factory.getInitialContext(null);
+ assertTrue("Correct DataSource registered", context1.lookup("java:comp/env/jdbc/myds") == ds);
+ assertTrue("Correct Object registered", context1.lookup("myobject") == obj);
+
+ Hashtable env2 = new Hashtable();
+ env2.put("key1", "value1");
+ Context context2 = factory.getInitialContext(env2);
+ assertTrue("Correct DataSource registered", context2.lookup("java:comp/env/jdbc/myds") == ds);
+ assertTrue("Correct Object registered", context2.lookup("myobject") == obj);
+ assertTrue("Correct environment", context2.getEnvironment() != env2);
+ assertTrue("Correct key1", "value1".equals(context2.getEnvironment().get("key1")));
+
+ Integer i = new Integer(0);
+ context1.rebind("myinteger", i);
+ String s = "";
+ context2.bind("mystring", s);
+
+ Context context3 = (Context) context2.lookup("");
+ context3.rename("java:comp/env/jdbc/myds", "jdbc/myds");
+ context3.unbind("myobject");
+
+ assertTrue("Correct environment", context3.getEnvironment() != context2.getEnvironment());
+ context3.addToEnvironment("key2", "value2");
+ assertTrue("key2 added", "value2".equals(context3.getEnvironment().get("key2")));
+ context3.removeFromEnvironment("key1");
+ assertTrue("key1 removed", context3.getEnvironment().get("key1") == null);
+
+ assertTrue("Correct DataSource registered", context1.lookup("jdbc/myds") == ds);
+ try {
+ context1.lookup("myobject");
+ fail("Should have thrown NameNotFoundException");
+ }
+ catch (NameNotFoundException ex) {
+ // expected
+ }
+ assertTrue("Correct Integer registered", context1.lookup("myinteger") == i);
+ assertTrue("Correct String registered", context1.lookup("mystring") == s);
+
+ assertTrue("Correct DataSource registered", context2.lookup("jdbc/myds") == ds);
+ try {
+ context2.lookup("myobject");
+ fail("Should have thrown NameNotFoundException");
+ }
+ catch (NameNotFoundException ex) {
+ // expected
+ }
+ assertTrue("Correct Integer registered", context2.lookup("myinteger") == i);
+ assertTrue("Correct String registered", context2.lookup("mystring") == s);
+
+ assertTrue("Correct DataSource registered", context3.lookup("jdbc/myds") == ds);
+ try {
+ context3.lookup("myobject");
+ fail("Should have thrown NameNotFoundException");
+ }
+ catch (NameNotFoundException ex) {
+ // expected
+ }
+ assertTrue("Correct Integer registered", context3.lookup("myinteger") == i);
+ assertTrue("Correct String registered", context3.lookup("mystring") == s);
+
+ Map bindingMap = new HashMap();
+ NamingEnumeration bindingEnum = context3.listBindings("");
+ while (bindingEnum.hasMoreElements()) {
+ Binding binding = (Binding) bindingEnum.nextElement();
+ bindingMap.put(binding.getName(), binding);
+ }
+ assertTrue("Correct jdbc subcontext", ((Binding) bindingMap.get("jdbc")).getObject() instanceof Context);
+ assertTrue("Correct jdbc subcontext", SimpleNamingContext.class.getName().equals(((Binding) bindingMap.get("jdbc")).getClassName()));
+
+ Context jdbcContext = (Context) context3.lookup("jdbc");
+ jdbcContext.bind("mydsX", ds);
+ Map subBindingMap = new HashMap();
+ NamingEnumeration subBindingEnum = jdbcContext.listBindings("");
+ while (subBindingEnum.hasMoreElements()) {
+ Binding binding = (Binding) subBindingEnum.nextElement();
+ subBindingMap.put(binding.getName(), binding);
+ }
+
+ assertTrue("Correct DataSource registered", ds.equals(((Binding) subBindingMap.get("myds")).getObject()));
+ assertTrue("Correct DataSource registered", DriverManagerDataSource.class.getName().equals(((Binding) subBindingMap.get("myds")).getClassName()));
+ assertTrue("Correct DataSource registered", ds.equals(((Binding) subBindingMap.get("mydsX")).getObject()));
+ assertTrue("Correct DataSource registered", DriverManagerDataSource.class.getName().equals(((Binding) subBindingMap.get("mydsX")).getClassName()));
+ assertTrue("Correct Integer registered", i.equals(((Binding) bindingMap.get("myinteger")).getObject()));
+ assertTrue("Correct Integer registered", Integer.class.getName().equals(((Binding) bindingMap.get("myinteger")).getClassName()));
+ assertTrue("Correct String registered", s.equals(((Binding) bindingMap.get("mystring")).getObject()));
+ assertTrue("Correct String registered", String.class.getName().equals(((Binding) bindingMap.get("mystring")).getClassName()));
+
+ context1.createSubcontext("jdbc").bind("sub/subds", ds);
+
+ Map pairMap = new HashMap();
+ NamingEnumeration pairEnum = context2.list("jdbc");
+ while (pairEnum.hasMore()) {
+ NameClassPair pair = (NameClassPair) pairEnum.next();
+ pairMap.put(pair.getName(), pair.getClassName());
+ }
+ assertTrue("Correct sub subcontext", SimpleNamingContext.class.getName().equals(pairMap.get("sub")));
+
+ Context subContext = (Context) context2.lookup("jdbc/sub");
+ Map subPairMap = new HashMap();
+ NamingEnumeration subPairEnum = subContext.list("");
+ while (subPairEnum.hasMoreElements()) {
+ NameClassPair pair = (NameClassPair) subPairEnum.next();
+ subPairMap.put(pair.getName(), pair.getClassName());
+ }
+
+ assertTrue("Correct DataSource registered", DriverManagerDataSource.class.getName().equals(subPairMap.get("subds")));
+ assertTrue("Correct DataSource registered", DriverManagerDataSource.class.getName().equals(pairMap.get("myds")));
+ assertTrue("Correct DataSource registered", DriverManagerDataSource.class.getName().equals(pairMap.get("mydsX")));
+
+ pairMap.clear();
+ pairEnum = context1.list("jdbc/");
+ while (pairEnum.hasMore()) {
+ NameClassPair pair = (NameClassPair) pairEnum.next();
+ pairMap.put(pair.getName(), pair.getClassName());
+ }
+ assertTrue("Correct DataSource registered", DriverManagerDataSource.class.getName().equals(pairMap.get("myds")));
+ assertTrue("Correct DataSource registered", DriverManagerDataSource.class.getName().equals(pairMap.get("mydsX")));
+ }
+
+ /**
+ * Demonstrates how emptyActivatedContextBuilder() method can be
+ * used repeatedly, and how it affects creating a new InitialContext()
+ */
+ public void testCreateInitialContext() throws Exception {
+ SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
+ String name = "foo";
+ Object o = new Object();
+ builder.bind(name, o);
+ // Check it affects JNDI
+ Context ctx = new InitialContext();
+ assertTrue(ctx.lookup(name) == o);
+ // Check it returns mutable contexts
+ ctx.unbind(name);
+ try {
+ ctx = new InitialContext();
+ ctx.lookup(name);
+ fail("Should have thrown NamingException");
+ }
+ catch (NamingException ex) {
+ // expected
+ }
+
+ // Check the same call will work again, but the context is empty
+ builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
+ try {
+ ctx = new InitialContext();
+ ctx.lookup(name);
+ fail("Should have thrown NamingException");
+ }
+ catch (NamingException ex) {
+ // expected
+ }
+ Object o2 = new Object();
+ builder.bind(name, o2);
+ assertEquals(ctx.lookup(name), o2);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/mail/SimpleMailMessageTests.java b/org.springframework.testsuite/src/test/java/org/springframework/mail/SimpleMailMessageTests.java
new file mode 100644
index 00000000000..30b6d02710a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/mail/SimpleMailMessageTests.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.mail;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Dmitriy Kopylenko
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ * @since 10.09.2003
+ */
+public final class SimpleMailMessageTests extends TestCase {
+
+ public void testSimpleMessageCopyCtor() {
+ SimpleMailMessage message = new SimpleMailMessage();
+ message.setFrom("me@mail.org");
+ message.setTo("you@mail.org");
+
+ SimpleMailMessage messageCopy = new SimpleMailMessage(message);
+ assertEquals("me@mail.org", messageCopy.getFrom());
+ assertEquals("you@mail.org", messageCopy.getTo()[0]);
+
+ message.setReplyTo("reply@mail.org");
+ message.setCc(new String[]{"he@mail.org", "she@mail.org"});
+ message.setBcc(new String[]{"us@mail.org", "them@mail.org"});
+ Date sentDate = new Date();
+ message.setSentDate(sentDate);
+ message.setSubject("my subject");
+ message.setText("my text");
+
+ assertEquals("me@mail.org", message.getFrom());
+ assertEquals("reply@mail.org", message.getReplyTo());
+ assertEquals("you@mail.org", message.getTo()[0]);
+ List ccs = Arrays.asList(message.getCc());
+ assertTrue(ccs.contains("he@mail.org"));
+ assertTrue(ccs.contains("she@mail.org"));
+ List bccs = Arrays.asList(message.getBcc());
+ assertTrue(bccs.contains("us@mail.org"));
+ assertTrue(bccs.contains("them@mail.org"));
+ assertEquals(sentDate, message.getSentDate());
+ assertEquals("my subject", message.getSubject());
+ assertEquals("my text", message.getText());
+
+ messageCopy = new SimpleMailMessage(message);
+ assertEquals("me@mail.org", messageCopy.getFrom());
+ assertEquals("reply@mail.org", messageCopy.getReplyTo());
+ assertEquals("you@mail.org", messageCopy.getTo()[0]);
+ ccs = Arrays.asList(messageCopy.getCc());
+ assertTrue(ccs.contains("he@mail.org"));
+ assertTrue(ccs.contains("she@mail.org"));
+ bccs = Arrays.asList(message.getBcc());
+ assertTrue(bccs.contains("us@mail.org"));
+ assertTrue(bccs.contains("them@mail.org"));
+ assertEquals(sentDate, messageCopy.getSentDate());
+ assertEquals("my subject", messageCopy.getSubject());
+ assertEquals("my text", messageCopy.getText());
+ }
+
+ public void testDeepCopyOfStringArrayTypedFieldsOnCopyCtor() throws Exception {
+
+ SimpleMailMessage original = new SimpleMailMessage();
+ original.setTo(new String[]{"fiona@mail.org", "apple@mail.org"});
+ original.setCc(new String[]{"he@mail.org", "she@mail.org"});
+ original.setBcc(new String[]{"us@mail.org", "them@mail.org"});
+
+ SimpleMailMessage copy = new SimpleMailMessage(original);
+
+ original.getTo()[0] = "mmm@mmm.org";
+ original.getCc()[0] = "mmm@mmm.org";
+ original.getBcc()[0] = "mmm@mmm.org";
+
+ assertEquals("fiona@mail.org", copy.getTo()[0]);
+ assertEquals("he@mail.org", copy.getCc()[0]);
+ assertEquals("us@mail.org", copy.getBcc()[0]);
+ }
+
+ /**
+ * Tests that two equal SimpleMailMessages have equal hash codes.
+ */
+ public final void testHashCode() {
+ SimpleMailMessage message1 = new SimpleMailMessage();
+ message1.setFrom("from@somewhere");
+ message1.setReplyTo("replyTo@somewhere");
+ message1.setTo("to@somewhere");
+ message1.setCc("cc@somewhere");
+ message1.setBcc("bcc@somewhere");
+ message1.setSentDate(new Date());
+ message1.setSubject("subject");
+ message1.setText("text");
+
+ // Copy the message
+ SimpleMailMessage message2 = new SimpleMailMessage(message1);
+
+ assertEquals(message1, message2);
+ assertEquals(message1.hashCode(), message2.hashCode());
+ }
+
+ public final void testEqualsObject() {
+ SimpleMailMessage message1;
+ SimpleMailMessage message2;
+
+ // Same object is equal
+ message1 = new SimpleMailMessage();
+ message2 = message1;
+ assertTrue(message1.equals(message2));
+
+ // Null object is not equal
+ message1 = new SimpleMailMessage();
+ message2 = null;
+ assertTrue(!(message1.equals(message2)));
+
+ // Different class is not equal
+ assertTrue(!(message1.equals(new Object())));
+
+ // Equal values are equal
+ message1 = new SimpleMailMessage();
+ message2 = new SimpleMailMessage();
+ assertTrue(message1.equals(message2));
+
+ message1 = new SimpleMailMessage();
+ message1.setFrom("from@somewhere");
+ message1.setReplyTo("replyTo@somewhere");
+ message1.setTo("to@somewhere");
+ message1.setCc("cc@somewhere");
+ message1.setBcc("bcc@somewhere");
+ message1.setSentDate(new Date());
+ message1.setSubject("subject");
+ message1.setText("text");
+ message2 = new SimpleMailMessage(message1);
+ assertTrue(message1.equals(message2));
+ }
+
+ public void testCopyCtorChokesOnNullOriginalMessage() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new SimpleMailMessage(null);
+ }
+ }.runTest();
+ }
+
+ public void testCopyToChokesOnNullTargetMessage() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new SimpleMailMessage().copyTo(null);
+ }
+ }.runTest();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/mail/javamail/ConfigurableMimeFileTypeMapTests.java b/org.springframework.testsuite/src/test/java/org/springframework/mail/javamail/ConfigurableMimeFileTypeMapTests.java
new file mode 100644
index 00000000000..4c5e108bea1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/mail/javamail/ConfigurableMimeFileTypeMapTests.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.mail.javamail;
+
+import java.io.File;
+
+import junit.framework.TestCase;
+
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class ConfigurableMimeFileTypeMapTests extends TestCase {
+
+ public void testAgainstDefaultConfiguration() throws Exception {
+ ConfigurableMimeFileTypeMap ftm = new ConfigurableMimeFileTypeMap();
+ ftm.afterPropertiesSet();
+
+ assertEquals("Invalid content type for HTM", "text/html", ftm.getContentType("foobar.HTM"));
+ assertEquals("Invalid content type for html", "text/html", ftm.getContentType("foobar.html"));
+ assertEquals("Invalid content type for c++", "text/plain", ftm.getContentType("foobar.c++"));
+ assertEquals("Invalid content type for svf", "image/vnd.svf", ftm.getContentType("foobar.svf"));
+ assertEquals("Invalid content type for dsf", "image/x-mgx-dsf", ftm.getContentType("foobar.dsf"));
+ assertEquals("Invalid default content type", "application/octet-stream", ftm.getContentType("foobar.foo"));
+ }
+
+ public void testAgainstDefaultConfigurationWithFilePath() throws Exception {
+ ConfigurableMimeFileTypeMap ftm = new ConfigurableMimeFileTypeMap();
+ assertEquals("Invalid content type for HTM", "text/html", ftm.getContentType(new File("/tmp/foobar.HTM")));
+ }
+
+ public void testWithAdditionalMappings() throws Exception {
+ ConfigurableMimeFileTypeMap ftm = new ConfigurableMimeFileTypeMap();
+ ftm.setMappings(new String[] {"foo/bar HTM foo", "foo/cpp c++"});
+ ftm.afterPropertiesSet();
+
+ assertEquals("Invalid content type for HTM - override didn't work", "foo/bar", ftm.getContentType("foobar.HTM"));
+ assertEquals("Invalid content type for c++ - override didn't work", "foo/cpp", ftm.getContentType("foobar.c++"));
+ assertEquals("Invalid content type for foo - new mapping didn't work", "foo/bar", ftm.getContentType("bar.foo"));
+ }
+
+ public void testWithCustomMappingLocation() throws Exception {
+ Resource resource = new ClassPathResource("test.mime.types", getClass());
+
+ ConfigurableMimeFileTypeMap ftm = new ConfigurableMimeFileTypeMap();
+ ftm.setMappingLocation(resource);
+ ftm.afterPropertiesSet();
+
+ assertEquals("Invalid content type for foo", "text/foo", ftm.getContentType("foobar.foo"));
+ assertEquals("Invalid content type for bar", "text/bar", ftm.getContentType("foobar.bar"));
+ assertEquals("Invalid content type for fimg", "image/foo", ftm.getContentType("foobar.fimg"));
+ assertEquals("Invalid content type for bimg", "image/bar", ftm.getContentType("foobar.bimg"));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/mail/javamail/InternetAddressEditorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/mail/javamail/InternetAddressEditorTests.java
new file mode 100644
index 00000000000..3233099baca
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/mail/javamail/InternetAddressEditorTests.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.mail.javamail;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Brian Hanafee
+ * @since 09.07.2005
+ */
+public class InternetAddressEditorTests extends TestCase {
+
+ private static final String EMPTY = "";
+ private static final String SIMPLE = "nobody@nowhere.com";
+ private static final String BAD = "(";
+
+ private InternetAddressEditor editor;
+
+ protected void setUp() {
+ editor = new InternetAddressEditor();
+ }
+
+ public void testUninitialized() {
+ assertEquals("Uninitialized editor did not return empty value string", EMPTY, editor.getAsText());
+ }
+
+ public void testSetNull() {
+ editor.setAsText(null);
+ assertEquals("Setting null did not result in empty value string", EMPTY, editor.getAsText());
+ }
+
+ public void testSetEmpty() {
+ editor.setAsText(EMPTY);
+ assertEquals("Setting empty string did not result in empty value string", EMPTY, editor.getAsText());
+ }
+
+ public void testAllWhitespace() {
+ editor.setAsText(" ");
+ assertEquals("All whitespace was not recognized", EMPTY, editor.getAsText());
+ }
+
+ public void testSimpleGoodAddess() {
+ editor.setAsText(SIMPLE);
+ assertEquals("Simple email address failed", SIMPLE, editor.getAsText());
+ }
+
+ public void testExcessWhitespace() {
+ editor.setAsText(" " + SIMPLE + " ");
+ assertEquals("Whitespace was not stripped", SIMPLE, editor.getAsText());
+ }
+
+ public void testSimpleBadAddress() {
+ try {
+ editor.setAsText(BAD);
+ fail("Should have failed on \"" + BAD + "\", instead got " + editor.getAsText());
+ }
+ catch (IllegalArgumentException e) {
+ // Passed the test
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/mail/javamail/JavaMailSenderTests.java b/org.springframework.testsuite/src/test/java/org/springframework/mail/javamail/JavaMailSenderTests.java
new file mode 100644
index 00000000000..befbe54e56c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/mail/javamail/JavaMailSenderTests.java
@@ -0,0 +1,536 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.mail.javamail;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Properties;
+
+import javax.activation.FileTypeMap;
+import javax.mail.Address;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.NoSuchProviderException;
+import javax.mail.Session;
+import javax.mail.Transport;
+import javax.mail.URLName;
+import javax.mail.internet.AddressException;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeMessage;
+
+import junit.framework.TestCase;
+
+import org.springframework.mail.MailParseException;
+import org.springframework.mail.MailSendException;
+import org.springframework.mail.SimpleMailMessage;
+
+/**
+ * @author Juergen Hoeller
+ * @since 09.10.2004
+ */
+public class JavaMailSenderTests extends TestCase {
+
+ public void testJavaMailSenderWithSimpleMessage() throws MessagingException, IOException {
+ MockJavaMailSender sender = new MockJavaMailSender();
+ sender.setHost("host");
+ sender.setPort(30);
+ sender.setUsername("username");
+ sender.setPassword("password");
+
+ SimpleMailMessage simpleMessage = new SimpleMailMessage();
+ simpleMessage.setFrom("me@mail.org");
+ simpleMessage.setReplyTo("reply@mail.org");
+ simpleMessage.setTo("you@mail.org");
+ simpleMessage.setCc(new String[] {"he@mail.org", "she@mail.org"});
+ simpleMessage.setBcc(new String[] {"us@mail.org", "them@mail.org"});
+ Date sentDate = new Date(2004, 1, 1);
+ simpleMessage.setSentDate(sentDate);
+ simpleMessage.setSubject("my subject");
+ simpleMessage.setText("my text");
+ sender.send(simpleMessage);
+
+ assertEquals("host", sender.transport.getConnectedHost());
+ assertEquals(30, sender.transport.getConnectedPort());
+ assertEquals("username", sender.transport.getConnectedUsername());
+ assertEquals("password", sender.transport.getConnectedPassword());
+ assertTrue(sender.transport.isCloseCalled());
+
+ assertEquals(1, sender.transport.getSentMessages().size());
+ MimeMessage sentMessage = sender.transport.getSentMessage(0);
+ List froms = Arrays.asList(sentMessage.getFrom());
+ assertEquals(1, froms.size());
+ assertEquals("me@mail.org", ((InternetAddress) froms.get(0)).getAddress());
+ List replyTos = Arrays.asList(sentMessage.getReplyTo());
+ assertEquals("reply@mail.org", ((InternetAddress) replyTos.get(0)).getAddress());
+ List tos = Arrays.asList(sentMessage.getRecipients(Message.RecipientType.TO));
+ assertEquals(1, tos.size());
+ assertEquals("you@mail.org", ((InternetAddress) tos.get(0)).getAddress());
+ List ccs = Arrays.asList(sentMessage.getRecipients(Message.RecipientType.CC));
+ assertEquals(2, ccs.size());
+ assertEquals("he@mail.org", ((InternetAddress) ccs.get(0)).getAddress());
+ assertEquals("she@mail.org", ((InternetAddress) ccs.get(1)).getAddress());
+ List bccs = Arrays.asList(sentMessage.getRecipients(Message.RecipientType.BCC));
+ assertEquals(2, bccs.size());
+ assertEquals("us@mail.org", ((InternetAddress) bccs.get(0)).getAddress());
+ assertEquals("them@mail.org", ((InternetAddress) bccs.get(1)).getAddress());
+ assertEquals(sentDate.getTime(), sentMessage.getSentDate().getTime());
+ assertEquals("my subject", sentMessage.getSubject());
+ assertEquals("my text", sentMessage.getContent());
+ }
+
+ public void testJavaMailSenderWithSimpleMessages() throws MessagingException, IOException {
+ MockJavaMailSender sender = new MockJavaMailSender();
+ sender.setHost("host");
+ sender.setUsername("username");
+ sender.setPassword("password");
+
+ SimpleMailMessage simpleMessage1 = new SimpleMailMessage();
+ simpleMessage1.setTo("he@mail.org");
+ SimpleMailMessage simpleMessage2 = new SimpleMailMessage();
+ simpleMessage2.setTo("she@mail.org");
+ sender.send(new SimpleMailMessage[] {simpleMessage1, simpleMessage2});
+
+ assertEquals(sender.transport.getConnectedHost(), "host");
+ assertEquals(sender.transport.getConnectedUsername(), "username");
+ assertEquals(sender.transport.getConnectedPassword(), "password");
+ assertTrue(sender.transport.isCloseCalled());
+
+ assertEquals(2, sender.transport.getSentMessages().size());
+ MimeMessage sentMessage1 = sender.transport.getSentMessage(0);
+ List tos1 = Arrays.asList(sentMessage1.getRecipients(Message.RecipientType.TO));
+ assertEquals(1, tos1.size());
+ assertEquals("he@mail.org", ((InternetAddress) tos1.get(0)).getAddress());
+ MimeMessage sentMessage2 = sender.transport.getSentMessage(1);
+ List tos2 = Arrays.asList(sentMessage2.getRecipients(Message.RecipientType.TO));
+ assertEquals(1, tos2.size());
+ assertEquals("she@mail.org", ((InternetAddress) tos2.get(0)).getAddress());
+ }
+
+ public void testJavaMailSenderWithMimeMessage() throws MessagingException {
+ MockJavaMailSender sender = new MockJavaMailSender();
+ sender.setHost("host");
+ sender.setUsername("username");
+ sender.setPassword("password");
+
+ MimeMessage mimeMessage = sender.createMimeMessage();
+ mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress("you@mail.org"));
+ sender.send(mimeMessage);
+
+ assertEquals(sender.transport.getConnectedHost(), "host");
+ assertEquals(sender.transport.getConnectedUsername(), "username");
+ assertEquals(sender.transport.getConnectedPassword(), "password");
+ assertTrue(sender.transport.isCloseCalled());
+ assertEquals(1, sender.transport.getSentMessages().size());
+ assertEquals(mimeMessage, sender.transport.getSentMessage(0));
+ }
+
+ public void testJavaMailSenderWithMimeMessages() throws MessagingException {
+ MockJavaMailSender sender = new MockJavaMailSender();
+ sender.setHost("host");
+ sender.setUsername("username");
+ sender.setPassword("password");
+
+ MimeMessage mimeMessage1 = sender.createMimeMessage();
+ mimeMessage1.setRecipient(Message.RecipientType.TO, new InternetAddress("he@mail.org"));
+ MimeMessage mimeMessage2 = sender.createMimeMessage();
+ mimeMessage2.setRecipient(Message.RecipientType.TO, new InternetAddress("she@mail.org"));
+ sender.send(new MimeMessage[] {mimeMessage1, mimeMessage2});
+
+ assertEquals(sender.transport.getConnectedHost(), "host");
+ assertEquals(sender.transport.getConnectedUsername(), "username");
+ assertEquals(sender.transport.getConnectedPassword(), "password");
+ assertTrue(sender.transport.isCloseCalled());
+ assertEquals(2, sender.transport.getSentMessages().size());
+ assertEquals(mimeMessage1, sender.transport.getSentMessage(0));
+ assertEquals(mimeMessage2, sender.transport.getSentMessage(1));
+ }
+
+ public void testJavaMailSenderWithMimeMessagePreparator() {
+ MockJavaMailSender sender = new MockJavaMailSender();
+ sender.setHost("host");
+ sender.setUsername("username");
+ sender.setPassword("password");
+
+ final List messages = new ArrayList();
+
+ MimeMessagePreparator preparator = new MimeMessagePreparator() {
+ public void prepare(MimeMessage mimeMessage) throws MessagingException {
+ mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress("you@mail.org"));
+ messages.add(mimeMessage);
+ }
+ };
+ sender.send(preparator);
+
+ assertEquals(sender.transport.getConnectedHost(), "host");
+ assertEquals(sender.transport.getConnectedUsername(), "username");
+ assertEquals(sender.transport.getConnectedPassword(), "password");
+ assertTrue(sender.transport.isCloseCalled());
+ assertEquals(1, sender.transport.getSentMessages().size());
+ assertEquals(messages.get(0), sender.transport.getSentMessage(0));
+ }
+
+ public void testJavaMailSenderWithMimeMessagePreparators() {
+ MockJavaMailSender sender = new MockJavaMailSender();
+ sender.setHost("host");
+ sender.setUsername("username");
+ sender.setPassword("password");
+
+ final List messages = new ArrayList();
+
+ MimeMessagePreparator preparator1 = new MimeMessagePreparator() {
+ public void prepare(MimeMessage mimeMessage) throws MessagingException {
+ mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress("he@mail.org"));
+ messages.add(mimeMessage);
+ }
+ };
+ MimeMessagePreparator preparator2 = new MimeMessagePreparator() {
+ public void prepare(MimeMessage mimeMessage) throws MessagingException {
+ mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress("she@mail.org"));
+ messages.add(mimeMessage);
+ }
+ };
+ sender.send(new MimeMessagePreparator[] {preparator1, preparator2});
+
+ assertEquals(sender.transport.getConnectedHost(), "host");
+ assertEquals(sender.transport.getConnectedUsername(), "username");
+ assertEquals(sender.transport.getConnectedPassword(), "password");
+ assertTrue(sender.transport.isCloseCalled());
+ assertEquals(2, sender.transport.getSentMessages().size());
+ assertEquals(messages.get(0), sender.transport.getSentMessage(0));
+ assertEquals(messages.get(1), sender.transport.getSentMessage(1));
+ }
+
+ public void testJavaMailSenderWithMimeMessageHelper() throws MessagingException {
+ MockJavaMailSender sender = new MockJavaMailSender();
+ sender.setHost("host");
+ sender.setUsername("username");
+ sender.setPassword("password");
+
+ MimeMessageHelper message = new MimeMessageHelper(sender.createMimeMessage());
+ assertNull(message.getEncoding());
+ assertTrue(message.getFileTypeMap() instanceof ConfigurableMimeFileTypeMap);
+
+ message.setTo("you@mail.org");
+ sender.send(message.getMimeMessage());
+
+ assertEquals(sender.transport.getConnectedHost(), "host");
+ assertEquals(sender.transport.getConnectedUsername(), "username");
+ assertEquals(sender.transport.getConnectedPassword(), "password");
+ assertTrue(sender.transport.isCloseCalled());
+ assertEquals(1, sender.transport.getSentMessages().size());
+ assertEquals(message.getMimeMessage(), sender.transport.getSentMessage(0));
+ }
+
+ public void testJavaMailSenderWithMimeMessageHelperAndSpecificEncoding() throws MessagingException {
+ MockJavaMailSender sender = new MockJavaMailSender();
+ sender.setHost("host");
+ sender.setUsername("username");
+ sender.setPassword("password");
+
+ MimeMessageHelper message = new MimeMessageHelper(sender.createMimeMessage(), "UTF-8");
+ assertEquals("UTF-8", message.getEncoding());
+ FileTypeMap fileTypeMap = new ConfigurableMimeFileTypeMap();
+ message.setFileTypeMap(fileTypeMap);
+ assertEquals(fileTypeMap, message.getFileTypeMap());
+
+ message.setTo("you@mail.org");
+ sender.send(message.getMimeMessage());
+
+ assertEquals(sender.transport.getConnectedHost(), "host");
+ assertEquals(sender.transport.getConnectedUsername(), "username");
+ assertEquals(sender.transport.getConnectedPassword(), "password");
+ assertTrue(sender.transport.isCloseCalled());
+ assertEquals(1, sender.transport.getSentMessages().size());
+ assertEquals(message.getMimeMessage(), sender.transport.getSentMessage(0));
+ }
+
+ public void testJavaMailSenderWithMimeMessageHelperAndDefaultEncoding() throws MessagingException {
+ MockJavaMailSender sender = new MockJavaMailSender();
+ sender.setHost("host");
+ sender.setUsername("username");
+ sender.setPassword("password");
+ sender.setDefaultEncoding("UTF-8");
+
+ FileTypeMap fileTypeMap = new ConfigurableMimeFileTypeMap();
+ sender.setDefaultFileTypeMap(fileTypeMap);
+ MimeMessageHelper message = new MimeMessageHelper(sender.createMimeMessage());
+ assertEquals("UTF-8", message.getEncoding());
+ assertEquals(fileTypeMap, message.getFileTypeMap());
+
+ message.setTo("you@mail.org");
+ sender.send(message.getMimeMessage());
+
+ assertEquals(sender.transport.getConnectedHost(), "host");
+ assertEquals(sender.transport.getConnectedUsername(), "username");
+ assertEquals(sender.transport.getConnectedPassword(), "password");
+ assertTrue(sender.transport.isCloseCalled());
+ assertEquals(1, sender.transport.getSentMessages().size());
+ assertEquals(message.getMimeMessage(), sender.transport.getSentMessage(0));
+ }
+
+ public void testJavaMailSenderWithParseExceptionOnSimpleMessage() {
+ MockJavaMailSender sender = new MockJavaMailSender();
+ SimpleMailMessage simpleMessage = new SimpleMailMessage();
+ simpleMessage.setFrom("");
+ try {
+ sender.send(simpleMessage);
+ }
+ catch (MailParseException ex) {
+ // expected
+ assertTrue(ex.getCause() instanceof AddressException);
+ }
+ }
+
+ public void testJavaMailSenderWithParseExceptionOnMimeMessagePreparator() {
+ MockJavaMailSender sender = new MockJavaMailSender();
+ MimeMessagePreparator preparator = new MimeMessagePreparator() {
+ public void prepare(MimeMessage mimeMessage) throws MessagingException {
+ mimeMessage.setFrom(new InternetAddress(""));
+ }
+ };
+ try {
+ sender.send(preparator);
+ }
+ catch (MailParseException ex) {
+ // expected
+ assertTrue(ex.getCause() instanceof AddressException);
+ }
+ }
+
+ public void testJavaMailSenderWithCustomSession() throws MessagingException {
+ final Session session = Session.getInstance(new Properties());
+ MockJavaMailSender sender = new MockJavaMailSender() {
+ protected Transport getTransport(Session sess) throws NoSuchProviderException {
+ assertEquals(session, sess);
+ return super.getTransport(sess);
+ }
+ };
+ sender.setSession(session);
+ sender.setHost("host");
+ sender.setUsername("username");
+ sender.setPassword("password");
+
+ MimeMessage mimeMessage = sender.createMimeMessage();
+ mimeMessage.setSubject("custom");
+ mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress("you@mail.org"));
+ mimeMessage.setSentDate(new Date(2005, 3, 1));
+ sender.send(mimeMessage);
+
+ assertEquals(sender.transport.getConnectedHost(), "host");
+ assertEquals(sender.transport.getConnectedUsername(), "username");
+ assertEquals(sender.transport.getConnectedPassword(), "password");
+ assertTrue(sender.transport.isCloseCalled());
+ assertEquals(1, sender.transport.getSentMessages().size());
+ assertEquals(mimeMessage, sender.transport.getSentMessage(0));
+ }
+
+ public void testJavaMailProperties() throws MessagingException {
+ Properties props = new Properties();
+ props.setProperty("bogusKey", "bogusValue");
+ MockJavaMailSender sender = new MockJavaMailSender() {
+ protected Transport getTransport(Session sess) throws NoSuchProviderException {
+ assertEquals("bogusValue", sess.getProperty("bogusKey"));
+ return super.getTransport(sess);
+ }
+ };
+ sender.setJavaMailProperties(props);
+ sender.setHost("host");
+ sender.setUsername("username");
+ sender.setPassword("password");
+
+ MimeMessage mimeMessage = sender.createMimeMessage();
+ mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress("you@mail.org"));
+ sender.send(mimeMessage);
+
+ assertEquals(sender.transport.getConnectedHost(), "host");
+ assertEquals(sender.transport.getConnectedUsername(), "username");
+ assertEquals(sender.transport.getConnectedPassword(), "password");
+ assertTrue(sender.transport.isCloseCalled());
+ assertEquals(1, sender.transport.getSentMessages().size());
+ assertEquals(mimeMessage, sender.transport.getSentMessage(0));
+ }
+
+ public void testFailedMailServerConnect() throws Exception {
+ MockJavaMailSender sender = new MockJavaMailSender();
+ sender.setHost(null);
+ sender.setUsername("username");
+ sender.setPassword("password");
+ SimpleMailMessage simpleMessage1 = new SimpleMailMessage();
+ try {
+ sender.send(simpleMessage1);
+ fail("Should have thrown MailSendException");
+ }
+ catch (MailSendException ex) {
+ // expected
+ assertTrue(ex.getFailedMessages() != null);
+ assertTrue(ex.getFailedMessages().isEmpty());
+ }
+ }
+
+ public void testFailedSimpleMessage() throws Exception {
+ MockJavaMailSender sender = new MockJavaMailSender();
+ sender.setHost("host");
+ sender.setUsername("username");
+ sender.setPassword("password");
+
+ SimpleMailMessage simpleMessage1 = new SimpleMailMessage();
+ simpleMessage1.setTo("he@mail.org");
+ simpleMessage1.setSubject("fail");
+ SimpleMailMessage simpleMessage2 = new SimpleMailMessage();
+ simpleMessage2.setTo("she@mail.org");
+
+ try {
+ sender.send(new SimpleMailMessage[] {simpleMessage1, simpleMessage2});
+ }
+ catch (MailSendException ex) {
+ System.out.println(ex);
+ ex.printStackTrace();
+ assertEquals(sender.transport.getConnectedHost(), "host");
+ assertEquals(sender.transport.getConnectedUsername(), "username");
+ assertEquals(sender.transport.getConnectedPassword(), "password");
+ assertTrue(sender.transport.isCloseCalled());
+ assertEquals(1, sender.transport.getSentMessages().size());
+ assertEquals(new InternetAddress("she@mail.org"), sender.transport.getSentMessage(0).getAllRecipients()[0]);
+ assertEquals(1, ex.getFailedMessages().size());
+ assertEquals(simpleMessage1, ex.getFailedMessages().keySet().iterator().next());
+ Object subEx = ex.getFailedMessages().values().iterator().next();
+ assertTrue(subEx instanceof MessagingException);
+ assertEquals("failed", ((MessagingException) subEx).getMessage());
+ }
+ }
+
+ public void testFailedMimeMessage() throws Exception {
+ MockJavaMailSender sender = new MockJavaMailSender();
+ sender.setHost("host");
+ sender.setUsername("username");
+ sender.setPassword("password");
+
+ MimeMessage mimeMessage1 = sender.createMimeMessage();
+ mimeMessage1.setRecipient(Message.RecipientType.TO, new InternetAddress("he@mail.org"));
+ mimeMessage1.setSubject("fail");
+ MimeMessage mimeMessage2 = sender.createMimeMessage();
+ mimeMessage2.setRecipient(Message.RecipientType.TO, new InternetAddress("she@mail.org"));
+
+ try {
+ sender.send(new MimeMessage[] {mimeMessage1, mimeMessage2});
+ }
+ catch (MailSendException ex) {
+ ex.printStackTrace();
+ assertEquals(sender.transport.getConnectedHost(), "host");
+ assertEquals(sender.transport.getConnectedUsername(), "username");
+ assertEquals(sender.transport.getConnectedPassword(), "password");
+ assertTrue(sender.transport.isCloseCalled());
+ assertEquals(1, sender.transport.getSentMessages().size());
+ assertEquals(mimeMessage2, sender.transport.getSentMessage(0));
+ assertEquals(1, ex.getFailedMessages().size());
+ assertEquals(mimeMessage1, ex.getFailedMessages().keySet().iterator().next());
+ Object subEx = ex.getFailedMessages().values().iterator().next();
+ assertTrue(subEx instanceof MessagingException);
+ assertEquals("failed", ((MessagingException) subEx).getMessage());
+ }
+ }
+
+
+ private static class MockJavaMailSender extends JavaMailSenderImpl {
+
+ private MockTransport transport;
+
+ protected Transport getTransport(Session session) throws NoSuchProviderException {
+ this.transport = new MockTransport(session, null);
+ return transport;
+ }
+ }
+
+
+ private static class MockTransport extends Transport {
+
+ private String connectedHost = null;
+ private int connectedPort = -2;
+ private String connectedUsername = null;
+ private String connectedPassword = null;
+ private boolean closeCalled = false;
+ private List sentMessages = new ArrayList();
+
+ public MockTransport(Session session, URLName urlName) {
+ super(session, urlName);
+ }
+
+ public String getConnectedHost() {
+ return connectedHost;
+ }
+
+ public int getConnectedPort() {
+ return connectedPort;
+ }
+
+ public String getConnectedUsername() {
+ return connectedUsername;
+ }
+
+ public String getConnectedPassword() {
+ return connectedPassword;
+ }
+
+ public boolean isCloseCalled() {
+ return closeCalled;
+ }
+
+ public List getSentMessages() {
+ return sentMessages;
+ }
+
+ public MimeMessage getSentMessage(int index) {
+ return (MimeMessage) this.sentMessages.get(index);
+ }
+
+ public void connect(String host, int port, String username, String password) throws MessagingException {
+ if (host == null) {
+ throw new MessagingException("no host");
+ }
+ this.connectedHost = host;
+ this.connectedPort = port;
+ this.connectedUsername = username;
+ this.connectedPassword = password;
+ }
+
+ public synchronized void close() throws MessagingException {
+ this.closeCalled = true;
+ }
+
+ public void sendMessage(Message message, Address[] addresses) throws MessagingException {
+ if ("fail".equals(message.getSubject())) {
+ throw new MessagingException("failed");
+ }
+ List addr1 = Arrays.asList(message.getAllRecipients());
+ List addr2 = Arrays.asList(addresses);
+ if (!addr1.equals(addr2)) {
+ throw new MessagingException("addresses not correct");
+ }
+ if (message.getSentDate() == null) {
+ throw new MessagingException("No sentDate specified");
+ }
+ if (message.getSubject() != null && message.getSubject().indexOf("custom") != -1) {
+ assertEquals(new Date(2005, 3, 1), message.getSentDate());
+ }
+ this.sentMessages.add(message);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/mail/javamail/test.mime.types b/org.springframework.testsuite/src/test/java/org/springframework/mail/javamail/test.mime.types
new file mode 100644
index 00000000000..f54f4d7f211
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/mail/javamail/test.mime.types
@@ -0,0 +1,4 @@
+text/foo foo
+text/bar bar
+image/foo fimg
+image/bar bimg
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/mock/easymock/AbstractScalarMockTemplate.java b/org.springframework.testsuite/src/test/java/org/springframework/mock/easymock/AbstractScalarMockTemplate.java
new file mode 100644
index 00000000000..aaba654bb56
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/mock/easymock/AbstractScalarMockTemplate.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.mock.easymock;
+
+import org.easymock.MockControl;
+
+/**
+ * Makes those tests that require a single (scalar) EasyMock mock
+ * control and object easier to author.
+ *
+ * @author Rick Evans
+ * @since 2.0
+ */
+public abstract class AbstractScalarMockTemplate {
+
+ private static final int NORMAL = 0;
+ private static final int NICE = 1;
+ private static final int STRICT = 2;
+
+
+ private Class mockInterface;
+
+ private int mode = NORMAL;
+
+
+ /**
+ * Creates a new instance of the {@link AbstractScalarMockTemplate} class.
+ */
+ protected AbstractScalarMockTemplate() {
+ }
+
+ /**
+ * Creates a new instance of the {@link AbstractScalarMockTemplate} class.
+ * @param mockInterface the interface that is to be mocked
+ */
+ protected AbstractScalarMockTemplate(Class mockInterface) {
+ this.mockInterface = mockInterface;
+ }
+
+ /**
+ * Creates a new instance of the {@link AbstractScalarMockTemplate} class.
+ * @param mockInterface the interface that is to be mocked
+ * @param nice true if a "nice" mock control is to be created;
+ * false if a "strict" control is to be created
+ */
+ protected AbstractScalarMockTemplate(Class mockInterface, boolean nice) {
+ this.mockInterface = mockInterface;
+ this.mode = nice ? NICE : STRICT;
+ }
+
+
+ /**
+ * Sets the interface that is to be mocked.
+ * @param mockInterface the interface that is to be mocked
+ */
+ public void setMockInterface(Class mockInterface) {
+ this.mockInterface = mockInterface;
+ }
+
+ /**
+ * Gets the interface that is to be mocked.
+ * @return the interface that is to be mocked
+ */
+ public Class getMockInterface() {
+ return mockInterface;
+ }
+
+
+ /**
+ * Setup any expectations for the test.
+ *
The default implementation is a no-op; i.e. no expectations are set.
+ * @param mockControl the EasyMock {@link org.easymock.MockControl} for the mocked object
+ * @param mockObject the mocked object
+ * @throws Exception if calling methods on the supplied mockObject
+ * that are declared as throwing one more exceptions (just here to satisfy the compiler really).
+ */
+ public void setupExpectations(MockControl mockControl, Object mockObject) throws Exception {
+ }
+
+ /**
+ * Do the EasyMock-driven test.
+ *
This is the driving template method, and should not typically need to overriden.
+ * @throws Exception if an exception is thrown during testing
+ */
+ public void test() throws Exception {
+ MockControl mockControl = createMockControl();
+ Object mockObject = mockControl.getMock();
+ setupExpectations(mockControl, mockObject);
+ mockControl.replay();
+ doTest(mockObject);
+ mockControl.verify();
+ }
+
+ /**
+ * Do the actual test using the supplied mock.
+ * @param mockObject the mocked object
+ * @throws Exception if an exception is thrown during the test logic
+ */
+ public abstract void doTest(Object mockObject) throws Exception;
+
+
+ /**
+ * Create a {@link org.easymock.MockControl} for the mocked interface.
+ * @return a {@link org.easymock.MockControl} for the mocked interface
+ */
+ protected MockControl createMockControl() {
+ return this.mode == NORMAL
+ ? MockControl.createControl(this.getMockInterface())
+ : this.mode == NICE
+ ? MockControl.createNiceControl(this.getMockInterface())
+ : MockControl.createStrictControl(this.getMockInterface());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java b/org.springframework.testsuite/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java
new file mode 100644
index 00000000000..0f6d11ad00c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.mock.web;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rick Evans
+ * @author Mark Fisher
+ */
+public class MockHttpServletRequestTests extends TestCase {
+
+ public void testHttpHeaderNameCasingIsPreserved() throws Exception {
+ String headerName = "Header1";
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addHeader(headerName, "value1");
+ Enumeration requestHeaders = request.getHeaderNames();
+ assertNotNull(requestHeaders);
+ assertEquals("HTTP header casing not being preserved", headerName, requestHeaders.nextElement());
+ }
+
+ public void testSetMultipleParameters() {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setParameter("key1", "value1");
+ request.setParameter("key2", "value2");
+ Map params = new HashMap(2);
+ params.put("key1", "newValue1");
+ params.put("key3", new String[] { "value3A", "value3B" });
+ request.setParameters(params);
+ String[] values1 = request.getParameterValues("key1");
+ assertEquals(1, values1.length);
+ assertEquals("newValue1", request.getParameter("key1"));
+ assertEquals("value2", request.getParameter("key2"));
+ String[] values3 = request.getParameterValues("key3");
+ assertEquals(2, values3.length);
+ assertEquals("value3A", values3[0]);
+ assertEquals("value3B", values3[1]);
+ }
+
+ public void testAddMultipleParameters() {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setParameter("key1", "value1");
+ request.setParameter("key2", "value2");
+ Map params = new HashMap(2);
+ params.put("key1", "newValue1");
+ params.put("key3", new String[] { "value3A", "value3B" });
+ request.addParameters(params);
+ String[] values1 = request.getParameterValues("key1");
+ assertEquals(2, values1.length);
+ assertEquals("value1", values1[0]);
+ assertEquals("newValue1", values1[1]);
+ assertEquals("value2", request.getParameter("key2"));
+ String[] values3 = request.getParameterValues("key3");
+ assertEquals(2, values3.length);
+ assertEquals("value3A", values3[0]);
+ assertEquals("value3B", values3[1]);
+ }
+
+ public void testRemoveAllParameters() {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setParameter("key1", "value1");
+ Map params = new HashMap(2);
+ params.put("key2", "value2");
+ params.put("key3", new String[] { "value3A", "value3B" });
+ request.addParameters(params);
+ assertEquals(3, request.getParameterMap().size());
+ request.removeAllParameters();
+ assertEquals(0, request.getParameterMap().size());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java b/org.springframework.testsuite/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java
new file mode 100644
index 00000000000..e2b31f07ed7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.mock.web;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.springframework.web.util.WebUtils;
+
+/**
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ * @since 19.02.2006
+ */
+public class MockHttpServletResponseTests extends TestCase {
+
+ public void testSetContentTypeWithNoEncoding() {
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ response.setContentType("test/plain");
+ assertEquals("Character encoding should be the default",
+ WebUtils.DEFAULT_CHARACTER_ENCODING, response.getCharacterEncoding());
+ }
+
+ public void testSetContentTypeWithUTF8() {
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ response.setContentType("test/plain; charset=UTF-8");
+ assertEquals("Character encoding should be 'UTF-8'", "UTF-8", response.getCharacterEncoding());
+ }
+
+ public void testHttpHeaderNameCasingIsPreserved() throws Exception {
+ final String headerName = "Header1";
+
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ response.addHeader(headerName, "value1");
+ Set responseHeaders = response.getHeaderNames();
+ assertNotNull(responseHeaders);
+ assertEquals(1, responseHeaders.size());
+ assertEquals("HTTP header casing not being preserved", headerName, responseHeaders.iterator().next());
+ }
+
+ public void testServletOutputStreamCommittedWhenBufferSizeExceeded() throws IOException {
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ assertFalse(response.isCommitted());
+ response.getOutputStream().write('X');
+ assertFalse(response.isCommitted());
+ int size = response.getBufferSize();
+ response.getOutputStream().write(new byte[size]);
+ assertTrue(response.isCommitted());
+ assertEquals(size + 1, response.getContentAsByteArray().length);
+ }
+
+ public void testServletOutputStreamCommittedOnFlushBuffer() throws IOException {
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ assertFalse(response.isCommitted());
+ response.getOutputStream().write('X');
+ assertFalse(response.isCommitted());
+ response.flushBuffer();
+ assertTrue(response.isCommitted());
+ assertEquals(1, response.getContentAsByteArray().length);
+ }
+
+ public void testServletWriterCommittedWhenBufferSizeExceeded() throws IOException {
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ assertFalse(response.isCommitted());
+ response.getWriter().write("X");
+ assertFalse(response.isCommitted());
+ int size = response.getBufferSize();
+ char[] data = new char[size];
+ Arrays.fill(data, 'p');
+ response.getWriter().write(data);
+ assertTrue(response.isCommitted());
+ assertEquals(size + 1, response.getContentAsByteArray().length);
+ }
+
+ public void testServletOutputStreamCommittedOnOutputStreamFlush() throws IOException {
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ assertFalse(response.isCommitted());
+ response.getOutputStream().write('X');
+ assertFalse(response.isCommitted());
+ response.getOutputStream().flush();
+ assertTrue(response.isCommitted());
+ assertEquals(1, response.getContentAsByteArray().length);
+ }
+
+ public void testServletWriterCommittedOnWriterFlush() throws IOException {
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ assertFalse(response.isCommitted());
+ response.getWriter().write("X");
+ assertFalse(response.isCommitted());
+ response.getWriter().flush();
+ assertTrue(response.isCommitted());
+ assertEquals(1, response.getContentAsByteArray().length);
+ }
+
+ public void testServletWriterAutoFlushedForString() throws IOException {
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ response.getWriter().write("X");
+ assertEquals("X", response.getContentAsString());
+ }
+
+ public void testServletWriterAutoFlushedForChar() throws IOException {
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ response.getWriter().write('X');
+ assertEquals("X", response.getContentAsString());
+ }
+
+ public void testServletWriterAutoFlushedForCharArray() throws IOException {
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ response.getWriter().write("XY".toCharArray());
+ assertEquals("XY", response.getContentAsString());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/mock/web/MockPageContextTests.java b/org.springframework.testsuite/src/test/java/org/springframework/mock/web/MockPageContextTests.java
new file mode 100644
index 00000000000..33cde3e8724
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/mock/web/MockPageContextTests.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.mock.web;
+
+import junit.framework.TestCase;
+
+import javax.servlet.jsp.PageContext;
+
+/**
+ * Unit tests for the MockPageContext class.
+ *
+ * @author Rick Evans
+ */
+public final class MockPageContextTests extends TestCase {
+
+ public void testSetAttributeWithNoScopeUsesPageScope() throws Exception {
+ String key = "foo";
+ String value = "bar";
+
+ MockPageContext ctx = new MockPageContext();
+ ctx.setAttribute(key, value);
+ assertEquals(value, ctx.getAttribute(key, PageContext.PAGE_SCOPE));
+ assertNull(ctx.getAttribute(key, PageContext.APPLICATION_SCOPE));
+ assertNull(ctx.getAttribute(key, PageContext.REQUEST_SCOPE));
+ assertNull(ctx.getAttribute(key, PageContext.SESSION_SCOPE));
+ }
+
+ public void testRemoveAttributeWithNoScopeSpecifiedRemovesValueFromAllScopes() throws Exception {
+ String key = "foo";
+ String value = "bar";
+
+ MockPageContext ctx = new MockPageContext();
+ ctx.setAttribute(key, value, PageContext.APPLICATION_SCOPE);
+ ctx.removeAttribute(key);
+
+ assertNull(ctx.getAttribute(key, PageContext.PAGE_SCOPE));
+ assertNull(ctx.getAttribute(key, PageContext.APPLICATION_SCOPE));
+ assertNull(ctx.getAttribute(key, PageContext.REQUEST_SCOPE));
+ assertNull(ctx.getAttribute(key, PageContext.SESSION_SCOPE));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/mock/web/MockServletContextTests.java b/org.springframework.testsuite/src/test/java/org/springframework/mock/web/MockServletContextTests.java
new file mode 100644
index 00000000000..370845a0676
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/mock/web/MockServletContextTests.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.mock.web;
+
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Juergen Hoeller
+ * @since 19.02.2006
+ */
+public class MockServletContextTests extends TestCase {
+
+ public void testListFiles() {
+ MockServletContext sc = new MockServletContext("org/springframework/mock");
+ Set paths = sc.getResourcePaths("/web");
+ assertNotNull(paths);
+ assertTrue(paths.contains("/web/MockServletContextTests.class"));
+ }
+
+ public void testListSubdirectories() {
+ MockServletContext sc = new MockServletContext("org/springframework/mock");
+ Set paths = sc.getResourcePaths("/");
+ assertNotNull(paths);
+ assertTrue(paths.contains("/web/"));
+ }
+
+ public void testListNonDirectory() {
+ MockServletContext sc = new MockServletContext("org/springframework/mock");
+ Set paths = sc.getResourcePaths("/web/MockServletContextTests.class");
+ assertNull(paths);
+ }
+
+ public void testListInvalidPath() {
+ MockServletContext sc = new MockServletContext("org/springframework/mock");
+ Set paths = sc.getResourcePaths("/web/invalid");
+ assertNull(paths);
+ }
+
+ public void testGetContext() {
+ MockServletContext sc = new MockServletContext();
+ MockServletContext sc2 = new MockServletContext();
+ sc.setContextPath("/");
+ sc.registerContext("/second", sc2);
+ assertSame(sc, sc.getContext("/"));
+ assertSame(sc2, sc.getContext("/second"));
+ }
+
+ public void testGetMimeType() {
+ MockServletContext sc = new MockServletContext();
+ assertEquals("text/html", sc.getMimeType("test.html"));
+ assertEquals("image/gif", sc.getMimeType("test.gif"));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/HibernateInterceptorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/HibernateInterceptorTests.java
new file mode 100644
index 00000000000..517a945f723
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/HibernateInterceptorTests.java
@@ -0,0 +1,603 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.orm.hibernate3;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Method;
+import java.sql.SQLException;
+
+import junit.framework.TestCase;
+import org.aopalliance.intercept.Interceptor;
+import org.aopalliance.intercept.Invocation;
+import org.aopalliance.intercept.MethodInvocation;
+import org.easymock.MockControl;
+import org.hibernate.FlushMode;
+import org.hibernate.HibernateException;
+import org.hibernate.SessionFactory;
+import org.hibernate.classic.Session;
+import org.hibernate.exception.ConstraintViolationException;
+
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+
+/**
+ * @author Juergen Hoeller
+ * @since 05.03.2005
+ */
+public class HibernateInterceptorTests extends TestCase {
+
+ public void testInterceptorWithNewSession() throws HibernateException {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateInterceptor interceptor = new HibernateInterceptor();
+ interceptor.setSessionFactory(sf);
+ try {
+ interceptor.invoke(new TestInvocation(sf));
+ }
+ catch (Throwable t) {
+ fail("Should not have thrown Throwable: " + t.getMessage());
+ }
+
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testInterceptorWithNewSessionAndFlushNever() throws HibernateException {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf);
+ session.setFlushMode(FlushMode.NEVER);
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateInterceptor interceptor = new HibernateInterceptor();
+ interceptor.setFlushModeName("FLUSH_NEVER");
+ interceptor.setSessionFactory(sf);
+ try {
+ interceptor.invoke(new TestInvocation(sf));
+ }
+ catch (Throwable t) {
+ fail("Should not have thrown Throwable: " + t.getMessage());
+ }
+
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testInterceptorWithNewSessionAndFilter() throws HibernateException {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf);
+ session.enableFilter("myFilter");
+ sessionControl.setReturnValue(null, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateInterceptor interceptor = new HibernateInterceptor();
+ interceptor.setSessionFactory(sf);
+ interceptor.setFilterName("myFilter");
+ try {
+ interceptor.invoke(new TestInvocation(sf));
+ }
+ catch (Throwable t) {
+ fail("Should not have thrown Throwable: " + t.getMessage());
+ }
+
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testInterceptorWithThreadBound() {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
+ HibernateInterceptor interceptor = new HibernateInterceptor();
+ interceptor.setSessionFactory(sf);
+ try {
+ interceptor.invoke(new TestInvocation(sf));
+ }
+ catch (Throwable t) {
+ fail("Should not have thrown Throwable: " + t.getMessage());
+ }
+ finally {
+ TransactionSynchronizationManager.unbindResource(sf);
+ }
+
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testInterceptorWithThreadBoundAndFlushEager() throws HibernateException {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
+ HibernateInterceptor interceptor = new HibernateInterceptor();
+ interceptor.setFlushMode(HibernateInterceptor.FLUSH_EAGER);
+ interceptor.setSessionFactory(sf);
+ try {
+ interceptor.invoke(new TestInvocation(sf));
+ }
+ catch (Throwable t) {
+ fail("Should not have thrown Throwable: " + t.getMessage());
+ }
+ finally {
+ TransactionSynchronizationManager.unbindResource(sf);
+ }
+
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testInterceptorWithThreadBoundAndFlushEagerSwitch() throws HibernateException {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.NEVER, 1);
+ session.setFlushMode(FlushMode.AUTO);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.setFlushMode(FlushMode.NEVER);
+ sessionControl.setVoidCallable(1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
+ HibernateInterceptor interceptor = new HibernateInterceptor();
+ interceptor.setFlushMode(HibernateInterceptor.FLUSH_EAGER);
+ interceptor.setSessionFactory(sf);
+ try {
+ interceptor.invoke(new TestInvocation(sf));
+ }
+ catch (Throwable t) {
+ fail("Should not have thrown Throwable: " + t.getMessage());
+ }
+ finally {
+ TransactionSynchronizationManager.unbindResource(sf);
+ }
+
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testInterceptorWithThreadBoundAndFlushCommit() {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO, 1);
+ session.setFlushMode(FlushMode.COMMIT);
+ sessionControl.setVoidCallable(1);
+ session.setFlushMode(FlushMode.AUTO);
+ sessionControl.setVoidCallable(1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
+ HibernateInterceptor interceptor = new HibernateInterceptor();
+ interceptor.setSessionFactory(sf);
+ interceptor.setFlushMode(HibernateInterceptor.FLUSH_COMMIT);
+ try {
+ interceptor.invoke(new TestInvocation(sf));
+ }
+ catch (Throwable t) {
+ fail("Should not have thrown Throwable: " + t.getMessage());
+ }
+ finally {
+ TransactionSynchronizationManager.unbindResource(sf);
+ }
+
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testInterceptorWithThreadBoundAndFlushAlways() {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO, 1);
+ session.setFlushMode(FlushMode.ALWAYS);
+ sessionControl.setVoidCallable(1);
+ session.setFlushMode(FlushMode.AUTO);
+ sessionControl.setVoidCallable(1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
+ HibernateInterceptor interceptor = new HibernateInterceptor();
+ interceptor.setSessionFactory(sf);
+ interceptor.setFlushMode(HibernateInterceptor.FLUSH_ALWAYS);
+ try {
+ interceptor.invoke(new TestInvocation(sf));
+ }
+ catch (Throwable t) {
+ fail("Should not have thrown Throwable: " + t.getMessage());
+ }
+ finally {
+ TransactionSynchronizationManager.unbindResource(sf);
+ }
+
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testInterceptorWithThreadBoundAndFilter() {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.enableFilter("myFilter");
+ sessionControl.setReturnValue(null, 1);
+ session.disableFilter("myFilter");
+ sessionControl.setVoidCallable(1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
+ HibernateInterceptor interceptor = new HibernateInterceptor();
+ interceptor.setSessionFactory(sf);
+ interceptor.setFilterName("myFilter");
+ try {
+ interceptor.invoke(new TestInvocation(sf));
+ }
+ catch (Throwable t) {
+ fail("Should not have thrown Throwable: " + t.getMessage());
+ }
+ finally {
+ TransactionSynchronizationManager.unbindResource(sf);
+ }
+
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testInterceptorWithThreadBoundAndFilters() {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.enableFilter("myFilter");
+ sessionControl.setReturnValue(null, 1);
+ session.enableFilter("yourFilter");
+ sessionControl.setReturnValue(null, 1);
+ session.disableFilter("myFilter");
+ sessionControl.setVoidCallable(1);
+ session.disableFilter("yourFilter");
+ sessionControl.setVoidCallable(1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
+ HibernateInterceptor interceptor = new HibernateInterceptor();
+ interceptor.setSessionFactory(sf);
+ interceptor.setFilterNames(new String[] {"myFilter", "yourFilter"});
+ try {
+ interceptor.invoke(new TestInvocation(sf));
+ }
+ catch (Throwable t) {
+ fail("Should not have thrown Throwable: " + t.getMessage());
+ }
+ finally {
+ TransactionSynchronizationManager.unbindResource(sf);
+ }
+
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testInterceptorWithFlushFailure() throws Throwable {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ SQLException sqlEx = new SQLException("argh", "27");
+ session.flush();
+ ConstraintViolationException jdbcEx = new ConstraintViolationException("", sqlEx, null);
+ sessionControl.setThrowable(jdbcEx, 1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateInterceptor interceptor = new HibernateInterceptor();
+ interceptor.setSessionFactory(sf);
+ try {
+ interceptor.invoke(new TestInvocation(sf));
+ fail("Should have thrown DataIntegrityViolationException");
+ }
+ catch (DataIntegrityViolationException ex) {
+ // expected
+ assertEquals(jdbcEx, ex.getCause());
+ }
+
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testInterceptorWithThreadBoundEmptyHolder() {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ SessionHolder holder = new SessionHolder("key", session);
+ holder.removeSession("key");
+ TransactionSynchronizationManager.bindResource(sf, holder);
+ HibernateInterceptor interceptor = new HibernateInterceptor();
+ interceptor.setSessionFactory(sf);
+ try {
+ interceptor.invoke(new TestInvocation(sf));
+ }
+ catch (Throwable t) {
+ fail("Should not have thrown Throwable: " + t.getMessage());
+ }
+
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testInterceptorWithEntityInterceptor() throws HibernateException {
+ MockControl interceptorControl = MockControl.createControl(org.hibernate.Interceptor.class);
+ org.hibernate.Interceptor entityInterceptor = (org.hibernate.Interceptor) interceptorControl.getMock();
+ interceptorControl.replay();
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ sf.openSession(entityInterceptor);
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateInterceptor interceptor = new HibernateInterceptor();
+ interceptor.setSessionFactory(sf);
+ interceptor.setEntityInterceptor(entityInterceptor);
+ try {
+ interceptor.invoke(new TestInvocation(sf));
+ }
+ catch (Throwable t) {
+ fail("Should not have thrown Throwable: " + t.getMessage());
+ }
+
+ interceptorControl.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testInterceptorWithEntityInterceptorBeanName() throws HibernateException {
+ MockControl interceptorControl = MockControl.createControl(org.hibernate.Interceptor.class);
+ org.hibernate.Interceptor entityInterceptor = (org.hibernate.Interceptor) interceptorControl.getMock();
+ interceptorControl.replay();
+ MockControl interceptor2Control = MockControl.createControl(org.hibernate.Interceptor.class);
+ org.hibernate.Interceptor entityInterceptor2 = (org.hibernate.Interceptor) interceptor2Control.getMock();
+ interceptor2Control.replay();
+
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ sf.openSession(entityInterceptor);
+ sfControl.setReturnValue(session, 1);
+ sf.openSession(entityInterceptor2);
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 2);
+ session.flush();
+ sessionControl.setVoidCallable(2);
+ session.close();
+ sessionControl.setReturnValue(null, 2);
+ sfControl.replay();
+ sessionControl.replay();
+
+ MockControl beanFactoryControl = MockControl.createControl(BeanFactory.class);
+ BeanFactory beanFactory = (BeanFactory) beanFactoryControl.getMock();
+ beanFactory.getBean("entityInterceptor", org.hibernate.Interceptor.class);
+ beanFactoryControl.setReturnValue(entityInterceptor, 1);
+ beanFactory.getBean("entityInterceptor", org.hibernate.Interceptor.class);
+ beanFactoryControl.setReturnValue(entityInterceptor2, 1);
+ beanFactoryControl.replay();
+
+ HibernateInterceptor interceptor = new HibernateInterceptor();
+ interceptor.setSessionFactory(sf);
+ interceptor.setEntityInterceptorBeanName("entityInterceptor");
+ interceptor.setBeanFactory(beanFactory);
+ for (int i = 0; i < 2; i++) {
+ try {
+ interceptor.invoke(new TestInvocation(sf));
+ }
+ catch (Throwable t) {
+ fail("Should not have thrown Throwable: " + t.getMessage());
+ }
+ }
+
+ interceptorControl.verify();
+ interceptor2Control.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ protected void tearDown() {
+ assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ }
+
+
+ private static class TestInvocation implements MethodInvocation {
+
+ private SessionFactory sessionFactory;
+
+ public TestInvocation(SessionFactory sessionFactory) {
+ this.sessionFactory = sessionFactory;
+ }
+
+ public Object proceed() throws Throwable {
+ if (!TransactionSynchronizationManager.hasResource(this.sessionFactory)) {
+ throw new IllegalStateException("Session not bound");
+ }
+ return null;
+ }
+
+ public int getCurrentInterceptorIndex() {
+ return 0;
+ }
+
+ public int getNumberOfInterceptors() {
+ return 0;
+ }
+
+ public Interceptor getInterceptor(int i) {
+ return null;
+ }
+
+ public Method getMethod() {
+ return null;
+ }
+
+ public AccessibleObject getStaticPart() {
+ return null;
+ }
+
+ public Object getArgument(int i) {
+ return null;
+ }
+
+ public Object[] getArguments() {
+ return null;
+ }
+
+ public void setArgument(int i, Object handler) {
+ }
+
+ public int getArgumentCount() {
+ return 0;
+ }
+
+ public Object getThis() {
+ return null;
+ }
+
+ public Object getProxy() {
+ return null;
+ }
+
+ public Invocation cloneInstance() {
+ return null;
+ }
+
+ public void release() {
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/HibernateJtaTransactionTests.java b/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/HibernateJtaTransactionTests.java
new file mode 100644
index 00000000000..134a4f2f7db
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/HibernateJtaTransactionTests.java
@@ -0,0 +1,1824 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.orm.hibernate3;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+import org.hibernate.FlushMode;
+import org.hibernate.HibernateException;
+import org.hibernate.Query;
+import org.hibernate.SessionFactory;
+import org.hibernate.classic.Session;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.SessionImplementor;
+
+import org.springframework.dao.DataAccessException;
+import org.springframework.transaction.MockJtaTransaction;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionException;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.UnexpectedRollbackException;
+import org.springframework.transaction.jta.JtaTransactionManager;
+import org.springframework.transaction.support.TransactionCallback;
+import org.springframework.transaction.support.TransactionCallbackWithoutResult;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+import org.springframework.transaction.support.TransactionTemplate;
+
+/**
+ * @author Juergen Hoeller
+ * @since 05.03.2005
+ */
+public class HibernateJtaTransactionTests extends TestCase {
+
+ public void testJtaTransactionCommit() throws Exception {
+ doTestJtaTransactionCommit(Status.STATUS_NO_TRANSACTION, false);
+ }
+
+ public void testJtaTransactionCommitWithReadOnly() throws Exception {
+ doTestJtaTransactionCommit(Status.STATUS_NO_TRANSACTION, true);
+ }
+
+ public void testJtaTransactionCommitWithExisting() throws Exception {
+ doTestJtaTransactionCommit(Status.STATUS_ACTIVE, false);
+ }
+
+ public void testJtaTransactionCommitWithExistingAndReadOnly() throws Exception {
+ doTestJtaTransactionCommit(Status.STATUS_ACTIVE, true);
+ }
+
+ private void doTestJtaTransactionCommit(int status, final boolean readOnly) throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ final MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ final MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ ut.getStatus();
+ utControl.setReturnValue(status, 1);
+ if (status == Status.STATUS_NO_TRANSACTION) {
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.commit();
+ utControl.setVoidCallable(1);
+ }
+ else {
+ ut.getStatus();
+ utControl.setReturnValue(status, 1);
+ }
+
+ final List list = new ArrayList();
+ list.add("test");
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.createQuery("some query string");
+ sessionControl.setReturnValue(query, 1);
+ if (readOnly) {
+ session.setFlushMode(FlushMode.NEVER);
+ sessionControl.setVoidCallable(1);
+ }
+ query.list();
+ queryControl.setReturnValue(list, 1);
+
+ utControl.replay();
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ JtaTransactionManager ptm = new JtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setReadOnly(readOnly);
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ try {
+ assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setExposeNativeSession(true);
+ ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session, sess);
+ return null;
+ }
+ });
+ ht = new HibernateTemplate(sf);
+ List htl = ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ return sess.createQuery("some query string").list();
+ }
+ });
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ sessionControl.verify();
+ queryControl.verify();
+ sessionControl.reset();
+ if (!readOnly) {
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ }
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sessionControl.replay();
+ return htl;
+ }
+ catch (Error err) {
+ err.printStackTrace();
+ throw err;
+ }
+ }
+ });
+
+ assertTrue("Correct result list", result == list);
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testJtaTransactionCommitWithJtaTm() throws Exception {
+ doTestJtaTransactionCommitWithJtaTm(Status.STATUS_NO_TRANSACTION);
+ }
+
+ public void testJtaTransactionCommitWithJtaTmAndExisting() throws Exception {
+ doTestJtaTransactionCommitWithJtaTm(Status.STATUS_ACTIVE);
+ }
+
+ private void doTestJtaTransactionCommitWithJtaTm(int status) throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(status, 2);
+ if (status == Status.STATUS_NO_TRANSACTION) {
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ ut.commit();
+ utControl.setVoidCallable(1);
+ }
+
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockJtaTransaction transaction = new MockJtaTransaction();
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction, 6);
+
+ MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
+ final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
+ final MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ sf.getTransactionManager();
+ sfControl.setReturnValue(tm, 1);
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+
+ utControl.replay();
+ tmControl.replay();
+ sfControl.replay();
+ sessionControl.replay();
+
+ JtaTransactionManager ptm = new JtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ final List l = new ArrayList();
+ l.add("test");
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ try {
+ assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setExposeNativeSession(true);
+ List htl = ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session, sess);
+ return l;
+ }
+ });
+ ht = new HibernateTemplate(sf);
+ ht.setExposeNativeSession(true);
+ htl = ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session, sess);
+ return l;
+ }
+ });
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ sessionControl.verify();
+ sessionControl.reset();
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sessionControl.replay();
+ return htl;
+ }
+ catch (Error err) {
+ err.printStackTrace();
+ throw err;
+ }
+ }
+ });
+
+ assertTrue("Correct result list", result == l);
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testJtaTransactionWithFlushFailure() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ ut.rollback();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ final MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ JtaTransactionManager ptm = new JtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ final List l = new ArrayList();
+ l.add("test");
+ final HibernateException flushEx = new HibernateException("flush failure");
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+
+ try {
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ try {
+ assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setExposeNativeSession(true);
+ List htl = ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session, sess);
+ return l;
+ }
+ });
+ ht = new HibernateTemplate(sf);
+ ht.setExposeNativeSession(true);
+ htl = ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session, sess);
+ return l;
+ }
+ });
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ sessionControl.verify();
+ sessionControl.reset();
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO, 1);
+ session.flush();
+ sessionControl.setThrowable(flushEx);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sessionControl.replay();
+ return htl;
+ }
+ catch (Error err) {
+ err.printStackTrace();
+ throw err;
+ }
+ }
+ });
+ }
+ catch (DataAccessException ex) {
+ // expected
+ assertTrue(flushEx == ex.getCause());
+ }
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testJtaTransactionRollback() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ ut.rollback();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ final MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ JtaTransactionManager ptm = new JtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ final List l = new ArrayList();
+ l.add("test");
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ try {
+ assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ List htl = ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) {
+ return l;
+ }
+ });
+ status.setRollbackOnly();
+ sessionControl.verify();
+ sessionControl.reset();
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sessionControl.replay();
+ return htl;
+ }
+ catch (Error err) {
+ err.printStackTrace();
+ throw err;
+ }
+ }
+ });
+ assertTrue("Correct result list", result == l);
+
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ utControl.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testJtaTransactionCommitWithPreBound() throws Exception {
+ doTestJtaTransactionCommitWithPreBound(false, false, false);
+ }
+
+ public void testJtaTransactionCommitWithPreBoundAndReadOnly() throws Exception {
+ doTestJtaTransactionCommitWithPreBound(false, false, true);
+ }
+
+ public void testJtaTransactionCommitWithPreBoundAndFlushModeNever() throws Exception {
+ doTestJtaTransactionCommitWithPreBound(false, true, false);
+ }
+
+ public void testJtaTransactionCommitWithPreBoundAndFlushModeNeverAndReadOnly() throws Exception {
+ doTestJtaTransactionCommitWithPreBound(false, true, true);
+ }
+
+ public void testJtaTransactionCommitWithJtaTmAndPreBound() throws Exception {
+ doTestJtaTransactionCommitWithPreBound(true, false, false);
+ }
+
+ public void testJtaTransactionCommitWithJtaTmAndPreBoundAndReadOnly() throws Exception {
+ doTestJtaTransactionCommitWithPreBound(true, false, true);
+ }
+
+ public void testJtaTransactionCommitWithJtaTmAndPreBoundAndFlushModeNever() throws Exception {
+ doTestJtaTransactionCommitWithPreBound(true, true, false);
+ }
+
+ public void testJtaTransactionCommitWithJtaTmAndPreBoundAndFlushModeNeverAndReadOnly() throws Exception {
+ doTestJtaTransactionCommitWithPreBound(true, true, true);
+ }
+
+ protected void doTestJtaTransactionCommitWithPreBound(
+ boolean jtaTm, final boolean flushNever, final boolean readOnly) throws Exception {
+
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.commit();
+ utControl.setVoidCallable(1);
+
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ if (jtaTm) {
+ MockJtaTransaction transaction = new MockJtaTransaction();
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction, 1);
+ }
+
+ MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
+ final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
+ final MockControl sessionControl = MockControl.createControl(ExtendedSession.class);
+ final ExtendedSession session = (ExtendedSession) sessionControl.getMock();
+ sf.getTransactionManager();
+ sfControl.setReturnValue((jtaTm ? tm : null), 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 5);
+ session.getFlushMode();
+ if (flushNever) {
+ sessionControl.setReturnValue(FlushMode.NEVER, 1);
+ if (!readOnly) {
+ session.setFlushMode(FlushMode.AUTO);
+ sessionControl.setVoidCallable(1);
+ }
+ }
+ else {
+ sessionControl.setReturnValue(FlushMode.AUTO, 1);
+ }
+
+ utControl.replay();
+ tmControl.replay();
+ sfControl.replay();
+ sessionControl.replay();
+
+ TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
+ try {
+ JtaTransactionManager ptm = new JtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setReadOnly(readOnly);
+ final List l = new ArrayList();
+ l.add("test");
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ try {
+ assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setExposeNativeSession(true);
+ List htl = null;
+ for (int i = 0; i < 5; i++) {
+ htl = ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session, sess);
+ return l;
+ }
+ });
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ }
+ sessionControl.verify();
+ sessionControl.reset();
+ if (!readOnly) {
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ if (flushNever) {
+ session.setFlushMode(FlushMode.NEVER);
+ sessionControl.setVoidCallable(1);
+ }
+ }
+ session.afterTransactionCompletion(true, null);
+ sessionControl.setVoidCallable(1);
+ session.disconnect();
+ sessionControl.setReturnValue(null, 1);
+ sessionControl.replay();
+ return htl;
+ }
+ catch (Error err) {
+ err.printStackTrace();
+ throw err;
+ }
+ }
+ });
+
+ assertTrue("Correct result list", result == l);
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ }
+ finally {
+ TransactionSynchronizationManager.unbindResource(sf);
+ }
+
+ utControl.verify();
+ tmControl.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testJtaTransactionRollbackWithPreBound() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_MARKED_ROLLBACK, 2);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.setRollbackOnly();
+ utControl.setVoidCallable(1);
+ RollbackException rex = new RollbackException();
+ ut.commit();
+ utControl.setThrowable(rex, 1);
+ utControl.replay();
+
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ final MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 5);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
+ try {
+ JtaTransactionManager ptm = new JtaTransactionManager(ut);
+ final TransactionTemplate tt = new TransactionTemplate(ptm);
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ status.setRollbackOnly();
+ try {
+ assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setExposeNativeSession(true);
+ for (int i = 0; i < 5; i++) {
+ ht.execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session, sess);
+ return null;
+ }
+ });
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ }
+ sessionControl.verify();
+ sessionControl.reset();
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.disconnect();
+ sessionControl.setReturnValue(null, 1);
+ session.clear();
+ sessionControl.setVoidCallable(1);
+ sessionControl.replay();
+ }
+ catch (Error err) {
+ err.printStackTrace();
+ throw err;
+ }
+ }
+ });
+ }
+ });
+ fail("Should have thrown UnexpectedRollbackException");
+ }
+ catch (UnexpectedRollbackException ex) {
+ // expected
+ assertEquals(rex, ex.getCause());
+ }
+ finally {
+ TransactionSynchronizationManager.unbindResource(sf);
+ }
+
+ utControl.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testJtaTransactionCommitWithRequiresNew() throws Exception {
+ doTestJtaTransactionWithRequiresNew(false);
+ }
+
+ public void testJtaTransactionRollbackWithRequiresNew() throws Exception {
+ doTestJtaTransactionWithRequiresNew(true);
+ }
+
+ protected void doTestJtaTransactionWithRequiresNew(final boolean rollback) throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockControl tx1Control = MockControl.createControl(javax.transaction.Transaction.class);
+ javax.transaction.Transaction tx1 = (javax.transaction.Transaction) tx1Control.getMock();
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl session1Control = MockControl.createControl(Session.class);
+ final Session session1 = (Session) session1Control.getMock();
+ MockControl session2Control = MockControl.createControl(Session.class);
+ final Session session2 = (Session) session2Control.getMock();
+
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 3);
+ ut.begin();
+ utControl.setVoidCallable(2);
+ tm.suspend();
+ tmControl.setReturnValue(tx1, 1);
+ tm.resume(tx1);
+ tmControl.setVoidCallable(1);
+ if (rollback) {
+ ut.rollback();
+ }
+ else {
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.commit();
+ }
+ utControl.setVoidCallable(2);
+
+ sf.openSession();
+ sfControl.setReturnValue(session1, 1);
+ sf.openSession();
+ sfControl.setReturnValue(session2, 1);
+ session1.getSessionFactory();
+ session1Control.setReturnValue(sf, 1);
+ session2.getSessionFactory();
+ session2Control.setReturnValue(sf, 1);
+ session1.isOpen();
+ session1Control.setReturnValue(true, 1);
+ session2.isOpen();
+ session2Control.setReturnValue(true, 1);
+ session2.getFlushMode();
+ session2Control.setReturnValue(FlushMode.AUTO, 1);
+ if (!rollback) {
+ session1.getFlushMode();
+ session1Control.setReturnValue(FlushMode.AUTO, 1);
+ session2.getFlushMode();
+ session2Control.setReturnValue(FlushMode.AUTO, 1);
+ session1.flush();
+ session1Control.setVoidCallable(1);
+ session2.flush();
+ session2Control.setVoidCallable(2);
+ }
+ session1.disconnect();
+ session1Control.setReturnValue(null, 1);
+ session1.close();
+ session1Control.setReturnValue(null, 1);
+ session2.close();
+ session2Control.setReturnValue(null, 1);
+
+ utControl.replay();
+ tmControl.replay();
+ sfControl.replay();
+ session1Control.replay();
+ session2Control.replay();
+
+ JtaTransactionManager ptm = new JtaTransactionManager();
+ ptm.setUserTransaction(ut);
+ ptm.setTransactionManager(tm);
+ final TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ try {
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ org.hibernate.Session outerSession = SessionFactoryUtils.getSession(sf, false);
+ assertSame(session1, outerSession);
+ SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sf);
+ assertTrue("Has thread session", holder != null);
+ try {
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ org.hibernate.Session innerSession = SessionFactoryUtils.getSession(sf, false);
+ assertSame(session2, innerSession);
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setFlushMode(HibernateTemplate.FLUSH_EAGER);
+ return ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session innerSession) {
+ if (rollback) {
+ throw new HibernateException("");
+ }
+ return null;
+ }
+ });
+ }
+ });
+ return null;
+ }
+ finally {
+ assertTrue("Same thread session as before", outerSession == SessionFactoryUtils.getSession(sf, false));
+ }
+ }
+ });
+ if (rollback) {
+ fail("Should have thrown DataAccessException");
+ }
+ }
+ catch (DataAccessException ex) {
+ if (!rollback) {
+ throw ex;
+ }
+ }
+ finally {
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ }
+
+ utControl.verify();
+ tmControl.verify();
+ sfControl.verify();
+ session1Control.verify();
+ session2Control.verify();
+ }
+
+ public void testJtaTransactionWithRequiresNewAndSuspendException() throws Exception {
+ doTestJtaTransactionWithRequiresNewAndException(true);
+ }
+
+ public void testJtaTransactionWithRequiresNewAndBeginException() throws Exception {
+ doTestJtaTransactionWithRequiresNewAndException(false);
+ }
+
+ protected void doTestJtaTransactionWithRequiresNewAndException(boolean suspendException) throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockControl txControl = MockControl.createControl(javax.transaction.Transaction.class);
+ javax.transaction.Transaction tx = (javax.transaction.Transaction) txControl.getMock();
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl session1Control = MockControl.createControl(Session.class);
+ final Session session1 = (Session) session1Control.getMock();
+
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ if (suspendException) {
+ tm.suspend();
+ tmControl.setThrowable(new SystemException(), 1);
+ }
+ else {
+ tm.suspend();
+ tmControl.setReturnValue(tx, 1);
+ ut.begin();
+ utControl.setThrowable(new SystemException(), 1);
+ tm.resume(tx);
+ tmControl.setVoidCallable(1);
+ }
+ ut.rollback();
+ utControl.setVoidCallable(1);
+
+ sf.openSession();
+ sfControl.setReturnValue(session1, 1);
+ session1.getSessionFactory();
+ session1Control.setReturnValue(sf, 1);
+ session1.disconnect();
+ session1Control.setReturnValue(null, 1);
+ session1.close();
+ session1Control.setReturnValue(null, 1);
+
+ utControl.replay();
+ tmControl.replay();
+ sfControl.replay();
+ session1Control.replay();
+
+ JtaTransactionManager ptm = new JtaTransactionManager();
+ ptm.setUserTransaction(ut);
+ ptm.setTransactionManager(tm);
+ final TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ try {
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ org.hibernate.Session outerSession = SessionFactoryUtils.getSession(sf, false);
+ assertSame(session1, outerSession);
+ SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sf);
+ assertTrue("Has thread session", holder != null);
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ return null;
+ }
+ });
+ return null;
+ }
+ });
+ fail("Should have thrown TransactionException");
+ }
+ catch (TransactionException ex) {
+ // expected
+ }
+ finally {
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ }
+
+ utControl.verify();
+ tmControl.verify();
+ sfControl.verify();
+ session1Control.verify();
+ }
+
+ public void testJtaTransactionCommitWithRequiresNewAndJtaTm() throws Exception {
+ doTestJtaTransactionWithRequiresNewAndJtaTm(false);
+ }
+
+ public void testJtaTransactionRollbackWithRequiresNewAndJtaTm() throws Exception {
+ doTestJtaTransactionWithRequiresNewAndJtaTm(true);
+ }
+
+ protected void doTestJtaTransactionWithRequiresNewAndJtaTm(final boolean rollback) throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockControl tx1Control = MockControl.createControl(javax.transaction.Transaction.class);
+ javax.transaction.Transaction tx1 = (javax.transaction.Transaction) tx1Control.getMock();
+ MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
+ final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
+ MockControl session1Control = MockControl.createControl(Session.class);
+ final Session session1 = (Session) session1Control.getMock();
+ MockControl session2Control = MockControl.createControl(Session.class);
+ final Session session2 = (Session) session2Control.getMock();
+
+ MockJtaTransaction transaction1 = new MockJtaTransaction();
+ MockJtaTransaction transaction2 = new MockJtaTransaction();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 3);
+ ut.begin();
+ utControl.setVoidCallable(2);
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction1, 1);
+ tm.suspend();
+ tmControl.setReturnValue(tx1, 1);
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction2, 1);
+ tm.resume(tx1);
+ tmControl.setVoidCallable(1);
+ if (rollback) {
+ ut.rollback();
+ }
+ else {
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.commit();
+ }
+ utControl.setVoidCallable(2);
+
+ sf.getTransactionManager();
+ sfControl.setReturnValue(tm, 2);
+ sf.openSession();
+ sfControl.setReturnValue(session1, 1);
+ sf.openSession();
+ sfControl.setReturnValue(session2, 1);
+ session1.isOpen();
+ session1Control.setReturnValue(true, 1);
+ session2.isOpen();
+ session2Control.setReturnValue(true, 1);
+ session2.getFlushMode();
+ session2Control.setReturnValue(FlushMode.AUTO, 1);
+ if (!rollback) {
+ session1.getFlushMode();
+ session1Control.setReturnValue(FlushMode.AUTO, 1);
+ session2.getFlushMode();
+ session2Control.setReturnValue(FlushMode.AUTO, 1);
+ session1.flush();
+ session1Control.setVoidCallable(1);
+ session2.flush();
+ session2Control.setVoidCallable(2);
+ }
+ session1.disconnect();
+ session1Control.setReturnValue(null, 1);
+ session1.close();
+ session1Control.setReturnValue(null, 1);
+ session2.close();
+ session2Control.setReturnValue(null, 1);
+
+ utControl.replay();
+ tmControl.replay();
+ sfControl.replay();
+ session1Control.replay();
+ session2Control.replay();
+
+ JtaTransactionManager ptm = new JtaTransactionManager();
+ ptm.setUserTransaction(ut);
+ ptm.setTransactionManager(tm);
+ final TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ try {
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ org.hibernate.Session outerSession = SessionFactoryUtils.getSession(sf, false);
+ assertSame(session1, outerSession);
+ SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sf);
+ assertTrue("Has thread session", holder != null);
+ try {
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ org.hibernate.Session innerSession = SessionFactoryUtils.getSession(sf, false);
+ assertSame(session2, innerSession);
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setFlushMode(HibernateTemplate.FLUSH_EAGER);
+ return ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session innerSession) {
+ if (rollback) {
+ throw new HibernateException("");
+ }
+ return null;
+ }
+ });
+ }
+ });
+ return null;
+ }
+ finally {
+ assertTrue("Same thread session as before", outerSession == SessionFactoryUtils.getSession(sf, false));
+ }
+ }
+ });
+ if (rollback) {
+ fail("Should have thrown DataAccessException");
+ }
+ }
+ catch (DataAccessException ex) {
+ if (!rollback) {
+ throw ex;
+ }
+ }
+ finally {
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ }
+
+ utControl.verify();
+ tmControl.verify();
+ sfControl.verify();
+ session1Control.verify();
+ session2Control.verify();
+ }
+
+ public void testTransactionWithPropagationSupports() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ ut.rollback();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.NEVER, 1);
+ session.setFlushMode(FlushMode.AUTO);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.setFlushMode(FlushMode.NEVER);
+ sessionControl.setVoidCallable(1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.NEVER, 1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ JtaTransactionManager tm = new JtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("Is not new transaction", !status.isNewTransaction());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setFlushMode(HibernateTemplate.FLUSH_EAGER);
+ ht.execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) {
+ return null;
+ }
+ });
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ return null;
+ }
+ });
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testTransactionWithPropagationSupportsAndInnerTransaction() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ ut.rollback();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO, 3);
+ session.flush();
+ sessionControl.setVoidCallable(3);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ JtaTransactionManager tm = new JtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
+ final TransactionTemplate tt2 = new TransactionTemplate(tm);
+ tt2.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("Is not new transaction", !status.isNewTransaction());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setFlushMode(HibernateTemplate.FLUSH_EAGER);
+ ht.execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) {
+ return null;
+ }
+ });
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ tt2.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setFlushMode(HibernateTemplate.FLUSH_EAGER);
+ return ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) {
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ //assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ return null;
+ }
+ });
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ return null;
+ }
+ });
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testJtaSessionSynchronization() throws Exception {
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockJtaTransaction transaction = new MockJtaTransaction();
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction, 6);
+
+ MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
+ final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
+ final MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ sf.getTransactionManager();
+ sfControl.setReturnValue(tm, 6);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 4);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+
+ tmControl.replay();
+ sfControl.replay();
+ sessionControl.replay();
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setExposeNativeSession(true);
+ for (int i = 0; i < 5; i++) {
+ ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session, sess);
+ return null;
+ }
+ });
+ }
+
+ Synchronization synchronization = transaction.getSynchronization();
+ assertTrue("JTA synchronization registered", synchronization != null);
+ synchronization.beforeCompletion();
+ synchronization.afterCompletion(Status.STATUS_COMMITTED);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tmControl.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testJtaSessionSynchronizationWithRollback() throws Exception {
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockJtaTransaction transaction = new MockJtaTransaction();
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction, 6);
+
+ MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
+ final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
+ final MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ sf.getTransactionManager();
+ sfControl.setReturnValue(tm, 6);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 4);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+
+ tmControl.replay();
+ sfControl.replay();
+ sessionControl.replay();
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setExposeNativeSession(true);
+ for (int i = 0; i < 5; i++) {
+ ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session, sess);
+ return null;
+ }
+ });
+ }
+
+ Synchronization synchronization = transaction.getSynchronization();
+ assertTrue("JTA synchronization registered", synchronization != null);
+ synchronization.afterCompletion(Status.STATUS_ROLLEDBACK);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tmControl.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testJtaSessionSynchronizationWithRollbackByOtherThread() throws Exception {
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockJtaTransaction transaction = new MockJtaTransaction();
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction, 7);
+ tm.getStatus();
+ tmControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+
+ MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
+ final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
+ final MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ sf.openSession();
+ sfControl.setReturnValue(session, 2);
+ sf.getTransactionManager();
+ sfControl.setReturnValue(tm, 7);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 8);
+ session.setFlushMode(FlushMode.NEVER);
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 2);
+
+ tmControl.replay();
+ sfControl.replay();
+ sessionControl.replay();
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ final HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setExposeNativeSession(true);
+ for (int i = 0; i < 5; i++) {
+ ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session, sess);
+ return null;
+ }
+ });
+ }
+
+ final Synchronization synchronization = transaction.getSynchronization();
+ assertTrue("JTA synchronization registered", synchronization != null);
+ Thread thread = new Thread() {
+ public void run() {
+ synchronization.afterCompletion(Status.STATUS_ROLLEDBACK);
+ }
+ };
+ thread.start();
+ thread.join();
+
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ TransactionTemplate tt = new TransactionTemplate(new JtaTransactionManager(tm));
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
+ tt.setReadOnly(true);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
+ for (int i = 0; i < 5; i++) {
+ ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session, sess);
+ return null;
+ }
+ });
+ }
+ }
+ });
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tmControl.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testJtaSessionSynchronizationWithFlushFailure() throws Exception {
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockJtaTransaction transaction = new MockJtaTransaction();
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction, 6);
+ tm.setRollbackOnly();
+ tmControl.setVoidCallable(1);
+
+ final HibernateException flushEx = new HibernateException("flush failure");
+ MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
+ final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
+ final MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ sf.getTransactionManager();
+ sfControl.setReturnValue(tm, 6);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 4);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO, 1);
+ session.flush();
+ sessionControl.setThrowable(flushEx, 1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+
+ tmControl.replay();
+ sfControl.replay();
+ sessionControl.replay();
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setExposeNativeSession(true);
+ for (int i = 0; i < 5; i++) {
+ ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session, sess);
+ return null;
+ }
+ });
+ }
+
+ Synchronization synchronization = transaction.getSynchronization();
+ assertTrue("JTA synchronization registered", synchronization != null);
+ try {
+ synchronization.beforeCompletion();
+ fail("Should have thrown HibernateSystemException");
+ }
+ catch (HibernateSystemException ex) {
+ assertSame(flushEx, ex.getCause());
+ }
+ synchronization.afterCompletion(Status.STATUS_ROLLEDBACK);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tmControl.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testJtaSessionSynchronizationWithSuspendedTransaction() throws Exception {
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockJtaTransaction transaction1 = new MockJtaTransaction();
+ MockJtaTransaction transaction2 = new MockJtaTransaction();
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction1, 2);
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction2, 3);
+
+ MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
+ final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
+ final MockControl session1Control = MockControl.createControl(Session.class);
+ final Session session1 = (Session) session1Control.getMock();
+ final MockControl session2Control = MockControl.createControl(Session.class);
+ final Session session2 = (Session) session2Control.getMock();
+ sf.openSession();
+ sfControl.setReturnValue(session1, 1);
+ sf.openSession();
+ sfControl.setReturnValue(session2, 1);
+ sf.getTransactionManager();
+ sfControl.setReturnValue(tm, 5);
+ session1.getFlushMode();
+ session1Control.setReturnValue(FlushMode.AUTO, 1);
+ session2.getFlushMode();
+ session2Control.setReturnValue(FlushMode.AUTO, 1);
+ session1.flush();
+ session1Control.setVoidCallable(1);
+ session2.flush();
+ session2Control.setVoidCallable(1);
+ session1.close();
+ session1Control.setReturnValue(null, 1);
+ session2.close();
+ session2Control.setReturnValue(null, 1);
+
+ tmControl.replay();
+ sfControl.replay();
+ session1Control.replay();
+ session2Control.replay();
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setExposeNativeSession(true);
+ ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session1, sess);
+ return null;
+ }
+ });
+ ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session2, sess);
+ return null;
+ }
+ });
+
+ Synchronization synchronization2 = transaction2.getSynchronization();
+ assertTrue("JTA synchronization registered", synchronization2 != null);
+ synchronization2.beforeCompletion();
+ synchronization2.afterCompletion(Status.STATUS_COMMITTED);
+
+ Synchronization synchronization1 = transaction1.getSynchronization();
+ assertTrue("JTA synchronization registered", synchronization1 != null);
+ synchronization1.beforeCompletion();
+ synchronization1.afterCompletion(Status.STATUS_COMMITTED);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tmControl.verify();
+ sfControl.verify();
+ session1Control.verify();
+ session2Control.verify();
+ }
+
+ public void testJtaSessionSynchronizationWithNonSessionFactoryImplementor() throws Exception {
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockJtaTransaction transaction = new MockJtaTransaction();
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction, 6);
+
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ final MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ MockControl sfiControl = MockControl.createControl(SessionFactoryImplementor.class);
+ final SessionFactoryImplementor sfi = (SessionFactoryImplementor) sfiControl.getMock();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sfi, 6);
+ sfi.getTransactionManager();
+ sfiControl.setReturnValue(tm, 6);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 4);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+
+ tmControl.replay();
+ sfControl.replay();
+ sessionControl.replay();
+ sfiControl.replay();
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setExposeNativeSession(true);
+ for (int i = 0; i < 5; i++) {
+ ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session, sess);
+ return null;
+ }
+ });
+ }
+
+ Synchronization synchronization = transaction.getSynchronization();
+ assertTrue("JTA Synchronization registered", synchronization != null);
+ synchronization.beforeCompletion();
+ synchronization.afterCompletion(Status.STATUS_COMMITTED);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tmControl.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ sfiControl.verify();
+ }
+
+ public void testJtaSessionSynchronizationWithSpringTransactionLaterOn() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockJtaTransaction transaction = new MockJtaTransaction();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction, 6);
+
+ MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
+ final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
+ final MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ sf.getTransactionManager();
+ sfControl.setReturnValue(tm, 6);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 4);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+
+ utControl.replay();
+ tmControl.replay();
+ sfControl.replay();
+ sessionControl.replay();
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ final HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setExposeNativeSession(true);
+ for (int i = 0; i < 2; i++) {
+ ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session, sess);
+ return null;
+ }
+ });
+ }
+
+ TransactionTemplate tt = new TransactionTemplate(new JtaTransactionManager(ut));
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ for (int i = 2; i < 5; i++) {
+ ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session, sess);
+ return null;
+ }
+ });
+ }
+ }
+ });
+
+ Synchronization synchronization = transaction.getSynchronization();
+ assertTrue("JTA synchronization registered", synchronization != null);
+ synchronization.beforeCompletion();
+ synchronization.afterCompletion(Status.STATUS_COMMITTED);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ tmControl.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testJtaSessionSynchronizationWithPreBound() throws Exception {
+ doTestJtaSessionSynchronizationWithPreBound(false);
+ }
+
+ public void testJtaJtaSessionSynchronizationWithPreBoundAndFlushNever() throws Exception {
+ doTestJtaSessionSynchronizationWithPreBound(true);
+ }
+
+ private void doTestJtaSessionSynchronizationWithPreBound(boolean flushNever) throws Exception {
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockJtaTransaction transaction = new MockJtaTransaction();
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction, 6);
+
+ MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
+ final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
+ final MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ sf.getTransactionManager();
+ sfControl.setReturnValue(tm, 6);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 5);
+ session.getFlushMode();
+ if (flushNever) {
+ sessionControl.setReturnValue(FlushMode.NEVER, 1);
+ session.setFlushMode(FlushMode.AUTO);
+ sessionControl.setVoidCallable(1);
+ }
+ else {
+ sessionControl.setReturnValue(FlushMode.AUTO, 1);
+ }
+
+ tmControl.replay();
+ sfControl.replay();
+ sessionControl.replay();
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
+ try {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setExposeNativeSession(true);
+ for (int i = 0; i < 5; i++) {
+ ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session, sess);
+ return null;
+ }
+ });
+ }
+
+ sessionControl.verify();
+ sessionControl.reset();
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ if (flushNever) {
+ session.setFlushMode(FlushMode.NEVER);
+ sessionControl.setVoidCallable(1);
+ }
+ session.disconnect();
+ sessionControl.setReturnValue(null, 1);
+ sessionControl.replay();
+
+ Synchronization synchronization = transaction.getSynchronization();
+ assertTrue("JTA synchronization registered", synchronization != null);
+ synchronization.beforeCompletion();
+ synchronization.afterCompletion(Status.STATUS_COMMITTED);
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ }
+ finally {
+ TransactionSynchronizationManager.unbindResource(sf);
+ }
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+
+ tmControl.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testJtaSessionSynchronizationWithRemoteTransaction() throws Exception {
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockJtaTransaction transaction = new MockJtaTransaction();
+
+ MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
+ final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
+ final MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+
+ for (int j = 0; j < 2; j++) {
+ tmControl.reset();
+ sfControl.reset();
+ sessionControl.reset();
+
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction, 6);
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ sf.getTransactionManager();
+ sfControl.setReturnValue(tm, 6);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 4);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+
+ tmControl.replay();
+ sfControl.replay();
+ sessionControl.replay();
+
+ if (j == 0) {
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ }
+ else {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ }
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setExposeNativeSession(true);
+ for (int i = 0; i < 5; i++) {
+ ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session, sess);
+ return null;
+ }
+ });
+ }
+
+ final Synchronization synchronization = transaction.getSynchronization();
+ assertTrue("JTA synchronization registered", synchronization != null);
+
+ // Call synchronization in a new thread, to simulate a synchronization
+ // triggered by a new remote call from a remote transaction coordinator.
+ Thread synch = new Thread() {
+ public void run() {
+ synchronization.beforeCompletion();
+ synchronization.afterCompletion(Status.STATUS_COMMITTED);
+ }
+ };
+ synch.start();
+ synch.join();
+
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sf);
+ assertTrue("Thread session holder empty", sessionHolder.isEmpty());
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tmControl.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ TransactionSynchronizationManager.unbindResource(sf);
+ }
+
+ protected void tearDown() {
+ assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ }
+
+
+ /**
+ * Interface that combines Hibernate's Session and SessionImplementor interface.
+ * Necessary for creating a mock that implements both interfaces.
+ * Note: Hibernate 3.1's SessionImplementor interface does not extend Session anymore.
+ */
+ public static interface ExtendedSession extends Session, SessionImplementor {
+
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/HibernateTemplateTests.java b/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/HibernateTemplateTests.java
new file mode 100644
index 00000000000..2bd94fe8961
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/HibernateTemplateTests.java
@@ -0,0 +1,2587 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.orm.hibernate3;
+
+import java.lang.reflect.Proxy;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+import org.hibernate.Criteria;
+import org.hibernate.Filter;
+import org.hibernate.FlushMode;
+import org.hibernate.HibernateException;
+import org.hibernate.Interceptor;
+import org.hibernate.JDBCException;
+import org.hibernate.LockMode;
+import org.hibernate.NonUniqueResultException;
+import org.hibernate.ObjectDeletedException;
+import org.hibernate.ObjectNotFoundException;
+import org.hibernate.PersistentObjectException;
+import org.hibernate.PropertyValueException;
+import org.hibernate.Query;
+import org.hibernate.QueryException;
+import org.hibernate.ReplicationMode;
+import org.hibernate.SessionFactory;
+import org.hibernate.StaleObjectStateException;
+import org.hibernate.StaleStateException;
+import org.hibernate.TransientObjectException;
+import org.hibernate.UnresolvableObjectException;
+import org.hibernate.WrongClassException;
+import org.hibernate.classic.Session;
+import org.hibernate.exception.ConstraintViolationException;
+import org.hibernate.exception.DataException;
+import org.hibernate.exception.GenericJDBCException;
+import org.hibernate.exception.JDBCConnectionException;
+import org.hibernate.exception.LockAcquisitionException;
+import org.hibernate.exception.SQLGrammarException;
+
+import org.springframework.beans.TestBean;
+import org.springframework.dao.CannotAcquireLockException;
+import org.springframework.dao.DataAccessResourceFailureException;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.dao.IncorrectResultSizeDataAccessException;
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+import org.springframework.dao.InvalidDataAccessResourceUsageException;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+
+/**
+ * @author Juergen Hoeller
+ * @since 05.03.2005
+ */
+public class HibernateTemplateTests extends TestCase {
+
+ private MockControl sfControl;
+ private SessionFactory sf;
+ private MockControl sessionControl;
+ private Session session;
+
+ protected void setUp() {
+ sfControl = MockControl.createControl(SessionFactory.class);
+ sf = (SessionFactory) sfControl.getMock();
+ sessionControl = MockControl.createControl(Session.class);
+ session = (Session) sessionControl.getMock();
+ }
+
+ public void testExecuteWithNewSession() throws HibernateException {
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ assertTrue("Correct allowCreate default", ht.isAllowCreate());
+ assertTrue("Correct flushMode default", ht.getFlushMode() == HibernateTemplate.FLUSH_AUTO);
+ final List l = new ArrayList();
+ l.add("test");
+ List result = ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ return l;
+ }
+ });
+ assertTrue("Correct result list", result == l);
+ }
+
+ public void testExecuteWithNewSessionAndFlushNever() throws HibernateException {
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.setFlushMode(FlushMode.NEVER);
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setFlushMode(HibernateTemplate.FLUSH_NEVER);
+ final List l = new ArrayList();
+ l.add("test");
+ List result = ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ return l;
+ }
+ });
+ assertTrue("Correct result list", result == l);
+ }
+
+ public void testExecuteWithNewSessionAndFilter() throws HibernateException {
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.enableFilter("myFilter");
+ sessionControl.setReturnValue(null, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setFilterName("myFilter");
+ final List l = new ArrayList();
+ l.add("test");
+ List result = ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ return l;
+ }
+ });
+ assertTrue("Correct result list", result == l);
+ }
+
+ public void testExecuteWithNewSessionAndFilters() throws HibernateException {
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.enableFilter("myFilter");
+ sessionControl.setReturnValue(null, 1);
+ session.enableFilter("yourFilter");
+ sessionControl.setReturnValue(null, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setFilterNames(new String[] {"myFilter", "yourFilter"});
+ final List l = new ArrayList();
+ l.add("test");
+ List result = ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ return l;
+ }
+ });
+ assertTrue("Correct result list", result == l);
+ }
+
+ public void testExecuteWithNotAllowCreate() {
+ sf.getCurrentSession();
+ sfControl.setThrowable(new HibernateException(""));
+ sfControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate();
+ ht.setSessionFactory(sf);
+ ht.setAllowCreate(false);
+ try {
+ ht.execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ return null;
+ }
+ });
+ fail("Should have thrown DataAccessException");
+ }
+ catch (DataAccessResourceFailureException ex) {
+ // expected
+ }
+ }
+
+ public void testExecuteWithNotAllowCreateAndThreadBound() {
+ sf.getCurrentSession();
+ sfControl.setReturnValue(session);
+ sfControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setAllowCreate(false);
+
+ final List l = new ArrayList();
+ l.add("test");
+ List result = ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ return l;
+ }
+ });
+ assertTrue("Correct result list", result == l);
+ }
+
+ public void testExecuteWithThreadBoundAndFlushEager() throws HibernateException {
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setFlushModeName("FLUSH_EAGER");
+
+ TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
+ try {
+ final List l = new ArrayList();
+ l.add("test");
+ List result = ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ return l;
+ }
+ });
+ assertTrue("Correct result list", result == l);
+ }
+ finally {
+ TransactionSynchronizationManager.unbindResource(sf);
+ }
+ }
+
+ public void testExecuteWithThreadBoundAndFilter() {
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.enableFilter("myFilter");
+ sessionControl.setReturnValue(null, 1);
+ session.disableFilter("myFilter");
+ sessionControl.setVoidCallable(1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setFilterName("myFilter");
+
+ TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
+ try {
+ final List l = new ArrayList();
+ l.add("test");
+ List result = ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ return l;
+ }
+ });
+ assertTrue("Correct result list", result == l);
+ }
+ finally {
+ TransactionSynchronizationManager.unbindResource(sf);
+ }
+ }
+
+ public void testExecuteWithThreadBoundAndFilters() {
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.enableFilter("myFilter");
+ sessionControl.setReturnValue(null, 1);
+ session.enableFilter("yourFilter");
+ sessionControl.setReturnValue(null, 1);
+ session.disableFilter("myFilter");
+ sessionControl.setVoidCallable(1);
+ session.disableFilter("yourFilter");
+ sessionControl.setVoidCallable(1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setFilterNames(new String[] {"myFilter", "yourFilter"});
+
+ TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
+ try {
+ final List l = new ArrayList();
+ l.add("test");
+ List result = ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ return l;
+ }
+ });
+ assertTrue("Correct result list", result == l);
+ }
+ finally {
+ TransactionSynchronizationManager.unbindResource(sf);
+ }
+ }
+
+ public void testExecuteWithThreadBoundAndParameterizedFilter() {
+ MockControl filterControl = MockControl.createControl(Filter.class);
+ Filter filter = (Filter) filterControl.getMock();
+
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.getEnabledFilter("myFilter");
+ sessionControl.setReturnValue(null, 1);
+ session.enableFilter("myFilter");
+ sessionControl.setReturnValue(filter, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setAllowCreate(false);
+ ht.setFilterName("myFilter");
+
+ TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
+ try {
+ final List l = new ArrayList();
+ l.add("test");
+ Filter f = ht.enableFilter("myFilter");
+ assertTrue("Correct filter", f == filter);
+ }
+ finally {
+ TransactionSynchronizationManager.unbindResource(sf);
+ }
+ }
+
+ public void testExecuteWithThreadBoundAndParameterizedExistingFilter() {
+ MockControl filterControl = MockControl.createControl(Filter.class);
+ Filter filter = (Filter) filterControl.getMock();
+
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.getEnabledFilter("myFilter");
+ sessionControl.setReturnValue(filter, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setAllowCreate(false);
+ ht.setFilterName("myFilter");
+
+ TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
+ try {
+ final List l = new ArrayList();
+ l.add("test");
+ Filter f = ht.enableFilter("myFilter");
+ assertTrue("Correct filter", f == filter);
+ }
+ finally {
+ TransactionSynchronizationManager.unbindResource(sf);
+ }
+ }
+
+ public void testExecuteWithThreadBoundAndNewSession() throws HibernateException {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl session2Control = MockControl.createControl(Session.class);
+ Session session2 = (Session) session2Control.getMock();
+
+ session2.connection();
+ session2Control.setReturnValue(con, 1);
+ sf.openSession(con);
+ sfControl.setReturnValue(session, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ session2Control.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setAlwaysUseNewSession(true);
+
+ TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session2));
+ try {
+ final List l = new ArrayList();
+ l.add("test");
+ List result = ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ return l;
+ }
+ });
+ assertTrue("Correct result list", result == l);
+ }
+ finally {
+ TransactionSynchronizationManager.unbindResource(sf);
+ }
+ }
+
+ public void testExecuteWithThreadBoundAndNewSessionAndEntityInterceptor() throws HibernateException {
+ MockControl interceptorControl = MockControl.createControl(org.hibernate.Interceptor.class);
+ Interceptor entityInterceptor = (Interceptor) interceptorControl.getMock();
+
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl session2Control = MockControl.createControl(Session.class);
+ Session session2 = (Session) session2Control.getMock();
+
+ session2.connection();
+ session2Control.setReturnValue(con, 1);
+ sf.openSession(con, entityInterceptor);
+ sfControl.setReturnValue(session, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ session2Control.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setAlwaysUseNewSession(true);
+ ht.setEntityInterceptor(entityInterceptor);
+
+ TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session2));
+ try {
+ final List l = new ArrayList();
+ l.add("test");
+ List result = ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ return l;
+ }
+ });
+ assertTrue("Correct result list", result == l);
+ }
+ finally {
+ TransactionSynchronizationManager.unbindResource(sf);
+ }
+ }
+
+ public void testExecuteWithEntityInterceptor() throws HibernateException {
+ MockControl interceptorControl = MockControl.createControl(org.hibernate.Interceptor.class);
+ Interceptor entityInterceptor = (Interceptor) interceptorControl.getMock();
+
+ sf.openSession(entityInterceptor);
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setEntityInterceptor(entityInterceptor);
+ final List l = new ArrayList();
+ l.add("test");
+ List result = ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ return l;
+ }
+ });
+ assertTrue("Correct result list", result == l);
+ }
+
+ public void testExecuteWithCacheQueries() throws HibernateException {
+ MockControl query1Control = MockControl.createControl(Query.class);
+ Query query1 = (Query) query1Control.getMock();
+ MockControl query2Control = MockControl.createControl(Query.class);
+ Query query2 = (Query) query2Control.getMock();
+ MockControl criteriaControl = MockControl.createControl(Criteria.class);
+ Criteria criteria = (Criteria) criteriaControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.createQuery("some query");
+ sessionControl.setReturnValue(query1);
+ query1.setCacheable(true);
+ query1Control.setReturnValue(query1, 1);
+ session.getNamedQuery("some query name");
+ sessionControl.setReturnValue(query2);
+ query2.setCacheable(true);
+ query2Control.setReturnValue(query2, 1);
+ session.createCriteria(TestBean.class);
+ sessionControl.setReturnValue(criteria, 1);
+ criteria.setCacheable(true);
+ criteriaControl.setReturnValue(criteria, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ query1Control.replay();
+ query2Control.replay();
+ criteriaControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setCacheQueries(true);
+ ht.execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) throws HibernateException {
+ assertNotSame(session, sess);
+ assertTrue(Proxy.isProxyClass(sess.getClass()));
+ sess.createQuery("some query");
+ sess.getNamedQuery("some query name");
+ sess.createCriteria(TestBean.class);
+ // should be ignored
+ sess.close();
+ return null;
+ }
+ });
+
+ query1Control.verify();
+ query2Control.verify();
+ criteriaControl.verify();
+ }
+
+ public void testExecuteWithCacheQueriesAndCacheRegion() throws HibernateException {
+ MockControl query1Control = MockControl.createControl(Query.class);
+ Query query1 = (Query) query1Control.getMock();
+ MockControl query2Control = MockControl.createControl(Query.class);
+ Query query2 = (Query) query2Control.getMock();
+ MockControl criteriaControl = MockControl.createControl(Criteria.class);
+ Criteria criteria = (Criteria) criteriaControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.createQuery("some query");
+ sessionControl.setReturnValue(query1);
+ query1.setCacheable(true);
+ query1Control.setReturnValue(query1, 1);
+ query1.setCacheRegion("myRegion");
+ query1Control.setReturnValue(query1, 1);
+ session.getNamedQuery("some query name");
+ sessionControl.setReturnValue(query2);
+ query2.setCacheable(true);
+ query2Control.setReturnValue(query2, 1);
+ query2.setCacheRegion("myRegion");
+ query2Control.setReturnValue(query2, 1);
+ session.createCriteria(TestBean.class);
+ sessionControl.setReturnValue(criteria, 1);
+ criteria.setCacheable(true);
+ criteriaControl.setReturnValue(criteria, 1);
+ criteria.setCacheRegion("myRegion");
+ criteriaControl.setReturnValue(criteria, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ query1Control.replay();
+ query2Control.replay();
+ criteriaControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setCacheQueries(true);
+ ht.setQueryCacheRegion("myRegion");
+ ht.execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) throws HibernateException {
+ assertNotSame(session, sess);
+ assertTrue(Proxy.isProxyClass(sess.getClass()));
+ sess.createQuery("some query");
+ sess.getNamedQuery("some query name");
+ sess.createCriteria(TestBean.class);
+ // should be ignored
+ sess.close();
+ return null;
+ }
+ });
+
+ query1Control.verify();
+ query2Control.verify();
+ criteriaControl.verify();
+ }
+
+ public void testExecuteWithCacheQueriesAndCacheRegionAndNativeSession() throws HibernateException {
+ MockControl query1Control = MockControl.createControl(Query.class);
+ Query query1 = (Query) query1Control.getMock();
+ MockControl query2Control = MockControl.createControl(Query.class);
+ Query query2 = (Query) query2Control.getMock();
+ MockControl criteriaControl = MockControl.createControl(Criteria.class);
+ Criteria criteria = (Criteria) criteriaControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.createQuery("some query");
+ sessionControl.setReturnValue(query1);
+ session.getNamedQuery("some query name");
+ sessionControl.setReturnValue(query2);
+ session.createCriteria(TestBean.class);
+ sessionControl.setReturnValue(criteria, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ query1Control.replay();
+ query2Control.replay();
+ criteriaControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setExposeNativeSession(true);
+ ht.setCacheQueries(true);
+ ht.setQueryCacheRegion("myRegion");
+ ht.execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) throws HibernateException {
+ assertSame(session, sess);
+ sess.createQuery("some query");
+ sess.getNamedQuery("some query name");
+ sess.createCriteria(TestBean.class);
+ return null;
+ }
+ });
+
+ query1Control.verify();
+ query2Control.verify();
+ criteriaControl.verify();
+ }
+
+ public void testExecuteWithFetchSizeAndMaxResults() throws HibernateException {
+ MockControl query1Control = MockControl.createControl(Query.class);
+ Query query1 = (Query) query1Control.getMock();
+ MockControl query2Control = MockControl.createControl(Query.class);
+ Query query2 = (Query) query2Control.getMock();
+ MockControl criteriaControl = MockControl.createControl(Criteria.class);
+ Criteria criteria = (Criteria) criteriaControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.createQuery("some query");
+ sessionControl.setReturnValue(query1);
+ query1.setFetchSize(10);
+ query1Control.setReturnValue(query1, 1);
+ query1.setMaxResults(20);
+ query1Control.setReturnValue(query1, 1);
+ session.getNamedQuery("some query name");
+ sessionControl.setReturnValue(query2);
+ query2.setFetchSize(10);
+ query2Control.setReturnValue(query2, 1);
+ query2.setMaxResults(20);
+ query2Control.setReturnValue(query2, 1);
+ session.createCriteria(TestBean.class);
+ sessionControl.setReturnValue(criteria, 1);
+ criteria.setFetchSize(10);
+ criteriaControl.setReturnValue(criteria, 1);
+ criteria.setMaxResults(20);
+ criteriaControl.setReturnValue(criteria, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ query1Control.replay();
+ query2Control.replay();
+ criteriaControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setFetchSize(10);
+ ht.setMaxResults(20);
+ ht.execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) throws HibernateException {
+ sess.createQuery("some query");
+ sess.getNamedQuery("some query name");
+ sess.createCriteria(TestBean.class);
+ return null;
+ }
+ });
+
+ query1Control.verify();
+ query2Control.verify();
+ criteriaControl.verify();
+ }
+
+ public void testGet() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.get(TestBean.class, "");
+ sessionControl.setReturnValue(tb, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ Object result = ht.get(TestBean.class, "");
+ assertTrue("Correct result", result == tb);
+ }
+
+ public void testGetWithLockMode() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.get(TestBean.class, "", LockMode.UPGRADE_NOWAIT);
+ sessionControl.setReturnValue(tb, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ Object result = ht.get(TestBean.class, "", LockMode.UPGRADE_NOWAIT);
+ assertTrue("Correct result", result == tb);
+ }
+
+ public void testGetWithEntityName() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.get("myEntity", "");
+ sessionControl.setReturnValue(tb, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ Object result = ht.get("myEntity", "");
+ assertTrue("Correct result", result == tb);
+ }
+
+ public void testGetWithEntityNameAndLockMode() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.get("myEntity", "", LockMode.UPGRADE_NOWAIT);
+ sessionControl.setReturnValue(tb, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ Object result = ht.get("myEntity", "", LockMode.UPGRADE_NOWAIT);
+ assertTrue("Correct result", result == tb);
+ }
+
+ public void testLoad() throws HibernateException {
+ TestBean tb = new TestBean();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.load(TestBean.class, "");
+ sessionControl.setReturnValue(tb, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ Object result = ht.load(TestBean.class, "");
+ assertTrue("Correct result", result == tb);
+ }
+
+ public void testLoadWithNotFound() throws HibernateException {
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.load(TestBean.class, "id");
+ ObjectNotFoundException onfex = new ObjectNotFoundException("id", TestBean.class.getName());
+ sessionControl.setThrowable(onfex);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ try {
+ ht.load(TestBean.class, "id");
+ fail("Should have thrown HibernateObjectRetrievalFailureException");
+ }
+ catch (HibernateObjectRetrievalFailureException ex) {
+ // expected
+ assertEquals(TestBean.class.getName(), ex.getPersistentClassName());
+ assertEquals("id", ex.getIdentifier());
+ assertEquals(onfex, ex.getCause());
+ }
+ }
+
+ public void testLoadWithLockMode() throws HibernateException {
+ TestBean tb = new TestBean();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.load(TestBean.class, "", LockMode.UPGRADE);
+ sessionControl.setReturnValue(tb, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ Object result = ht.load(TestBean.class, "", LockMode.UPGRADE);
+ assertTrue("Correct result", result == tb);
+ }
+
+ public void testLoadWithEntityName() throws HibernateException {
+ TestBean tb = new TestBean();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.load("myEntity", "");
+ sessionControl.setReturnValue(tb, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ Object result = ht.load("myEntity", "");
+ assertTrue("Correct result", result == tb);
+ }
+
+ public void testLoadWithEntityNameLockMode() throws HibernateException {
+ TestBean tb = new TestBean();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.load("myEntity", "", LockMode.UPGRADE);
+ sessionControl.setReturnValue(tb, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ Object result = ht.load("myEntity", "", LockMode.UPGRADE);
+ assertTrue("Correct result", result == tb);
+ }
+
+ public void testLoadWithObject() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.load(tb, "");
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.load(tb, "");
+ }
+
+ public void testLoadAll() throws HibernateException {
+ MockControl criteriaControl = MockControl.createControl(Criteria.class);
+ Criteria criteria = (Criteria) criteriaControl.getMock();
+ List list = new ArrayList();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.createCriteria(TestBean.class);
+ sessionControl.setReturnValue(criteria, 1);
+ criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
+ criteriaControl.setReturnValue(criteria);
+ criteria.list();
+ criteriaControl.setReturnValue(list, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ criteriaControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ List result = ht.loadAll(TestBean.class);
+ assertTrue("Correct result", result == list);
+
+ criteriaControl.verify();
+ }
+
+ public void testLoadAllWithCacheable() throws HibernateException {
+ MockControl criteriaControl = MockControl.createControl(Criteria.class);
+ Criteria criteria = (Criteria) criteriaControl.getMock();
+ List list = new ArrayList();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.createCriteria(TestBean.class);
+ sessionControl.setReturnValue(criteria, 1);
+ criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
+ criteriaControl.setReturnValue(criteria);
+ criteria.setCacheable(true);
+ criteriaControl.setReturnValue(criteria, 1);
+ criteria.list();
+ criteriaControl.setReturnValue(list, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ criteriaControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setCacheQueries(true);
+ List result = ht.loadAll(TestBean.class);
+ assertTrue("Correct result", result == list);
+
+ criteriaControl.verify();
+ }
+
+ public void testLoadAllWithCacheableAndCacheRegion() throws HibernateException {
+ MockControl criteriaControl = MockControl.createControl(Criteria.class);
+ Criteria criteria = (Criteria) criteriaControl.getMock();
+ List list = new ArrayList();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.createCriteria(TestBean.class);
+ sessionControl.setReturnValue(criteria, 1);
+ criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
+ criteriaControl.setReturnValue(criteria);
+ criteria.setCacheable(true);
+ criteriaControl.setReturnValue(criteria, 1);
+ criteria.setCacheRegion("myCacheRegion");
+ criteriaControl.setReturnValue(criteria, 1);
+ criteria.list();
+ criteriaControl.setReturnValue(list, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ criteriaControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setCacheQueries(true);
+ ht.setQueryCacheRegion("myCacheRegion");
+ List result = ht.loadAll(TestBean.class);
+ assertTrue("Correct result", result == list);
+
+ criteriaControl.verify();
+ }
+
+ public void testRefresh() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.refresh(tb);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.refresh(tb);
+ }
+
+ public void testContains() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.contains(tb);
+ sessionControl.setReturnValue(true, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ assertTrue(ht.contains(tb));
+ }
+
+ public void testEvict() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.evict(tb);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.evict(tb);
+ }
+
+ public void testLock() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.lock(tb, LockMode.WRITE);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.lock(tb, LockMode.WRITE);
+ }
+
+ public void testLockWithEntityName() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.lock("myEntity", tb, LockMode.WRITE);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.lock("myEntity", tb, LockMode.WRITE);
+ }
+
+ public void testSave() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO);
+ session.save(tb);
+ sessionControl.setReturnValue(new Integer(0), 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ assertEquals("Correct return value", ht.save(tb), new Integer(0));
+ }
+
+ public void testSaveWithEntityName() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO);
+ session.save("myEntity", tb);
+ sessionControl.setReturnValue(new Integer(0), 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ assertEquals("Correct return value", ht.save("myEntity", tb), new Integer(0));
+ }
+
+ public void testUpdate() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO);
+ session.update(tb);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.update(tb);
+ }
+
+ public void testUpdateWithLockMode() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO);
+ session.update(tb);
+ sessionControl.setVoidCallable(1);
+ session.lock(tb, LockMode.UPGRADE);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.update(tb, LockMode.UPGRADE);
+ }
+
+ public void testUpdateWithEntityName() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO);
+ session.update("myEntity", tb);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.update("myEntity", tb);
+ }
+
+ public void testUpdateWithEntityNameAndLockMode() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO);
+ session.update("myEntity", tb);
+ sessionControl.setVoidCallable(1);
+ session.lock(tb, LockMode.UPGRADE);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.update("myEntity", tb, LockMode.UPGRADE);
+ }
+
+ public void testSaveOrUpdate() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO);
+ session.saveOrUpdate(tb);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.saveOrUpdate(tb);
+ }
+
+ public void testSaveOrUpdateWithFlushModeNever() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.NEVER);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ try {
+ ht.saveOrUpdate(tb);
+ fail("Should have thrown InvalidDataAccessApiUsageException");
+ }
+ catch (InvalidDataAccessApiUsageException ex) {
+ // expected
+ }
+ }
+
+ public void testSaveOrUpdateWithEntityName() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO);
+ session.saveOrUpdate("myEntity", tb);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.saveOrUpdate("myEntity", tb);
+ }
+
+ public void testSaveOrUpdateAll() throws HibernateException {
+ TestBean tb1 = new TestBean();
+ TestBean tb2 = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO);
+ session.saveOrUpdate(tb1);
+ sessionControl.setVoidCallable(1);
+ session.saveOrUpdate(tb2);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ List tbs = new ArrayList();
+ tbs.add(tb1);
+ tbs.add(tb2);
+ ht.saveOrUpdateAll(tbs);
+ }
+
+ public void testReplicate() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO);
+ session.replicate(tb, ReplicationMode.LATEST_VERSION);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.replicate(tb, ReplicationMode.LATEST_VERSION);
+ }
+
+ public void testReplicateWithEntityName() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO);
+ session.replicate("myEntity", tb, ReplicationMode.LATEST_VERSION);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.replicate("myEntity", tb, ReplicationMode.LATEST_VERSION);
+ }
+
+ public void testPersist() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO);
+ session.persist(tb);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.persist(tb);
+ }
+
+ public void testPersistWithEntityName() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO);
+ session.persist("myEntity", tb);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.persist("myEntity", tb);
+ }
+
+ public void testMerge() throws HibernateException {
+ TestBean tb = new TestBean();
+ TestBean tbMerged = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO);
+ session.merge(tb);
+ sessionControl.setReturnValue(tbMerged, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ assertSame(tbMerged, ht.merge(tb));
+ }
+
+ public void testMergeWithEntityName() throws HibernateException {
+ TestBean tb = new TestBean();
+ TestBean tbMerged = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO);
+ session.merge("myEntity", tb);
+ sessionControl.setReturnValue(tbMerged, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ assertSame(tbMerged, ht.merge("myEntity", tb));
+ }
+
+ public void testDelete() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO);
+ session.delete(tb);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.delete(tb);
+ }
+
+ public void testDeleteWithLockMode() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO);
+ session.lock(tb, LockMode.UPGRADE);
+ sessionControl.setVoidCallable(1);
+ session.delete(tb);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.delete(tb, LockMode.UPGRADE);
+ }
+
+ public void testDeleteWithEntityName() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO);
+ session.delete("myEntity", tb);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.delete("myEntity", tb);
+ }
+
+ public void testDeleteWithEntityNameAndLockMode() throws HibernateException {
+ TestBean tb = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO);
+ session.lock("myEntity", tb, LockMode.UPGRADE);
+ sessionControl.setVoidCallable(1);
+ session.delete("myEntity", tb);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.delete("myEntity", tb, LockMode.UPGRADE);
+ }
+
+ public void testDeleteAll() throws HibernateException {
+ TestBean tb1 = new TestBean();
+ TestBean tb2 = new TestBean();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO);
+ session.delete(tb1);
+ sessionControl.setVoidCallable(1);
+ session.delete(tb2);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ List tbs = new ArrayList();
+ tbs.add(tb1);
+ tbs.add(tb2);
+ ht.deleteAll(tbs);
+ }
+
+ public void testFlush() throws HibernateException {
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.setFlushMode(FlushMode.NEVER);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setFlushMode(HibernateTemplate.FLUSH_NEVER);
+ ht.flush();
+ }
+
+ public void testClear() throws HibernateException {
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.clear();
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.clear();
+ }
+
+ public void testFind() throws HibernateException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ List list = new ArrayList();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.createQuery("some query string");
+ sessionControl.setReturnValue(query, 1);
+ query.list();
+ queryControl.setReturnValue(list, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ List result = ht.find("some query string");
+ assertTrue("Correct list", result == list);
+ queryControl.verify();
+ }
+
+ public void testFindWithParameter() throws HibernateException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ List list = new ArrayList();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.createQuery("some query string");
+ sessionControl.setReturnValue(query, 1);
+ query.setParameter(0, "myvalue");
+ queryControl.setReturnValue(query, 1);
+ query.list();
+ queryControl.setReturnValue(list, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ List result = ht.find("some query string", "myvalue");
+ assertTrue("Correct list", result == list);
+ queryControl.verify();
+ }
+
+ public void testFindWithParameters() throws HibernateException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ List list = new ArrayList();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.createQuery("some query string");
+ sessionControl.setReturnValue(query, 1);
+ query.setParameter(0, "myvalue1");
+ queryControl.setReturnValue(query, 1);
+ query.setParameter(1, new Integer(2));
+ queryControl.setReturnValue(query, 1);
+ query.list();
+ queryControl.setReturnValue(list, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ List result = ht.find("some query string", new Object[] {"myvalue1", new Integer(2)});
+ assertTrue("Correct list", result == list);
+ queryControl.verify();
+ }
+
+ public void testFindWithNamedParameter() throws HibernateException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ List list = new ArrayList();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.createQuery("some query string");
+ sessionControl.setReturnValue(query, 1);
+ query.setParameter("myparam", "myvalue");
+ queryControl.setReturnValue(query, 1);
+ query.list();
+ queryControl.setReturnValue(list, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ List result = ht.findByNamedParam("some query string", "myparam", "myvalue");
+ assertTrue("Correct list", result == list);
+ queryControl.verify();
+ }
+
+ public void testFindWithNamedParameters() throws HibernateException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ List list = new ArrayList();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.createQuery("some query string");
+ sessionControl.setReturnValue(query, 1);
+ query.setParameter("myparam1", "myvalue1");
+ queryControl.setReturnValue(query, 1);
+ query.setParameter("myparam2", new Integer(2));
+ queryControl.setReturnValue(query, 1);
+ query.list();
+ queryControl.setReturnValue(list, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ List result = ht.findByNamedParam("some query string",
+ new String[] {"myparam1", "myparam2"},
+ new Object[] {"myvalue1", new Integer(2)});
+ assertTrue("Correct list", result == list);
+ queryControl.verify();
+ }
+
+ public void testFindByValueBean() throws HibernateException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ TestBean tb = new TestBean();
+ List list = new ArrayList();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.createQuery("some query string");
+ sessionControl.setReturnValue(query, 1);
+ query.setProperties(tb);
+ queryControl.setReturnValue(query, 1);
+ query.list();
+ queryControl.setReturnValue(list, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ List result = ht.findByValueBean("some query string", tb);
+ assertTrue("Correct list", result == list);
+ queryControl.verify();
+ }
+
+ public void testFindByNamedQuery() throws HibernateException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ List list = new ArrayList();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getNamedQuery("some query name");
+ sessionControl.setReturnValue(query, 1);
+ query.list();
+ queryControl.setReturnValue(list, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ List result = ht.findByNamedQuery("some query name");
+ assertTrue("Correct list", result == list);
+ queryControl.verify();
+ }
+
+ public void testFindByNamedQueryWithParameter() throws HibernateException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ List list = new ArrayList();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getNamedQuery("some query name");
+ sessionControl.setReturnValue(query, 1);
+ query.setParameter(0, "myvalue");
+ queryControl.setReturnValue(query, 1);
+ query.list();
+ queryControl.setReturnValue(list, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ List result = ht.findByNamedQuery("some query name", "myvalue");
+ assertTrue("Correct list", result == list);
+ queryControl.verify();
+ }
+
+ public void testFindByNamedQueryWithParameters() throws HibernateException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ List list = new ArrayList();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getNamedQuery("some query name");
+ sessionControl.setReturnValue(query, 1);
+ query.setParameter(0, "myvalue1");
+ queryControl.setReturnValue(query, 1);
+ query.setParameter(1, new Integer(2));
+ queryControl.setReturnValue(query, 1);
+ query.list();
+ queryControl.setReturnValue(list, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ List result = ht.findByNamedQuery("some query name", new Object[] {"myvalue1", new Integer(2)});
+ assertTrue("Correct list", result == list);
+ queryControl.verify();
+ }
+
+ public void testFindByNamedQueryWithNamedParameter() throws HibernateException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ List list = new ArrayList();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getNamedQuery("some query name");
+ sessionControl.setReturnValue(query, 1);
+ query.setParameter("myparam", "myvalue");
+ queryControl.setReturnValue(query, 1);
+ query.list();
+ queryControl.setReturnValue(list, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ List result = ht.findByNamedQueryAndNamedParam("some query name", "myparam", "myvalue");
+ assertTrue("Correct list", result == list);
+ queryControl.verify();
+ }
+
+ public void testFindByNamedQueryWithNamedParameters() throws HibernateException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ List list = new ArrayList();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getNamedQuery("some query name");
+ sessionControl.setReturnValue(query, 1);
+ query.setParameter("myparam1", "myvalue1");
+ queryControl.setReturnValue(query, 1);
+ query.setParameter("myparam2", new Integer(2));
+ queryControl.setReturnValue(query, 1);
+ query.list();
+ queryControl.setReturnValue(list, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ List result = ht.findByNamedQueryAndNamedParam("some query name",
+ new String[] {"myparam1", "myparam2"},
+ new Object[] {"myvalue1", new Integer(2)});
+ assertTrue("Correct list", result == list);
+ queryControl.verify();
+ }
+
+ public void testFindByNamedQueryAndValueBean() throws HibernateException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ TestBean tb = new TestBean();
+ List list = new ArrayList();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getNamedQuery("some query name");
+ sessionControl.setReturnValue(query, 1);
+ query.setProperties(tb);
+ queryControl.setReturnValue(query, 1);
+ query.list();
+ queryControl.setReturnValue(list, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ List result = ht.findByNamedQueryAndValueBean("some query name", tb);
+ assertTrue("Correct list", result == list);
+ queryControl.verify();
+ }
+
+ public void testFindWithCacheable() throws HibernateException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ List list = new ArrayList();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.createQuery("some query string");
+ sessionControl.setReturnValue(query, 1);
+ query.setCacheable(true);
+ queryControl.setReturnValue(query, 1);
+ query.list();
+ queryControl.setReturnValue(list, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setCacheQueries(true);
+ List result = ht.find("some query string");
+ assertTrue("Correct list", result == list);
+ sfControl.verify();
+ }
+
+ public void testFindWithCacheableAndCacheRegion() throws HibernateException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ List list = new ArrayList();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.createQuery("some query string");
+ sessionControl.setReturnValue(query, 1);
+ query.setCacheable(true);
+ queryControl.setReturnValue(query, 1);
+ query.setCacheRegion("myCacheRegion");
+ queryControl.setReturnValue(query, 1);
+ query.list();
+ queryControl.setReturnValue(list, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setCacheQueries(true);
+ ht.setQueryCacheRegion("myCacheRegion");
+ List result = ht.find("some query string");
+ assertTrue("Correct list", result == list);
+ sfControl.verify();
+ }
+
+ public void testFindByNamedQueryWithCacheable() throws HibernateException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ List list = new ArrayList();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getNamedQuery("some query name");
+ sessionControl.setReturnValue(query, 1);
+ query.setCacheable(true);
+ queryControl.setReturnValue(query, 1);
+ query.list();
+ queryControl.setReturnValue(list, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setCacheQueries(true);
+ List result = ht.findByNamedQuery("some query name");
+ assertTrue("Correct list", result == list);
+ queryControl.verify();
+ }
+
+ public void testFindByNamedQueryWithCacheableAndCacheRegion() throws HibernateException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ List list = new ArrayList();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getNamedQuery("some query name");
+ sessionControl.setReturnValue(query, 1);
+ query.setCacheable(true);
+ queryControl.setReturnValue(query, 1);
+ query.setCacheRegion("myCacheRegion");
+ queryControl.setReturnValue(query, 1);
+ query.list();
+ queryControl.setReturnValue(list, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setCacheQueries(true);
+ ht.setQueryCacheRegion("myCacheRegion");
+ List result = ht.findByNamedQuery("some query name");
+ assertTrue("Correct list", result == list);
+ queryControl.verify();
+ }
+
+ public void testIterate() throws HibernateException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ Iterator it = Collections.EMPTY_LIST.iterator();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.createQuery("some query string");
+ sessionControl.setReturnValue(query, 1);
+ query.iterate();
+ queryControl.setReturnValue(it, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ Iterator result = ht.iterate("some query string");
+ assertTrue("Correct list", result == it);
+ queryControl.verify();
+ }
+
+ public void testIterateWithParameter() throws HibernateException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ Iterator it = Collections.EMPTY_LIST.iterator();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.createQuery("some query string");
+ sessionControl.setReturnValue(query, 1);
+ query.setParameter(0, "myvalue");
+ queryControl.setReturnValue(query, 1);
+ query.iterate();
+ queryControl.setReturnValue(it, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ Iterator result = ht.iterate("some query string", "myvalue");
+ assertTrue("Correct list", result == it);
+ queryControl.verify();
+ }
+
+ public void testIterateWithParameters() throws HibernateException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ Iterator it = Collections.EMPTY_LIST.iterator();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.createQuery("some query string");
+ sessionControl.setReturnValue(query, 1);
+ query.setParameter(0, "myvalue1");
+ queryControl.setReturnValue(query, 1);
+ query.setParameter(1, new Integer(2));
+ queryControl.setReturnValue(query, 1);
+ query.iterate();
+ queryControl.setReturnValue(it, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ Iterator result = ht.iterate("some query string",
+ new Object[] {"myvalue1", new Integer(2)});
+ assertTrue("Correct list", result == it);
+ sfControl.verify();
+ }
+
+ public void testBulkUpdate() throws HibernateException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.createQuery("some query string");
+ sessionControl.setReturnValue(query, 1);
+ query.executeUpdate();
+ queryControl.setReturnValue(5, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ int result = ht.bulkUpdate("some query string");
+ assertTrue("Correct list", result == 5);
+ queryControl.verify();
+ }
+
+ public void testBulkUpdateWithParameter() throws HibernateException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.createQuery("some query string");
+ sessionControl.setReturnValue(query, 1);
+ query.setParameter(0, "myvalue");
+ queryControl.setReturnValue(query, 1);
+ query.executeUpdate();
+ queryControl.setReturnValue(5, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ int result = ht.bulkUpdate("some query string", "myvalue");
+ assertTrue("Correct list", result == 5);
+ queryControl.verify();
+ }
+
+ public void testBulkUpdateWithParameters() throws HibernateException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.createQuery("some query string");
+ sessionControl.setReturnValue(query, 1);
+ query.setParameter(0, "myvalue1");
+ queryControl.setReturnValue(query, 1);
+ query.setParameter(1, new Integer(2));
+ queryControl.setReturnValue(query, 1);
+ query.executeUpdate();
+ queryControl.setReturnValue(5, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ queryControl.replay();
+
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ int result = ht.bulkUpdate("some query string",
+ new Object[] {"myvalue1", new Integer(2)});
+ assertTrue("Correct list", result == 5);
+ queryControl.verify();
+ }
+
+ public void testExceptions() throws HibernateException {
+ SQLException sqlEx = new SQLException("argh", "27");
+
+ final JDBCConnectionException jcex = new JDBCConnectionException("mymsg", sqlEx);
+ try {
+ createTemplate().execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ throw jcex;
+ }
+ });
+ fail("Should have thrown DataAccessResourceFailureException");
+ }
+ catch (DataAccessResourceFailureException ex) {
+ // expected
+ assertEquals(jcex, ex.getCause());
+ assertTrue(ex.getMessage().indexOf("mymsg") != -1);
+ }
+
+ final SQLGrammarException sgex = new SQLGrammarException("mymsg", sqlEx);
+ try {
+ createTemplate().execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ throw sgex;
+ }
+ });
+ fail("Should have thrown InvalidDataAccessResourceUsageException");
+ }
+ catch (InvalidDataAccessResourceUsageException ex) {
+ // expected
+ assertEquals(sgex, ex.getCause());
+ assertTrue(ex.getMessage().indexOf("mymsg") != -1);
+ }
+
+ final LockAcquisitionException laex = new LockAcquisitionException("mymsg", sqlEx);
+ try {
+ createTemplate().execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ throw laex;
+ }
+ });
+ fail("Should have thrown CannotAcquireLockException");
+ }
+ catch (CannotAcquireLockException ex) {
+ // expected
+ assertEquals(laex, ex.getCause());
+ assertTrue(ex.getMessage().indexOf("mymsg") != -1);
+ }
+
+ final ConstraintViolationException cvex = new ConstraintViolationException("mymsg", sqlEx, "myconstraint");
+ try {
+ createTemplate().execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ throw cvex;
+ }
+ });
+ fail("Should have thrown DataIntegrityViolationException");
+ }
+ catch (DataIntegrityViolationException ex) {
+ // expected
+ assertEquals(cvex, ex.getCause());
+ assertTrue(ex.getMessage().indexOf("mymsg") != -1);
+ }
+
+ final DataException dex = new DataException("mymsg", sqlEx);
+ try {
+ createTemplate().execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ throw dex;
+ }
+ });
+ fail("Should have thrown DataIntegrityViolationException");
+ }
+ catch (DataIntegrityViolationException ex) {
+ // expected
+ assertEquals(dex, ex.getCause());
+ assertTrue(ex.getMessage().indexOf("mymsg") != -1);
+ }
+
+ final JDBCException jdex = new JDBCException("mymsg", sqlEx);
+ try {
+ createTemplate().execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ throw jdex;
+ }
+ });
+ fail("Should have thrown HibernateJdbcException");
+ }
+ catch (HibernateJdbcException ex) {
+ // expected
+ assertEquals(jdex, ex.getCause());
+ assertTrue(ex.getMessage().indexOf("mymsg") != -1);
+ }
+
+ final PropertyValueException pvex = new PropertyValueException("mymsg", "myentity", "myproperty");
+ try {
+ createTemplate().execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ throw pvex;
+ }
+ });
+ fail("Should have thrown DataIntegrityViolationException");
+ }
+ catch (DataIntegrityViolationException ex) {
+ // expected
+ assertEquals(pvex, ex.getCause());
+ assertTrue(ex.getMessage().indexOf("mymsg") != -1);
+ }
+
+ try {
+ createTemplate().execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ throw new PersistentObjectException("");
+ }
+ });
+ fail("Should have thrown InvalidDataAccessApiUsageException");
+ }
+ catch (InvalidDataAccessApiUsageException ex) {
+ // expected
+ }
+
+ try {
+ createTemplate().execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ throw new TransientObjectException("");
+ }
+ });
+ fail("Should have thrown InvalidDataAccessApiUsageException");
+ }
+ catch (InvalidDataAccessApiUsageException ex) {
+ // expected
+ }
+
+ final ObjectDeletedException odex = new ObjectDeletedException("msg", "id", TestBean.class.getName());
+ try {
+ createTemplate().execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ throw odex;
+ }
+ });
+ fail("Should have thrown InvalidDataAccessApiUsageException");
+ }
+ catch (InvalidDataAccessApiUsageException ex) {
+ // expected
+ assertEquals(odex, ex.getCause());
+ }
+
+ final QueryException qex = new QueryException("msg");
+ qex.setQueryString("query");
+ try {
+ createTemplate().execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ throw qex;
+ }
+ });
+ fail("Should have thrown InvalidDataAccessResourceUsageException");
+ }
+ catch (HibernateQueryException ex) {
+ // expected
+ assertEquals(qex, ex.getCause());
+ assertEquals("query", ex.getQueryString());
+ }
+
+ final UnresolvableObjectException uoex = new UnresolvableObjectException("id", TestBean.class.getName());
+ try {
+ createTemplate().execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ throw uoex;
+ }
+ });
+ fail("Should have thrown HibernateObjectRetrievalFailureException");
+ }
+ catch (HibernateObjectRetrievalFailureException ex) {
+ // expected
+ assertEquals(TestBean.class.getName(), ex.getPersistentClassName());
+ assertEquals("id", ex.getIdentifier());
+ assertEquals(uoex, ex.getCause());
+ }
+
+ final ObjectNotFoundException onfe = new ObjectNotFoundException("id", TestBean.class.getName());
+ try {
+ createTemplate().execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ throw onfe;
+ }
+ });
+ fail("Should have thrown HibernateObjectRetrievalFailureException");
+ }
+ catch (HibernateObjectRetrievalFailureException ex) {
+ // expected
+ assertEquals(TestBean.class.getName(), ex.getPersistentClassName());
+ assertEquals("id", ex.getIdentifier());
+ assertEquals(onfe, ex.getCause());
+ }
+
+ final WrongClassException wcex = new WrongClassException("msg", "id", TestBean.class.getName());
+ try {
+ createTemplate().execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ throw wcex;
+ }
+ });
+ fail("Should have thrown HibernateObjectRetrievalFailureException");
+ }
+ catch (HibernateObjectRetrievalFailureException ex) {
+ // expected
+ assertEquals(TestBean.class.getName(), ex.getPersistentClassName());
+ assertEquals("id", ex.getIdentifier());
+ assertEquals(wcex, ex.getCause());
+ }
+
+ final NonUniqueResultException nuex = new NonUniqueResultException(2);
+ try {
+ createTemplate().execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ throw nuex;
+ }
+ });
+ fail("Should have thrown IncorrectResultSizeDataAccessException");
+ }
+ catch (IncorrectResultSizeDataAccessException ex) {
+ // expected
+ assertEquals(1, ex.getExpectedSize());
+ assertEquals(-1, ex.getActualSize());
+ }
+
+ final StaleObjectStateException sosex = new StaleObjectStateException(TestBean.class.getName(), "id");
+ try {
+ createTemplate().execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ throw sosex;
+ }
+ });
+ fail("Should have thrown HibernateOptimisticLockingFailureException");
+ }
+ catch (HibernateOptimisticLockingFailureException ex) {
+ // expected
+ assertEquals(TestBean.class.getName(), ex.getPersistentClassName());
+ assertEquals("id", ex.getIdentifier());
+ assertEquals(sosex, ex.getCause());
+ }
+
+ final StaleStateException ssex = new StaleStateException("msg");
+ try {
+ createTemplate().execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ throw ssex;
+ }
+ });
+ fail("Should have thrown HibernateOptimisticLockingFailureException");
+ }
+ catch (HibernateOptimisticLockingFailureException ex) {
+ // expected
+ assertNull(ex.getPersistentClassName());
+ assertNull(ex.getIdentifier());
+ assertEquals(ssex, ex.getCause());
+ }
+
+ final HibernateException hex = new HibernateException("msg");
+ try {
+ createTemplate().execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ throw hex;
+ }
+ });
+ fail("Should have thrown HibernateSystemException");
+ }
+ catch (HibernateSystemException ex) {
+ // expected
+ assertEquals(hex, ex.getCause());
+ }
+ }
+
+ public void testFallbackExceptionTranslation() throws HibernateException {
+ SQLException sqlEx = new SQLException("argh", "27");
+
+ final GenericJDBCException gjex = new GenericJDBCException("mymsg", sqlEx);
+ try {
+ createTemplate().execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ throw gjex;
+ }
+ });
+ fail("Should have thrown DataIntegrityViolationException");
+ }
+ catch (DataIntegrityViolationException ex) {
+ // expected
+ assertEquals(sqlEx, ex.getCause());
+ assertTrue(ex.getMessage().indexOf("mymsg") != -1);
+ }
+ }
+
+ private HibernateTemplate createTemplate() throws HibernateException {
+ sfControl.reset();
+ sessionControl.reset();
+ sf.openSession();
+ sfControl.setReturnValue(session);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ return new HibernateTemplate(sf);
+ }
+
+ protected void tearDown() {
+ try {
+ sfControl.verify();
+ sessionControl.verify();
+ }
+ catch (IllegalStateException ex) {
+ // ignore: test method didn't call replay
+ }
+ assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/HibernateTransactionManagerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/HibernateTransactionManagerTests.java
new file mode 100644
index 00000000000..300061e0205
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/HibernateTransactionManagerTests.java
@@ -0,0 +1,1789 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.orm.hibernate3;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+import java.sql.Savepoint;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import javax.sql.DataSource;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+import org.hibernate.FlushMode;
+import org.hibernate.HibernateException;
+import org.hibernate.Interceptor;
+import org.hibernate.Query;
+import org.hibernate.SessionFactory;
+import org.hibernate.Transaction;
+import org.hibernate.cache.NoCacheProvider;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.classic.Session;
+import org.hibernate.dialect.HSQLDialect;
+import org.hibernate.exception.ConstraintViolationException;
+import org.hibernate.exception.GenericJDBCException;
+
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.jdbc.datasource.ConnectionHolder;
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+import org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy;
+import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
+import org.springframework.transaction.CannotCreateTransactionException;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.UnexpectedRollbackException;
+import org.springframework.transaction.support.TransactionCallback;
+import org.springframework.transaction.support.TransactionCallbackWithoutResult;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+import org.springframework.transaction.support.TransactionTemplate;
+
+/**
+ * @author Juergen Hoeller
+ * @since 05.03.2005
+ */
+public class HibernateTransactionManagerTests extends TestCase {
+
+ public void testTransactionCommit() throws Exception {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ final List list = new ArrayList();
+ list.add("test");
+ con.getTransactionIsolation();
+ conControl.setReturnValue(Connection.TRANSACTION_READ_COMMITTED);
+ con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
+ conControl.setVoidCallable(1);
+ con.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getTransaction();
+ sessionControl.setReturnValue(tx, 1);
+ tx.setTimeout(10);
+ txControl.setVoidCallable(1);
+ tx.begin();
+ txControl.setVoidCallable(1);
+ session.connection();
+ sessionControl.setReturnValue(con, 3);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.createQuery("some query string");
+ sessionControl.setReturnValue(query, 1);
+ query.list();
+ queryControl.setReturnValue(list, 1);
+ tx.commit();
+ txControl.setVoidCallable(1);
+ session.isConnected();
+ sessionControl.setReturnValue(true, 1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+
+ dsControl.replay();
+ conControl.replay();
+ sfControl.replay();
+ sessionControl.replay();
+ txControl.replay();
+ queryControl.replay();
+
+ LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean() {
+ protected SessionFactory newSessionFactory(Configuration config) throws HibernateException {
+ return sf;
+ }
+ };
+ lsfb.afterPropertiesSet();
+ final SessionFactory sfProxy = (SessionFactory) lsfb.getObject();
+
+ HibernateTransactionManager tm = new HibernateTransactionManager();
+ tm.setJdbcExceptionTranslator(new SQLStateSQLExceptionTranslator());
+ tm.setSessionFactory(sfProxy);
+ tm.setDataSource(ds);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
+ tt.setTimeout(10);
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sfProxy));
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sfProxy));
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ HibernateTemplate ht = new HibernateTemplate(sfProxy);
+ return ht.find("some query string");
+ }
+ });
+ assertTrue("Correct result list", result == list);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sfProxy));
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ dsControl.verify();
+ conControl.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ txControl.verify();
+ queryControl.verify();
+ }
+
+ public void testTransactionRollback() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.beginTransaction();
+ sessionControl.setReturnValue(tx, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ tx.rollback();
+ txControl.setVoidCallable(1);
+ session.isConnected();
+ sessionControl.setReturnValue(true, 1);
+ session.connection();
+ sessionControl.setReturnValue(con, 2);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+
+ sfControl.replay();
+ sessionControl.replay();
+ txControl.replay();
+
+ PlatformTransactionManager tm = new HibernateTransactionManager(sf);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ try {
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ return ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) {
+ throw new RuntimeException("application exception");
+ }
+ });
+ }
+ });
+ fail("Should have thrown RuntimeException");
+ }
+ catch (RuntimeException ex) {
+ // expected
+ }
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ sfControl.verify();
+ sessionControl.verify();
+ txControl.verify();
+ }
+
+ public void testTransactionRollbackOnly() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.beginTransaction();
+ sessionControl.setReturnValue(tx, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ tx.rollback();
+ txControl.setVoidCallable(1);
+ session.isConnected();
+ sessionControl.setReturnValue(true, 1);
+ session.connection();
+ sessionControl.setReturnValue(con, 2);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ txControl.replay();
+
+ PlatformTransactionManager tm = new HibernateTransactionManager(sf);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setFlushMode(HibernateTemplate.FLUSH_EAGER);
+ ht.execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) {
+ return null;
+ }
+ });
+ status.setRollbackOnly();
+ return null;
+ }
+ });
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ sfControl.verify();
+ sessionControl.verify();
+ txControl.verify();
+ }
+
+ public void testTransactionCommitWithEarlyFlush() throws Exception {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ final List list = new ArrayList();
+ list.add("test");
+ con.getTransactionIsolation();
+ conControl.setReturnValue(Connection.TRANSACTION_READ_COMMITTED);
+ con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
+ conControl.setVoidCallable(1);
+ con.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
+ conControl.setVoidCallable(1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getTransaction();
+ sessionControl.setReturnValue(tx, 1);
+ tx.setTimeout(10);
+ txControl.setVoidCallable(1);
+ tx.begin();
+ txControl.setVoidCallable(1);
+ session.connection();
+ sessionControl.setReturnValue(con, 3);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.createQuery("some query string");
+ sessionControl.setReturnValue(query, 1);
+ query.list();
+ queryControl.setReturnValue(list, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.setFlushMode(FlushMode.NEVER);
+ sessionControl.setVoidCallable(1);
+ tx.commit();
+ txControl.setVoidCallable(1);
+ session.isConnected();
+ sessionControl.setReturnValue(true, 1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+
+ dsControl.replay();
+ conControl.replay();
+ sfControl.replay();
+ sessionControl.replay();
+ txControl.replay();
+ queryControl.replay();
+
+ LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean() {
+ protected SessionFactory newSessionFactory(Configuration config) throws HibernateException {
+ return sf;
+ }
+ };
+ lsfb.afterPropertiesSet();
+ final SessionFactory sfProxy = (SessionFactory) lsfb.getObject();
+
+ HibernateTransactionManager tm = new HibernateTransactionManager();
+ tm.setJdbcExceptionTranslator(new SQLStateSQLExceptionTranslator());
+ tm.setSessionFactory(sfProxy);
+ tm.setDataSource(ds);
+ tm.setEarlyFlushBeforeCommit(true);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
+ tt.setTimeout(10);
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sfProxy));
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sfProxy));
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ HibernateTemplate ht = new HibernateTemplate(sfProxy);
+ return ht.find("some query string");
+ }
+ });
+ assertTrue("Correct result list", result == list);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sfProxy));
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ dsControl.verify();
+ conControl.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ txControl.verify();
+ queryControl.verify();
+ }
+
+ public void testParticipatingTransactionWithCommit() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.beginTransaction();
+ sessionControl.setReturnValue(tx, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO, 1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ tx.commit();
+ txControl.setVoidCallable(1);
+ session.isConnected();
+ sessionControl.setReturnValue(true, 1);
+ session.connection();
+ sessionControl.setReturnValue(con, 2);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ txControl.replay();
+
+ LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean() {
+ protected SessionFactory newSessionFactory(Configuration config) throws HibernateException {
+ return sf;
+ }
+ };
+ lsfb.afterPropertiesSet();
+ final SessionFactory sfProxy = (SessionFactory) lsfb.getObject();
+
+ PlatformTransactionManager tm = new HibernateTransactionManager(sfProxy);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ final List l = new ArrayList();
+ l.add("test");
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ return tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ HibernateTemplate ht = new HibernateTemplate(sfProxy);
+ ht.setFlushMode(HibernateTemplate.FLUSH_EAGER);
+ return ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) {
+ return l;
+ }
+ });
+ }
+ });
+ }
+ });
+ assertTrue("Correct result list", result == l);
+
+ sfControl.verify();
+ sessionControl.verify();
+ txControl.verify();
+ }
+
+ public void testParticipatingTransactionWithRollback() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.beginTransaction();
+ sessionControl.setReturnValue(tx, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO, 1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ tx.rollback();
+ txControl.setVoidCallable(1);
+ session.isConnected();
+ sessionControl.setReturnValue(true, 1);
+ session.connection();
+ sessionControl.setReturnValue(con, 2);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ txControl.replay();
+
+ PlatformTransactionManager tm = new HibernateTransactionManager(sf);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ try {
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ return tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setFlushMode(HibernateTemplate.FLUSH_EAGER);
+ return ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) {
+ throw new RuntimeException("application exception");
+ }
+ });
+ }
+ });
+ }
+ });
+ fail("Should have thrown RuntimeException");
+ }
+ catch (RuntimeException ex) {
+ // expected
+ }
+
+ sfControl.verify();
+ sessionControl.verify();
+ txControl.verify();
+ }
+
+ public void testParticipatingTransactionWithRollbackOnly() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.beginTransaction();
+ sessionControl.setReturnValue(tx, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ tx.rollback();
+ txControl.setVoidCallable(1);
+ session.isConnected();
+ sessionControl.setReturnValue(true, 1);
+ session.connection();
+ sessionControl.setReturnValue(con, 2);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ txControl.replay();
+
+ PlatformTransactionManager tm = new HibernateTransactionManager(sf);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ final List l = new ArrayList();
+ l.add("test");
+
+ try {
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ return tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) {
+ return l;
+ }
+ });
+ status.setRollbackOnly();
+ return null;
+ }
+ });
+ }
+ });
+ fail("Should have thrown UnexpectedRollbackException");
+ }
+ catch (UnexpectedRollbackException ex) {
+ // expected
+ }
+
+ sfControl.verify();
+ sessionControl.verify();
+ txControl.verify();
+ }
+
+ public void testParticipatingTransactionWithWithRequiresNew() throws Exception {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl session1Control = MockControl.createControl(Session.class);
+ Session session1 = (Session) session1Control.getMock();
+ MockControl session2Control = MockControl.createControl(Session.class);
+ Session session2 = (Session) session2Control.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session1, 1);
+ sf.openSession();
+ sfControl.setReturnValue(session2, 1);
+ session1.beginTransaction();
+ session1Control.setReturnValue(tx, 1);
+ session1.isOpen();
+ session1Control.setReturnValue(true, 1);
+ session2.beginTransaction();
+ session2Control.setReturnValue(tx, 1);
+ session2.isOpen();
+ session2Control.setReturnValue(true, 1);
+ session2.getFlushMode();
+ session2Control.setReturnValue(FlushMode.AUTO, 1);
+ session2.flush();
+ session2Control.setVoidCallable(1);
+ session1.close();
+ session1Control.setReturnValue(null, 1);
+ session2.close();
+ session2Control.setReturnValue(null, 1);
+ tx.commit();
+ txControl.setVoidCallable(2);
+ session1.isConnected();
+ session1Control.setReturnValue(true, 1);
+ session1.connection();
+ session1Control.setReturnValue(con, 2);
+ session2.isConnected();
+ session2Control.setReturnValue(true, 1);
+ session2.connection();
+ session2Control.setReturnValue(con, 2);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 2);
+
+ sfControl.replay();
+ session1Control.replay();
+ session2Control.replay();
+ conControl.replay();
+ txControl.replay();
+
+ PlatformTransactionManager tm = new HibernateTransactionManager(sf);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ final SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sf);
+ assertTrue("Has thread session", holder != null);
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setFlushMode(HibernateTemplate.FLUSH_EAGER);
+ return ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) {
+ assertTrue("Not enclosing session", session != holder.getSession());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ return null;
+ }
+ });
+ }
+ });
+ assertTrue("Same thread session as before",
+ holder.getSession() == SessionFactoryUtils.getSession(sf, false));
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ return null;
+ }
+ });
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+
+ sfControl.verify();
+ session1Control.verify();
+ session2Control.verify();
+ conControl.verify();
+ txControl.verify();
+ }
+
+ public void testParticipatingTransactionWithWithNotSupported() throws Exception {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 2);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.beginTransaction();
+ sessionControl.setReturnValue(tx, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.AUTO, 2);
+ session.flush();
+ sessionControl.setVoidCallable(2);
+ session.close();
+ sessionControl.setReturnValue(null, 2);
+ tx.commit();
+ txControl.setVoidCallable(1);
+ session.isConnected();
+ sessionControl.setReturnValue(true, 1);
+ session.connection();
+ sessionControl.setReturnValue(con, 2);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+
+ sfControl.replay();
+ sessionControl.replay();
+ conControl.replay();
+ txControl.replay();
+
+ HibernateTransactionManager tm = new HibernateTransactionManager(sf);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sf);
+ assertTrue("Has thread session", holder != null);
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setFlushMode(HibernateTemplate.FLUSH_EAGER);
+ return ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) {
+ return null;
+ }
+ });
+ }
+ });
+ assertTrue("Same thread session as before",
+ holder.getSession() == SessionFactoryUtils.getSession(sf, false));
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ return null;
+ }
+ });
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+
+ sfControl.verify();
+ sessionControl.verify();
+ txControl.verify();
+ }
+
+ public void testTransactionWithPropagationSupports() throws Exception {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.NEVER, 1);
+ session.setFlushMode(FlushMode.AUTO);
+ sessionControl.setVoidCallable(1);
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ session.setFlushMode(FlushMode.NEVER);
+ sessionControl.setVoidCallable(1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.NEVER, 1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean() {
+ protected SessionFactory newSessionFactory(Configuration config) throws HibernateException {
+ return sf;
+ }
+ };
+ lsfb.afterPropertiesSet();
+ final SessionFactory sfProxy = (SessionFactory) lsfb.getObject();
+
+ PlatformTransactionManager tm = new HibernateTransactionManager(sfProxy);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sfProxy));
+
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sfProxy));
+ assertTrue("Is not new transaction", !status.isNewTransaction());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ HibernateTemplate ht = new HibernateTemplate(sfProxy);
+ ht.setFlushMode(HibernateTemplate.FLUSH_EAGER);
+ ht.execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) {
+ return null;
+ }
+ });
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sfProxy));
+ return null;
+ }
+ });
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sfProxy));
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testTransactionWithPropagationSupportsAndInnerTransaction() throws Exception {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl session1Control = MockControl.createControl(Session.class);
+ final Session session1 = (Session) session1Control.getMock();
+ MockControl session2Control = MockControl.createControl(Session.class);
+ final Session session2 = (Session) session2Control.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session1, 1);
+ session1.getSessionFactory();
+ session1Control.setReturnValue(sf, 1);
+ session1.getFlushMode();
+ session1Control.setReturnValue(FlushMode.AUTO, 2);
+ session1.flush();
+ session1Control.setVoidCallable(2);
+ session1.disconnect();
+ session1Control.setReturnValue(null, 1);
+ session1.close();
+ session1Control.setReturnValue(null, 1);
+
+ sf.openSession();
+ sfControl.setReturnValue(session2, 1);
+ session2.beginTransaction();
+ session2Control.setReturnValue(tx, 1);
+ session2.connection();
+ session2Control.setReturnValue(con, 2);
+ session2.getFlushMode();
+ session2Control.setReturnValue(FlushMode.AUTO, 1);
+ session2.flush();
+ session2Control.setVoidCallable(1);
+ session2.isOpen();
+ session2Control.setReturnValue(true, 1);
+ tx.commit();
+ txControl.setVoidCallable(1);
+ session2.isConnected();
+ session2Control.setReturnValue(true, 1);
+ session2.close();
+ session2Control.setReturnValue(null, 1);
+ sfControl.replay();
+ session1Control.replay();
+ session2Control.replay();
+ txControl.replay();
+
+ LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean() {
+ protected SessionFactory newSessionFactory(Configuration config) throws HibernateException {
+ return sf;
+ }
+ };
+ lsfb.afterPropertiesSet();
+ final SessionFactory sfProxy = (SessionFactory) lsfb.getObject();
+
+ PlatformTransactionManager tm = new HibernateTransactionManager(sfProxy);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
+ final TransactionTemplate tt2 = new TransactionTemplate(tm);
+ tt2.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
+
+ final HibernateTemplate ht = new HibernateTemplate(sfProxy);
+ ht.setFlushMode(HibernateTemplate.FLUSH_EAGER);
+ ht.setExposeNativeSession(true);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sfProxy));
+ assertTrue("Is not new transaction", !status.isNewTransaction());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ ht.execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) {
+ assertSame(session1, session);
+ return null;
+ }
+ });
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sfProxy));
+ tt2.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ return ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) {
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ assertSame(session2, session);
+ return null;
+ }
+ });
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ return null;
+ }
+ });
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+
+ sfControl.verify();
+ session1Control.verify();
+ session2Control.verify();
+ txControl.verify();
+ }
+
+ public void testTransactionCommitWithEntityInterceptor() throws Exception {
+ MockControl interceptorControl = MockControl.createControl(org.hibernate.Interceptor.class);
+ Interceptor entityInterceptor = (Interceptor) interceptorControl.getMock();
+ interceptorControl.replay();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+
+ sf.openSession(entityInterceptor);
+ sfControl.setReturnValue(session, 1);
+ session.beginTransaction();
+ sessionControl.setReturnValue(tx, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ tx.commit();
+ txControl.setVoidCallable(1);
+ session.isConnected();
+ sessionControl.setReturnValue(true, 1);
+ session.connection();
+ sessionControl.setReturnValue(con, 2);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+
+ sfControl.replay();
+ sessionControl.replay();
+ txControl.replay();
+ conControl.replay();
+
+ HibernateTransactionManager tm = new HibernateTransactionManager(sf);
+ tm.setEntityInterceptor(entityInterceptor);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ final List l = new ArrayList();
+ l.add("test");
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ return ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ return l;
+ }
+ });
+ }
+ });
+ assertTrue("Correct result list", result == l);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ interceptorControl.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ txControl.verify();
+ conControl.verify();
+ }
+
+ public void testTransactionCommitWithEntityInterceptorBeanName() throws Exception {
+ MockControl interceptorControl = MockControl.createControl(org.hibernate.Interceptor.class);
+ Interceptor entityInterceptor = (Interceptor) interceptorControl.getMock();
+ interceptorControl.replay();
+ MockControl interceptor2Control = MockControl.createControl(org.hibernate.Interceptor.class);
+ Interceptor entityInterceptor2 = (Interceptor) interceptor2Control.getMock();
+ interceptor2Control.replay();
+
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+
+ sf.openSession(entityInterceptor);
+ sfControl.setReturnValue(session, 1);
+ sf.openSession(entityInterceptor2);
+ sfControl.setReturnValue(session, 1);
+ session.beginTransaction();
+ sessionControl.setReturnValue(tx, 2);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 2);
+ session.close();
+ sessionControl.setReturnValue(null, 2);
+ tx.commit();
+ txControl.setVoidCallable(2);
+ session.isConnected();
+ sessionControl.setReturnValue(true, 2);
+ session.connection();
+ sessionControl.setReturnValue(con, 4);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 2);
+
+ sfControl.replay();
+ sessionControl.replay();
+ txControl.replay();
+ conControl.replay();
+
+ MockControl beanFactoryControl = MockControl.createControl(BeanFactory.class);
+ BeanFactory beanFactory = (BeanFactory) beanFactoryControl.getMock();
+ beanFactory.getBean("entityInterceptor", Interceptor.class);
+ beanFactoryControl.setReturnValue(entityInterceptor, 1);
+ beanFactory.getBean("entityInterceptor", Interceptor.class);
+ beanFactoryControl.setReturnValue(entityInterceptor2, 1);
+ beanFactoryControl.replay();
+
+ HibernateTransactionManager tm = new HibernateTransactionManager(sf);
+ tm.setEntityInterceptorBeanName("entityInterceptor");
+ tm.setBeanFactory(beanFactory);
+
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ for (int i = 0; i < 2; i++) {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ return null;
+ }
+ });
+ }
+ });
+ }
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ interceptorControl.verify();
+ interceptor2Control.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ txControl.verify();
+ conControl.verify();
+ beanFactoryControl.verify();
+ }
+
+ public void testTransactionCommitWithReadOnly() throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ final List list = new ArrayList();
+ list.add("test");
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.beginTransaction();
+ sessionControl.setReturnValue(tx, 1);
+ session.setFlushMode(FlushMode.NEVER);
+ sessionControl.setVoidCallable(1);
+ session.connection();
+ sessionControl.setReturnValue(con, 2);
+ con.setReadOnly(true);
+ conControl.setVoidCallable(1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.createQuery("some query string");
+ sessionControl.setReturnValue(query, 1);
+ query.list();
+ queryControl.setReturnValue(list, 1);
+ tx.commit();
+ txControl.setVoidCallable(1);
+ session.isConnected();
+ sessionControl.setReturnValue(true, 1);
+ con.isReadOnly();
+ conControl.setReturnValue(true, 1);
+ con.setReadOnly(false);
+ conControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+
+ conControl.replay();
+ sfControl.replay();
+ sessionControl.replay();
+ txControl.replay();
+ queryControl.replay();
+
+ HibernateTransactionManager tm = new HibernateTransactionManager(sf);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setReadOnly(true);
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ return ht.find("some query string");
+ }
+ });
+ assertTrue("Correct result list", result == list);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ conControl.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ txControl.verify();
+ queryControl.verify();
+ }
+
+ public void testTransactionCommitWithFlushFailure() throws Exception {
+ doTestTransactionCommitWithFlushFailure(false);
+ }
+
+ public void testTransactionCommitWithFlushFailureAndFallbackTranslation() throws Exception {
+ doTestTransactionCommitWithFlushFailure(true);
+ }
+
+ private void doTestTransactionCommitWithFlushFailure(boolean fallbackTranslation) throws Exception {
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.beginTransaction();
+ sessionControl.setReturnValue(tx, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ tx.commit();
+ SQLException sqlEx = new SQLException("argh", "27");
+ Exception rootCause = null;
+ if (fallbackTranslation) {
+ GenericJDBCException jdbcEx = new GenericJDBCException("mymsg", sqlEx);
+ txControl.setThrowable(jdbcEx, 1);
+ rootCause = sqlEx;
+ }
+ else {
+ ConstraintViolationException jdbcEx = new ConstraintViolationException("mymsg", sqlEx, null);
+ txControl.setThrowable(jdbcEx, 1);
+ rootCause = jdbcEx;
+ }
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ tx.rollback();
+ txControl.setVoidCallable(1);
+ session.isConnected();
+ sessionControl.setReturnValue(true, 1);
+ session.connection();
+ sessionControl.setReturnValue(con, 2);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+
+ sfControl.replay();
+ sessionControl.replay();
+ txControl.replay();
+ conControl.replay();
+
+ HibernateTransactionManager tm = new HibernateTransactionManager(sf);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ final List l = new ArrayList();
+ l.add("test");
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ try {
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ return ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session session) throws HibernateException {
+ return l;
+ }
+ });
+ }
+ });
+ fail("Should have thrown DataIntegrityViolationException");
+ }
+ catch (DataIntegrityViolationException ex) {
+ // expected
+ assertEquals(rootCause, ex.getCause());
+ assertTrue(ex.getMessage().indexOf("mymsg") != -1);
+ }
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ sfControl.verify();
+ sessionControl.verify();
+ txControl.verify();
+ conControl.verify();
+ }
+
+ public void testTransactionCommitWithPreBound() throws Exception {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+
+ session.beginTransaction();
+ sessionControl.setReturnValue(tx, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.NEVER, 1);
+ session.setFlushMode(FlushMode.AUTO);
+ sessionControl.setVoidCallable(1);
+ session.setFlushMode(FlushMode.NEVER);
+ sessionControl.setVoidCallable(1);
+ session.connection();
+ sessionControl.setReturnValue(con, 3);
+ con.getTransactionIsolation();
+ conControl.setReturnValue(Connection.TRANSACTION_READ_COMMITTED);
+ con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
+ conControl.setVoidCallable(1);
+ con.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
+ conControl.setVoidCallable(1);
+ tx.commit();
+ txControl.setVoidCallable(1);
+ session.isConnected();
+ sessionControl.setReturnValue(true, 1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ session.disconnect();
+ sessionControl.setReturnValue(null, 1);
+
+ dsControl.replay();
+ conControl.replay();
+ sfControl.replay();
+ sessionControl.replay();
+ txControl.replay();
+
+ HibernateTransactionManager tm = new HibernateTransactionManager();
+ tm.setSessionFactory(sf);
+ tm.setDataSource(ds);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
+ final List l = new ArrayList();
+ l.add("test");
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sf);
+ assertTrue("Has thread transaction", sessionHolder.getTransaction() != null);
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setExposeNativeSession(true);
+ return ht.executeFind(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) throws HibernateException {
+ assertEquals(session, sess);
+ return l;
+ }
+ });
+ }
+ });
+ assertTrue("Correct result list", result == l);
+
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sf);
+ assertTrue("Hasn't thread transaction", sessionHolder.getTransaction() == null);
+ TransactionSynchronizationManager.unbindResource(sf);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ dsControl.verify();
+ conControl.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ txControl.verify();
+ }
+
+ public void testTransactionRollbackWithPreBound() throws Exception {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ MockControl tx1Control = MockControl.createControl(Transaction.class);
+ final Transaction tx1 = (Transaction) tx1Control.getMock();
+ MockControl tx2Control = MockControl.createControl(Transaction.class);
+ final Transaction tx2 = (Transaction) tx2Control.getMock();
+
+ session.beginTransaction();
+ sessionControl.setReturnValue(tx1, 1);
+ tx1.rollback();
+ tx1Control.setVoidCallable(1);
+ session.clear();
+ sessionControl.setVoidCallable(1);
+ session.beginTransaction();
+ sessionControl.setReturnValue(tx2, 1);
+ tx2.commit();
+ tx2Control.setVoidCallable(1);
+
+ session.isOpen();
+ sessionControl.setReturnValue(true, 2);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.NEVER, 2);
+ session.setFlushMode(FlushMode.AUTO);
+ sessionControl.setVoidCallable(2);
+ session.setFlushMode(FlushMode.NEVER);
+ sessionControl.setVoidCallable(2);
+ session.isConnected();
+ sessionControl.setReturnValue(true, 2);
+ session.connection();
+ sessionControl.setReturnValue(con, 6);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 2);
+ session.disconnect();
+ sessionControl.setReturnValue(null, 2);
+
+ dsControl.replay();
+ conControl.replay();
+ sfControl.replay();
+ sessionControl.replay();
+ tx1Control.replay();
+ tx2Control.replay();
+
+ HibernateTransactionManager tm = new HibernateTransactionManager();
+ tm.setSessionFactory(sf);
+ tm.setDataSource(ds);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+
+ try {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sf);
+ assertEquals(tx1, sessionHolder.getTransaction());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ status.setRollbackOnly();
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setExposeNativeSession(true);
+ ht.execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) throws HibernateException {
+ assertEquals(session, sess);
+ return null;
+ }
+ });
+ }
+ });
+ }
+ });
+ fail("Should have thrown UnexpectedRollbackException");
+ }
+ catch (UnexpectedRollbackException ex) {
+ // expected
+ }
+
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sf);
+ assertTrue("Hasn't thread transaction", sessionHolder.getTransaction() == null);
+ assertTrue("Not marked rollback-only", !sessionHolder.isRollbackOnly());
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sf);
+ assertEquals(tx2, sessionHolder.getTransaction());
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setExposeNativeSession(true);
+ ht.execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) throws HibernateException {
+ assertEquals(session, sess);
+ return null;
+ }
+ });
+ }
+ });
+
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("Hasn't thread transaction", sessionHolder.getTransaction() == null);
+ TransactionSynchronizationManager.unbindResource(sf);
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ dsControl.verify();
+ conControl.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ tx1Control.verify();
+ tx2Control.verify();
+ }
+
+ public void testTransactionRollbackWithHibernateManagedSession() throws Exception {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ MockControl tx1Control = MockControl.createControl(Transaction.class);
+ final Transaction tx1 = (Transaction) tx1Control.getMock();
+ MockControl tx2Control = MockControl.createControl(Transaction.class);
+ final Transaction tx2 = (Transaction) tx2Control.getMock();
+
+ sf.getCurrentSession();
+ sfControl.setReturnValue(session, 2);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 2);
+ session.getTransaction();
+ sessionControl.setReturnValue(tx1, 1);
+ session.beginTransaction();
+ sessionControl.setReturnValue(tx1, 1);
+ tx1.isActive();
+ tx1Control.setReturnValue(false, 1);
+ tx1.rollback();
+ tx1Control.setVoidCallable(1);
+ session.getTransaction();
+ sessionControl.setReturnValue(tx2, 1);
+ session.beginTransaction();
+ sessionControl.setReturnValue(tx2, 1);
+ tx2.isActive();
+ tx2Control.setReturnValue(false, 1);
+ tx2.commit();
+ tx2Control.setVoidCallable(1);
+
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.NEVER, 2);
+ session.setFlushMode(FlushMode.AUTO);
+ sessionControl.setVoidCallable(2);
+ session.setFlushMode(FlushMode.NEVER);
+ sessionControl.setVoidCallable(2);
+
+ sfControl.replay();
+ sessionControl.replay();
+ tx1Control.replay();
+ tx2Control.replay();
+
+ HibernateTransactionManager tm = new HibernateTransactionManager();
+ tm.setSessionFactory(sf);
+ tm.setPrepareConnection(false);
+ tm.setHibernateManagedSession(true);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+
+ try {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ tt.execute(new TransactionCallbackWithoutResult() {
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ status.setRollbackOnly();
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setAllowCreate(false);
+ ht.setExposeNativeSession(true);
+ ht.execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) throws HibernateException {
+ assertEquals(session, sess);
+ return null;
+ }
+ });
+ }
+ });
+ }
+ });
+ fail("Should have thrown UnexpectedRollbackException");
+ }
+ catch (UnexpectedRollbackException ex) {
+ // expected
+ }
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+
+ tt.execute(new TransactionCallbackWithoutResult() {
+ public void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ ht.setAllowCreate(false);
+ ht.setExposeNativeSession(true);
+ ht.execute(new HibernateCallback() {
+ public Object doInHibernate(org.hibernate.Session sess) throws HibernateException {
+ assertEquals(session, sess);
+ return null;
+ }
+ });
+ }
+ });
+
+ sfControl.verify();
+ sessionControl.verify();
+ tx1Control.verify();
+ tx2Control.verify();
+ }
+
+ public void testExistingTransactionWithPropagationNestedAndRollback() throws Exception {
+ doTestExistingTransactionWithPropagationNestedAndRollback(false);
+ }
+
+ public void testExistingTransactionWithManualSavepointAndRollback() throws Exception {
+ doTestExistingTransactionWithPropagationNestedAndRollback(true);
+ }
+
+ private void doTestExistingTransactionWithPropagationNestedAndRollback(final boolean manualSavepoint)
+ throws Exception {
+
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+ MockControl mdControl = MockControl.createControl(DatabaseMetaData.class);
+ DatabaseMetaData md = (DatabaseMetaData) mdControl.getMock();
+ MockControl spControl = MockControl.createControl(Savepoint.class);
+ Savepoint sp = (Savepoint) spControl.getMock();
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ final List list = new ArrayList();
+ list.add("test");
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.beginTransaction();
+ sessionControl.setReturnValue(tx, 1);
+ session.connection();
+ sessionControl.setReturnValue(con, 3);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ md.supportsSavepoints();
+ mdControl.setReturnValue(true, 1);
+ con.getMetaData();
+ conControl.setReturnValue(md, 1);
+ con.setSavepoint(ConnectionHolder.SAVEPOINT_NAME_PREFIX + 1);
+ conControl.setReturnValue(sp, 1);
+ con.rollback(sp);
+ conControl.setVoidCallable(1);
+ session.createQuery("some query string");
+ sessionControl.setReturnValue(query, 1);
+ query.list();
+ queryControl.setReturnValue(list, 1);
+ session.isConnected();
+ sessionControl.setReturnValue(true, 1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ tx.commit();
+ txControl.setVoidCallable(1);
+
+ dsControl.replay();
+ conControl.replay();
+ mdControl.replay();
+ spControl.replay();
+ sfControl.replay();
+ sessionControl.replay();
+ txControl.replay();
+ queryControl.replay();
+
+ HibernateTransactionManager tm = new HibernateTransactionManager();
+ tm.setJdbcExceptionTranslator(new SQLStateSQLExceptionTranslator());
+ tm.setNestedTransactionAllowed(true);
+ tm.setSessionFactory(sf);
+ tm.setDataSource(ds);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED);
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ if (manualSavepoint) {
+ Object savepoint = status.createSavepoint();
+ status.rollbackToSavepoint(savepoint);
+ }
+ else {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ status.setRollbackOnly();
+ }
+ });
+ }
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ return ht.find("some query string");
+ }
+ });
+ assertTrue("Correct result list", result == list);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ dsControl.verify();
+ conControl.verify();
+ mdControl.verify();
+ spControl.verify();
+ sfControl.verify();
+ sessionControl.verify();
+ txControl.verify();
+ queryControl.verify();
+ }
+
+ public void testTransactionCommitWithNonExistingDatabase() throws Exception {
+ final DriverManagerDataSource ds = new DriverManagerDataSource();
+ LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean();
+ lsfb.setDataSource(ds);
+ Properties props = new Properties();
+ props.setProperty("hibernate.dialect", HSQLDialect.class.getName());
+ props.setProperty("hibernate.cache.provider_class", NoCacheProvider.class.getName());
+ lsfb.setHibernateProperties(props);
+ lsfb.afterPropertiesSet();
+ final SessionFactory sf = (SessionFactory) lsfb.getObject();
+
+ HibernateTransactionManager tm = new HibernateTransactionManager();
+ tm.setSessionFactory(sf);
+ tm.afterPropertiesSet();
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
+ tt.setTimeout(10);
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ try {
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ return ht.find("from java.lang.Object");
+ }
+ });
+ fail("Should have thrown CannotCreateTransactionException");
+ }
+ catch (CannotCreateTransactionException ex) {
+ // expected
+ }
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ }
+
+ public void testTransactionCommitWithPreBoundSessionAndNonExistingDatabase() throws Exception {
+ final DriverManagerDataSource ds = new DriverManagerDataSource();
+ LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean();
+ lsfb.setDataSource(ds);
+ Properties props = new Properties();
+ props.setProperty("hibernate.dialect", HSQLDialect.class.getName());
+ props.setProperty("hibernate.cache.provider_class", NoCacheProvider.class.getName());
+ lsfb.setHibernateProperties(props);
+ lsfb.afterPropertiesSet();
+ final SessionFactory sf = (SessionFactory) lsfb.getObject();
+
+ HibernateTransactionManager tm = new HibernateTransactionManager();
+ tm.setSessionFactory(sf);
+ tm.afterPropertiesSet();
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
+ tt.setTimeout(10);
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ Session session = sf.openSession();
+ TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
+ try {
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ return ht.find("from java.lang.Object");
+ }
+ });
+ fail("Should have thrown CannotCreateTransactionException");
+ }
+ catch (CannotCreateTransactionException ex) {
+ // expected
+ SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sf);
+ assertFalse(holder.isSynchronizedWithTransaction());
+ }
+ finally {
+ TransactionSynchronizationManager.unbindResource(sf);
+ session.close();
+ }
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ }
+
+ public void testTransactionCommitWithNonExistingDatabaseAndLazyConnection() throws Exception {
+ DriverManagerDataSource dsTarget = new DriverManagerDataSource();
+ final LazyConnectionDataSourceProxy ds = new LazyConnectionDataSourceProxy();
+ ds.setTargetDataSource(dsTarget);
+ ds.setDefaultAutoCommit(true);
+ ds.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
+ //ds.setDefaultTransactionIsolationName("TRANSACTION_READ_COMMITTED");
+
+ LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean();
+ lsfb.setDataSource(ds);
+ Properties props = new Properties();
+ props.setProperty("hibernate.dialect", HSQLDialect.class.getName());
+ props.setProperty("hibernate.cache.provider_class", NoCacheProvider.class.getName());
+ lsfb.setHibernateProperties(props);
+ lsfb.afterPropertiesSet();
+ final SessionFactory sf = (SessionFactory) lsfb.getObject();
+
+ HibernateTransactionManager tm = new HibernateTransactionManager();
+ tm.setSessionFactory(sf);
+ tm.afterPropertiesSet();
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
+ tt.setTimeout(10);
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ HibernateTemplate ht = new HibernateTemplate(sf);
+ return ht.find("from java.lang.Object");
+ }
+ });
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ }
+
+ protected void tearDown() {
+ assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/LocalSessionFactoryBeanTests.java b/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/LocalSessionFactoryBeanTests.java
new file mode 100644
index 00000000000..73286384b03
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/LocalSessionFactoryBeanTests.java
@@ -0,0 +1,588 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.orm.hibernate3;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.transaction.TransactionManager;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+import org.hibernate.Hibernate;
+import org.hibernate.HibernateException;
+import org.hibernate.Interceptor;
+import org.hibernate.SessionFactory;
+import org.hibernate.cache.CacheProvider;
+import org.hibernate.cache.NoCacheProvider;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.cfg.ImprovedNamingStrategy;
+import org.hibernate.cfg.Mappings;
+import org.hibernate.cfg.NamingStrategy;
+import org.hibernate.connection.UserSuppliedConnectionProvider;
+import org.hibernate.engine.FilterDefinition;
+import org.hibernate.event.MergeEvent;
+import org.hibernate.event.MergeEventListener;
+import org.hibernate.mapping.TypeDef;
+
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.core.io.Resource;
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+
+/**
+ * @author Juergen Hoeller
+ * @since 05.03.2005
+ */
+public class LocalSessionFactoryBeanTests extends TestCase {
+
+ public void testLocalSessionFactoryBeanWithDataSource() throws Exception {
+ final DriverManagerDataSource ds = new DriverManagerDataSource();
+ final List invocations = new ArrayList();
+ LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() {
+ protected Configuration newConfiguration() {
+ return new Configuration() {
+ public Configuration addInputStream(InputStream is) {
+ try {
+ is.close();
+ }
+ catch (IOException ex) {
+ }
+ invocations.add("addResource");
+ return this;
+ }
+ };
+ }
+
+ protected SessionFactory newSessionFactory(Configuration config) {
+ assertEquals(LocalDataSourceConnectionProvider.class.getName(),
+ config.getProperty(Environment.CONNECTION_PROVIDER));
+ assertEquals(ds, LocalSessionFactoryBean.getConfigTimeDataSource());
+ invocations.add("newSessionFactory");
+ return null;
+ }
+ };
+ sfb.setDataSource(ds);
+ sfb.afterPropertiesSet();
+ assertTrue(sfb.getConfiguration() != null);
+ assertEquals("newSessionFactory", invocations.get(0));
+ }
+
+ public void testLocalSessionFactoryBeanWithCacheProvider() throws Exception {
+ final CacheProvider cacheProvider = new NoCacheProvider();
+ final List invocations = new ArrayList();
+ LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() {
+ protected Configuration newConfiguration() {
+ return new Configuration() {
+ public Configuration addInputStream(InputStream is) {
+ try {
+ is.close();
+ }
+ catch (IOException ex) {
+ }
+ invocations.add("addResource");
+ return this;
+ }
+ };
+ }
+
+ protected SessionFactory newSessionFactory(Configuration config) {
+ assertEquals(LocalCacheProviderProxy.class.getName(),
+ config.getProperty(Environment.CACHE_PROVIDER));
+ assertSame(cacheProvider, LocalSessionFactoryBean.getConfigTimeCacheProvider());
+ invocations.add("newSessionFactory");
+ return null;
+ }
+ };
+ sfb.setCacheProvider(cacheProvider);
+ sfb.afterPropertiesSet();
+ assertTrue(sfb.getConfiguration() != null);
+ assertEquals("newSessionFactory", invocations.get(0));
+ }
+
+ public void testLocalSessionFactoryBeanWithTransactionAwareDataSource() throws Exception {
+ final DriverManagerDataSource ds = new DriverManagerDataSource();
+ final List invocations = new ArrayList();
+ LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() {
+ protected Configuration newConfiguration() {
+ return new Configuration() {
+ public Configuration addInputStream(InputStream is) {
+ try {
+ is.close();
+ }
+ catch (IOException ex) {
+ }
+ invocations.add("addResource");
+ return this;
+ }
+ };
+ }
+
+ protected SessionFactory newSessionFactory(Configuration config) {
+ assertEquals(TransactionAwareDataSourceConnectionProvider.class.getName(),
+ config.getProperty(Environment.CONNECTION_PROVIDER));
+ assertEquals(ds, LocalSessionFactoryBean.getConfigTimeDataSource());
+ invocations.add("newSessionFactory");
+ return null;
+ }
+ };
+ sfb.setDataSource(ds);
+ sfb.setUseTransactionAwareDataSource(true);
+ sfb.afterPropertiesSet();
+ assertTrue(sfb.getConfiguration() != null);
+ assertEquals("newSessionFactory", invocations.get(0));
+ }
+
+ public void testLocalSessionFactoryBeanWithDataSourceAndMappingResources() throws Exception {
+ final DriverManagerDataSource ds = new DriverManagerDataSource();
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ final TransactionManager tm = (TransactionManager) tmControl.getMock();
+ final List invocations = new ArrayList();
+ LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() {
+ protected Configuration newConfiguration() {
+ return new Configuration() {
+ public Configuration addInputStream(InputStream is) {
+ try {
+ is.close();
+ }
+ catch (IOException ex) {
+ }
+ invocations.add("addResource");
+ return this;
+ }
+ };
+ }
+
+ protected SessionFactory newSessionFactory(Configuration config) {
+ assertEquals(LocalJtaDataSourceConnectionProvider.class.getName(),
+ config.getProperty(Environment.CONNECTION_PROVIDER));
+ assertEquals(ds, LocalSessionFactoryBean.getConfigTimeDataSource());
+ assertEquals(LocalTransactionManagerLookup.class.getName(),
+ config.getProperty(Environment.TRANSACTION_MANAGER_STRATEGY));
+ assertEquals(tm, LocalSessionFactoryBean.getConfigTimeTransactionManager());
+ invocations.add("newSessionFactory");
+ return null;
+ }
+ };
+ sfb.setMappingResources(new String[]{
+ "/org/springframework/beans/factory/xml/test.xml",
+ "/org/springframework/beans/factory/xml/child.xml"});
+ sfb.setDataSource(ds);
+ sfb.setJtaTransactionManager(tm);
+ sfb.afterPropertiesSet();
+ assertTrue(sfb.getConfiguration() != null);
+ assertEquals("addResource", invocations.get(0));
+ assertEquals("addResource", invocations.get(1));
+ assertEquals("newSessionFactory", invocations.get(2));
+ }
+
+ public void testLocalSessionFactoryBeanWithDataSourceAndMappingJarLocations() throws Exception {
+ final DriverManagerDataSource ds = new DriverManagerDataSource();
+ final Set invocations = new HashSet();
+ LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() {
+ protected Configuration newConfiguration() {
+ return new Configuration() {
+ public Configuration addJar(File file) {
+ invocations.add("addResource " + file.getPath());
+ return this;
+ }
+ };
+ }
+
+ protected SessionFactory newSessionFactory(Configuration config) {
+ assertEquals(LocalDataSourceConnectionProvider.class.getName(),
+ config.getProperty(Environment.CONNECTION_PROVIDER));
+ assertEquals(ds, LocalSessionFactoryBean.getConfigTimeDataSource());
+ invocations.add("newSessionFactory");
+ return null;
+ }
+ };
+ sfb.setMappingJarLocations(new Resource[]{
+ new FileSystemResource("mapping.hbm.jar"), new FileSystemResource("mapping2.hbm.jar")});
+ sfb.setDataSource(ds);
+ sfb.afterPropertiesSet();
+ assertTrue(sfb.getConfiguration() != null);
+ assertTrue(invocations.contains("addResource mapping.hbm.jar"));
+ assertTrue(invocations.contains("addResource mapping2.hbm.jar"));
+ assertTrue(invocations.contains("newSessionFactory"));
+ }
+
+ public void testLocalSessionFactoryBeanWithDataSourceAndProperties() throws Exception {
+ final DriverManagerDataSource ds = new DriverManagerDataSource();
+ final Set invocations = new HashSet();
+ LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() {
+ protected Configuration newConfiguration() {
+ return new Configuration() {
+ public Configuration addInputStream(InputStream is) {
+ try {
+ is.close();
+ }
+ catch (IOException ex) {
+ }
+ invocations.add("addResource");
+ return this;
+ }
+ };
+ }
+
+ protected SessionFactory newSessionFactory(Configuration config) {
+ assertEquals(LocalDataSourceConnectionProvider.class.getName(),
+ config.getProperty(Environment.CONNECTION_PROVIDER));
+ assertEquals(ds, LocalSessionFactoryBean.getConfigTimeDataSource());
+ assertEquals("myValue", config.getProperty("myProperty"));
+ invocations.add("newSessionFactory");
+ return null;
+ }
+ };
+ sfb.setMappingLocations(new Resource[]{
+ new ClassPathResource("/org/springframework/beans/factory/xml/test.xml")});
+ sfb.setDataSource(ds);
+ Properties prop = new Properties();
+ prop.setProperty(Environment.CONNECTION_PROVIDER, "myClass");
+ prop.setProperty("myProperty", "myValue");
+ sfb.setHibernateProperties(prop);
+ sfb.afterPropertiesSet();
+ assertTrue(sfb.getConfiguration() != null);
+ assertTrue(invocations.contains("addResource"));
+ assertTrue(invocations.contains("newSessionFactory"));
+ }
+
+ public void testLocalSessionFactoryBeanWithValidProperties() throws Exception {
+ final Set invocations = new HashSet();
+ LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() {
+ protected SessionFactory newSessionFactory(Configuration config) {
+ assertEquals(UserSuppliedConnectionProvider.class.getName(),
+ config.getProperty(Environment.CONNECTION_PROVIDER));
+ assertEquals("myValue", config.getProperty("myProperty"));
+ invocations.add("newSessionFactory");
+ return null;
+ }
+ };
+ Properties prop = new Properties();
+ prop.setProperty(Environment.CONNECTION_PROVIDER, UserSuppliedConnectionProvider.class.getName());
+ prop.setProperty("myProperty", "myValue");
+ sfb.setHibernateProperties(prop);
+ sfb.afterPropertiesSet();
+ assertTrue(sfb.getConfiguration() != null);
+ assertTrue(invocations.contains("newSessionFactory"));
+ }
+
+ public void testLocalSessionFactoryBeanWithInvalidProperties() throws Exception {
+ LocalSessionFactoryBean sfb = new LocalSessionFactoryBean();
+ sfb.setMappingResources(new String[0]);
+ Properties prop = new Properties();
+ prop.setProperty(Environment.CONNECTION_PROVIDER, "myClass");
+ sfb.setHibernateProperties(prop);
+ try {
+ sfb.afterPropertiesSet();
+ }
+ catch (HibernateException ex) {
+ // expected, provider class not found
+ }
+ }
+
+ public void testLocalSessionFactoryBeanWithInvalidMappings() throws Exception {
+ LocalSessionFactoryBean sfb = new LocalSessionFactoryBean();
+ sfb.setMappingResources(new String[]{"mapping.hbm.xml"});
+ try {
+ sfb.afterPropertiesSet();
+ }
+ catch (IOException ex) {
+ // expected, mapping resource not found
+ }
+ }
+
+ public void testLocalSessionFactoryBeanWithCustomSessionFactory() throws Exception {
+ MockControl factoryControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sessionFactory = (SessionFactory) factoryControl.getMock();
+ sessionFactory.close();
+ factoryControl.setVoidCallable(1);
+ factoryControl.replay();
+ LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() {
+ protected SessionFactory newSessionFactory(Configuration config) {
+ return sessionFactory;
+ }
+ };
+ sfb.setMappingResources(new String[0]);
+ sfb.setDataSource(new DriverManagerDataSource());
+ sfb.setExposeTransactionAwareSessionFactory(false);
+ sfb.afterPropertiesSet();
+ assertTrue(sessionFactory == sfb.getObject());
+ sfb.destroy();
+ factoryControl.verify();
+ }
+
+ public void testLocalSessionFactoryBeanWithEntityInterceptor() throws Exception {
+ LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() {
+ protected Configuration newConfiguration() {
+ return new Configuration() {
+ public Configuration setInterceptor(Interceptor interceptor) {
+ throw new IllegalArgumentException(interceptor.toString());
+ }
+ };
+ }
+ };
+ sfb.setMappingResources(new String[0]);
+ sfb.setDataSource(new DriverManagerDataSource());
+ MockControl interceptorControl = MockControl.createControl(Interceptor.class);
+ Interceptor entityInterceptor = (Interceptor) interceptorControl.getMock();
+ interceptorControl.replay();
+ sfb.setEntityInterceptor(entityInterceptor);
+ try {
+ sfb.afterPropertiesSet();
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ assertTrue("Correct exception", ex.getMessage().equals(entityInterceptor.toString()));
+ }
+ }
+
+ public void testLocalSessionFactoryBeanWithNamingStrategy() throws Exception {
+ LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() {
+ protected Configuration newConfiguration() {
+ return new Configuration() {
+ public Configuration setNamingStrategy(NamingStrategy namingStrategy) {
+ throw new IllegalArgumentException(namingStrategy.toString());
+ }
+ };
+ }
+ };
+ sfb.setMappingResources(new String[0]);
+ sfb.setDataSource(new DriverManagerDataSource());
+ sfb.setNamingStrategy(ImprovedNamingStrategy.INSTANCE);
+ try {
+ sfb.afterPropertiesSet();
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ assertTrue("Correct exception", ex.getMessage().equals(ImprovedNamingStrategy.INSTANCE.toString()));
+ }
+ }
+
+ public void testLocalSessionFactoryBeanWithCacheStrategies() throws Exception {
+ final Properties registeredClassCache = new Properties();
+ final Properties registeredCollectionCache = new Properties();
+ LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() {
+ protected Configuration newConfiguration() {
+ return new Configuration() {
+ public Configuration setCacheConcurrencyStrategy(String clazz, String concurrencyStrategy) {
+ registeredClassCache.setProperty(clazz, concurrencyStrategy);
+ return this;
+ }
+
+ public Configuration setCollectionCacheConcurrencyStrategy(String collectionRole, String concurrencyStrategy) {
+ registeredCollectionCache.setProperty(collectionRole, concurrencyStrategy);
+ return this;
+ }
+ };
+ }
+
+ protected SessionFactory newSessionFactory(Configuration config) {
+ return null;
+ }
+ };
+
+ sfb.setMappingResources(new String[0]);
+ sfb.setDataSource(new DriverManagerDataSource());
+ Properties classCache = new Properties();
+ classCache.setProperty("org.springframework.beans.TestBean", "read-write");
+ sfb.setEntityCacheStrategies(classCache);
+ Properties collectionCache = new Properties();
+ collectionCache.setProperty("org.springframework.beans.TestBean.friends", "read-only");
+ sfb.setCollectionCacheStrategies(collectionCache);
+ sfb.afterPropertiesSet();
+
+ assertEquals(classCache, registeredClassCache);
+ assertEquals(collectionCache, registeredCollectionCache);
+ }
+
+ public void testLocalSessionFactoryBeanWithCacheStrategiesAndRegions() throws Exception {
+ final Properties registeredClassCache = new Properties();
+ final Properties registeredCollectionCache = new Properties();
+ LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() {
+ protected Configuration newConfiguration() {
+ return new Configuration() {
+ public void setCacheConcurrencyStrategy(String clazz, String concurrencyStrategy, String regionName) {
+ registeredClassCache.setProperty(clazz, concurrencyStrategy + "," + regionName);
+ }
+
+ public void setCollectionCacheConcurrencyStrategy(String collectionRole, String concurrencyStrategy, String regionName) {
+ registeredCollectionCache.setProperty(collectionRole, concurrencyStrategy + "," + regionName);
+ }
+ };
+ }
+
+ protected SessionFactory newSessionFactory(Configuration config) {
+ return null;
+ }
+ };
+
+ sfb.setMappingResources(new String[0]);
+ sfb.setDataSource(new DriverManagerDataSource());
+ Properties classCache = new Properties();
+ classCache.setProperty("org.springframework.beans.TestBean", "read-write,myRegion");
+ sfb.setEntityCacheStrategies(classCache);
+ Properties collectionCache = new Properties();
+ collectionCache.setProperty("org.springframework.beans.TestBean.friends", "read-only,myRegion");
+ sfb.setCollectionCacheStrategies(collectionCache);
+ sfb.afterPropertiesSet();
+
+ assertEquals(classCache, registeredClassCache);
+ assertEquals(collectionCache, registeredCollectionCache);
+ }
+
+ public void testLocalSessionFactoryBeanWithEventListeners() throws Exception {
+ final Map registeredListeners = new HashMap();
+ LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() {
+ protected Configuration newConfiguration() {
+ return new Configuration() {
+ public void setListener(String type, Object listener) {
+ registeredListeners.put(type, listener);
+ }
+ };
+ }
+
+ protected SessionFactory newSessionFactory(Configuration config) {
+ return null;
+ }
+ };
+ sfb.setMappingResources(new String[0]);
+ sfb.setDataSource(new DriverManagerDataSource());
+ Map listeners = new HashMap();
+ listeners.put("flush", "myListener");
+ listeners.put("create", "yourListener");
+ sfb.setEventListeners(listeners);
+ sfb.afterPropertiesSet();
+ assertEquals(listeners, registeredListeners);
+ }
+
+ public void testLocalSessionFactoryBeanWithEventListenerSet() throws Exception {
+ final Map registeredListeners = new HashMap();
+ LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() {
+ protected Configuration newConfiguration() {
+ return new Configuration() {
+ public void setListeners(String type, Object[] listeners) {
+ assertTrue(listeners instanceof MergeEventListener[]);
+ registeredListeners.put(type, new HashSet(Arrays.asList(listeners)));
+ }
+ };
+ }
+
+ protected SessionFactory newSessionFactory(Configuration config) {
+ return null;
+ }
+ };
+ sfb.setMappingResources(new String[0]);
+ sfb.setDataSource(new DriverManagerDataSource());
+ Map listeners = new HashMap();
+ Set mergeSet = new HashSet();
+ mergeSet.add(new DummyMergeEventListener());
+ mergeSet.add(new DummyMergeEventListener());
+ listeners.put("merge", mergeSet);
+ sfb.setEventListeners(listeners);
+ sfb.afterPropertiesSet();
+ assertEquals(listeners, registeredListeners);
+ }
+
+ public void testLocalSessionFactoryBeanWithFilterDefinitions() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("filterDefinitions.xml", getClass()));
+ FilterTestLocalSessionFactoryBean sf = (FilterTestLocalSessionFactoryBean) xbf.getBean("&sessionFactory");
+ assertEquals(2, sf.registeredFilterDefinitions.size());
+ FilterDefinition filter1 = (FilterDefinition) sf.registeredFilterDefinitions.get(0);
+ FilterDefinition filter2 = (FilterDefinition) sf.registeredFilterDefinitions.get(1);
+
+ assertEquals("filter1", filter1.getFilterName());
+ assertEquals(2, filter1.getParameterNames().size());
+ assertEquals(Hibernate.STRING, filter1.getParameterType("param1"));
+ assertEquals(Hibernate.LONG, filter1.getParameterType("otherParam"));
+ assertEquals("someCondition", filter1.getDefaultFilterCondition());
+
+ assertEquals("filter2", filter2.getFilterName());
+ assertEquals(1, filter2.getParameterNames().size());
+ assertEquals(Hibernate.INTEGER, filter2.getParameterType("myParam"));
+ }
+
+ public void testLocalSessionFactoryBeanWithTypeDefinitions() throws Exception {
+ XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("typeDefinitions.xml", getClass()));
+ TypeTestLocalSessionFactoryBean sf = (TypeTestLocalSessionFactoryBean) xbf.getBean("&sessionFactory");
+ TypeDef type1 = (TypeDef) sf.mappings.getTypeDef("type1");
+ TypeDef type2 = (TypeDef) sf.mappings.getTypeDef("type2");
+
+ assertEquals("mypackage.MyTypeClass", type1.getTypeClass());
+ assertEquals(2, type1.getParameters().size());
+ assertEquals("value1", type1.getParameters().getProperty("param1"));
+ assertEquals("othervalue", type1.getParameters().getProperty("otherParam"));
+
+ assertEquals("mypackage.MyOtherTypeClass", type2.getTypeClass());
+ assertEquals(1, type2.getParameters().size());
+ assertEquals("myvalue", type2.getParameters().getProperty("myParam"));
+ }
+
+
+ public static class FilterTestLocalSessionFactoryBean extends LocalSessionFactoryBean {
+
+ public List registeredFilterDefinitions = new LinkedList();
+
+ protected Configuration newConfiguration() throws HibernateException {
+ return new Configuration() {
+ public void addFilterDefinition(FilterDefinition definition) {
+ registeredFilterDefinitions.add(definition);
+ }
+ };
+ }
+
+ protected SessionFactory newSessionFactory(Configuration config) {
+ return null;
+ }
+ }
+
+
+ public static class TypeTestLocalSessionFactoryBean extends LocalSessionFactoryBean {
+
+ public Mappings mappings;
+
+ protected SessionFactory newSessionFactory(Configuration config) {
+ this.mappings = config.createMappings();
+ return null;
+ }
+ }
+
+
+ public static class DummyMergeEventListener implements MergeEventListener {
+
+ public void onMerge(MergeEvent event) throws HibernateException {
+ }
+
+ public void onMerge(MergeEvent event, Map copiedAlready) throws HibernateException {
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/filterDefinitions.xml b/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/filterDefinitions.xml
new file mode 100644
index 00000000000..96b19990ac4
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/filterDefinitions.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ string
+ long
+
+
+
+
+
+
+
+ integer
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/support/HibernateDaoSupportTests.java b/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/support/HibernateDaoSupportTests.java
new file mode 100644
index 00000000000..b6d0e0e1df8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/support/HibernateDaoSupportTests.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.orm.hibernate3.support;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+import org.hibernate.SessionFactory;
+import org.easymock.MockControl;
+
+import org.springframework.orm.hibernate3.HibernateTemplate;
+
+/**
+ * @author Juergen Hoeller
+ * @since 05.03.2005
+ */
+public class HibernateDaoSupportTests extends TestCase {
+
+ public void testHibernateDaoSupportWithSessionFactory() throws Exception {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ SessionFactory sf = (SessionFactory) sfControl.getMock();
+ sfControl.replay();
+ final List test = new ArrayList();
+ HibernateDaoSupport dao = new HibernateDaoSupport() {
+ protected void initDao() {
+ test.add("test");
+ }
+ };
+ dao.setSessionFactory(sf);
+ dao.afterPropertiesSet();
+ assertEquals("Correct SessionFactory", sf, dao.getSessionFactory());
+ assertEquals("Correct HibernateTemplate", sf, dao.getHibernateTemplate().getSessionFactory());
+ assertEquals("initDao called", test.size(), 1);
+ sfControl.verify();
+ }
+
+ public void testHibernateDaoSupportWithHibernateTemplate() throws Exception {
+ HibernateTemplate template = new HibernateTemplate();
+ final List test = new ArrayList();
+ HibernateDaoSupport dao = new HibernateDaoSupport() {
+ protected void initDao() {
+ test.add("test");
+ }
+ };
+ dao.setHibernateTemplate(template);
+ dao.afterPropertiesSet();
+ assertEquals("Correct HibernateTemplate", template, dao.getHibernateTemplate());
+ assertEquals("initDao called", test.size(), 1);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/support/LobTypeTests.java b/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/support/LobTypeTests.java
new file mode 100644
index 00000000000..3be8ba5f858
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/support/LobTypeTests.java
@@ -0,0 +1,630 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.orm.hibernate3.support;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.TransactionManager;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+import org.easymock.internal.ArrayMatcher;
+import org.hibernate.SessionFactory;
+import org.hibernate.classic.Session;
+
+import org.springframework.jdbc.support.lob.LobCreator;
+import org.springframework.jdbc.support.lob.LobHandler;
+import org.springframework.orm.hibernate3.SessionFactoryUtils;
+import org.springframework.transaction.MockJtaTransaction;
+import org.springframework.transaction.support.TransactionSynchronization;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+
+/**
+ * @author Juergen Hoeller
+ * @since 05.03.2005
+ */
+public class LobTypeTests extends TestCase {
+
+ private MockControl rsControl = MockControl.createControl(ResultSet.class);
+ private ResultSet rs = (ResultSet) rsControl.getMock();
+ private MockControl psControl = MockControl.createControl(PreparedStatement.class);
+ private PreparedStatement ps = (PreparedStatement) psControl.getMock();
+
+ private MockControl lobHandlerControl = MockControl.createControl(LobHandler.class);
+ private LobHandler lobHandler = (LobHandler) lobHandlerControl.getMock();
+ private MockControl lobCreatorControl = MockControl.createControl(LobCreator.class);
+ private LobCreator lobCreator = (LobCreator) lobCreatorControl.getMock();
+
+ protected void setUp() throws SQLException {
+ lobHandler.getLobCreator();
+ lobHandlerControl.setReturnValue(lobCreator);
+ lobCreator.close();
+ lobCreatorControl.setVoidCallable(1);
+
+ rsControl.replay();
+ psControl.replay();
+ }
+
+ public void testClobStringType() throws Exception {
+ lobHandler.getClobAsString(rs, "column");
+ lobHandlerControl.setReturnValue("content");
+ lobCreator.setClobAsString(ps, 1, "content");
+ lobCreatorControl.setVoidCallable(1);
+
+ lobHandlerControl.replay();
+ lobCreatorControl.replay();
+
+ ClobStringType type = new ClobStringType(lobHandler, null);
+ assertEquals(1, type.sqlTypes().length);
+ assertEquals(Types.CLOB, type.sqlTypes()[0]);
+ assertEquals(String.class, type.returnedClass());
+ assertTrue(type.equals("content", "content"));
+ assertEquals("content", type.deepCopy("content"));
+ assertFalse(type.isMutable());
+
+ assertEquals("content", type.nullSafeGet(rs, new String[] {"column"}, null));
+ TransactionSynchronizationManager.initSynchronization();
+ try {
+ type.nullSafeSet(ps, "content", 1);
+ List synchs = TransactionSynchronizationManager.getSynchronizations();
+ assertEquals(1, synchs.size());
+ assertTrue(synchs.get(0).getClass().getName().endsWith("SpringLobCreatorSynchronization"));
+ ((TransactionSynchronization) synchs.get(0)).beforeCompletion();
+ ((TransactionSynchronization) synchs.get(0)).afterCompletion(TransactionSynchronization.STATUS_COMMITTED);
+ }
+ finally {
+ TransactionSynchronizationManager.clearSynchronization();
+ }
+ }
+
+ public void testClobStringTypeWithSynchronizedSession() throws Exception {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ lobHandler.getClobAsString(rs, "column");
+ lobHandlerControl.setReturnValue("content");
+ lobCreator.setClobAsString(ps, 1, "content");
+ lobCreatorControl.setVoidCallable(1);
+
+ lobHandlerControl.replay();
+ lobCreatorControl.replay();
+
+ ClobStringType type = new ClobStringType(lobHandler, null);
+ assertEquals(1, type.sqlTypes().length);
+ assertEquals(Types.CLOB, type.sqlTypes()[0]);
+ assertEquals(String.class, type.returnedClass());
+ assertTrue(type.equals("content", "content"));
+ assertEquals("content", type.deepCopy("content"));
+ assertFalse(type.isMutable());
+
+ assertEquals("content", type.nullSafeGet(rs, new String[] {"column"}, null));
+ TransactionSynchronizationManager.initSynchronization();
+ try {
+ SessionFactoryUtils.getSession(sf, true);
+ type.nullSafeSet(ps, "content", 1);
+ List synchs = TransactionSynchronizationManager.getSynchronizations();
+ assertEquals(2, synchs.size());
+ assertTrue(synchs.get(0).getClass().getName().endsWith("SpringLobCreatorSynchronization"));
+ ((TransactionSynchronization) synchs.get(0)).beforeCompletion();
+ ((TransactionSynchronization) synchs.get(0)).afterCompletion(TransactionSynchronization.STATUS_COMMITTED);
+ ((TransactionSynchronization) synchs.get(1)).beforeCompletion();
+ ((TransactionSynchronization) synchs.get(1)).afterCompletion(TransactionSynchronization.STATUS_COMMITTED);
+ }
+ finally {
+ TransactionSynchronizationManager.clearSynchronization();
+ }
+
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testClobStringTypeWithFlushOnCommit() throws Exception {
+ lobHandler.getClobAsString(rs, "column");
+ lobHandlerControl.setReturnValue("content");
+ lobCreator.setClobAsString(ps, 1, "content");
+ lobCreatorControl.setVoidCallable(1);
+
+ lobHandlerControl.replay();
+ lobCreatorControl.replay();
+
+ ClobStringType type = new ClobStringType(lobHandler, null);
+ assertEquals(1, type.sqlTypes().length);
+ assertEquals(Types.CLOB, type.sqlTypes()[0]);
+ assertEquals(String.class, type.returnedClass());
+ assertTrue(type.equals("content", "content"));
+ assertEquals("content", type.deepCopy("content"));
+ assertFalse(type.isMutable());
+
+ assertEquals("content", type.nullSafeGet(rs, new String[] {"column"}, null));
+ TransactionSynchronizationManager.initSynchronization();
+ try {
+ type.nullSafeSet(ps, "content", 1);
+ List synchs = TransactionSynchronizationManager.getSynchronizations();
+ assertEquals(1, synchs.size());
+ ((TransactionSynchronization) synchs.get(0)).afterCompletion(TransactionSynchronization.STATUS_COMMITTED);
+ }
+ finally {
+ TransactionSynchronizationManager.clearSynchronization();
+ }
+ }
+
+ public void testClobStringTypeWithJtaSynchronization() throws Exception {
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockJtaTransaction transaction = new MockJtaTransaction();
+ tm.getStatus();
+ tmControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction, 1);
+
+ lobHandler.getClobAsString(rs, "column");
+ lobHandlerControl.setReturnValue("content");
+ lobCreator.setClobAsString(ps, 1, "content");
+ lobCreatorControl.setVoidCallable(1);
+
+ lobHandlerControl.replay();
+ lobCreatorControl.replay();
+
+ ClobStringType type = new ClobStringType(lobHandler, tm);
+ assertEquals("content", type.nullSafeGet(rs, new String[] {"column"}, null));
+ tmControl.replay();
+ type.nullSafeSet(ps, "content", 1);
+ Synchronization synch = transaction.getSynchronization();
+ assertNotNull(synch);
+ synch.beforeCompletion();
+ synch.afterCompletion(Status.STATUS_COMMITTED);
+ tmControl.verify();
+ }
+
+ public void testClobStringTypeWithJtaSynchronizationAndRollback() throws Exception {
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockJtaTransaction transaction = new MockJtaTransaction();
+ tm.getStatus();
+ tmControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction, 1);
+
+ lobHandler.getClobAsString(rs, "column");
+ lobHandlerControl.setReturnValue("content");
+ lobCreator.setClobAsString(ps, 1, "content");
+ lobCreatorControl.setVoidCallable(1);
+
+ lobHandlerControl.replay();
+ lobCreatorControl.replay();
+
+ ClobStringType type = new ClobStringType(lobHandler, tm);
+ assertEquals("content", type.nullSafeGet(rs, new String[] {"column"}, null));
+ tmControl.replay();
+ type.nullSafeSet(ps, "content", 1);
+ Synchronization synch = transaction.getSynchronization();
+ assertNotNull(synch);
+ synch.afterCompletion(Status.STATUS_ROLLEDBACK);
+ tmControl.verify();
+ }
+
+ public void testBlobStringType() throws Exception {
+ String content = "content";
+ byte[] contentBytes = content.getBytes();
+ lobHandler.getBlobAsBytes(rs, "column");
+ lobHandlerControl.setReturnValue(contentBytes);
+ lobCreator.setBlobAsBytes(ps, 1, contentBytes);
+ lobCreatorControl.setMatcher(new ArrayMatcher());
+
+ lobHandlerControl.replay();
+ lobCreatorControl.replay();
+
+ BlobStringType type = new BlobStringType(lobHandler, null);
+ assertEquals(1, type.sqlTypes().length);
+ assertEquals(Types.BLOB, type.sqlTypes()[0]);
+ assertEquals(String.class, type.returnedClass());
+ assertTrue(type.equals("content", "content"));
+ assertEquals("content", type.deepCopy("content"));
+ assertFalse(type.isMutable());
+
+ assertEquals(content, type.nullSafeGet(rs, new String[] {"column"}, null));
+ TransactionSynchronizationManager.initSynchronization();
+ try {
+ type.nullSafeSet(ps, content, 1);
+ List synchs = TransactionSynchronizationManager.getSynchronizations();
+ assertEquals(1, synchs.size());
+ ((TransactionSynchronization) synchs.get(0)).beforeCompletion();
+ ((TransactionSynchronization) synchs.get(0)).afterCompletion(TransactionSynchronization.STATUS_COMMITTED);
+ }
+ finally {
+ TransactionSynchronizationManager.clearSynchronization();
+ }
+ }
+
+ public void testBlobStringTypeWithNull() throws Exception {
+ lobHandler.getBlobAsBytes(rs, "column");
+ lobHandlerControl.setReturnValue(null);
+ lobCreator.setBlobAsBytes(ps, 1, null);
+
+ lobHandlerControl.replay();
+ lobCreatorControl.replay();
+
+ BlobStringType type = new BlobStringType(lobHandler, null);
+ assertEquals(null, type.nullSafeGet(rs, new String[] {"column"}, null));
+ TransactionSynchronizationManager.initSynchronization();
+ try {
+ type.nullSafeSet(ps, null, 1);
+ List synchs = TransactionSynchronizationManager.getSynchronizations();
+ assertEquals(1, synchs.size());
+ ((TransactionSynchronization) synchs.get(0)).beforeCompletion();
+ }
+ finally {
+ TransactionSynchronizationManager.clearSynchronization();
+ }
+ }
+
+ public void testBlobStringTypeWithJtaSynchronization() throws Exception {
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockJtaTransaction transaction = new MockJtaTransaction();
+ tm.getStatus();
+ tmControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction, 1);
+
+ String content = "content";
+ byte[] contentBytes = content.getBytes();
+ lobHandler.getBlobAsBytes(rs, "column");
+ lobHandlerControl.setReturnValue(contentBytes);
+ lobCreator.setBlobAsBytes(ps, 1, contentBytes);
+ lobCreatorControl.setMatcher(new ArrayMatcher());
+
+ lobHandlerControl.replay();
+ lobCreatorControl.replay();
+
+ BlobStringType type = new BlobStringType(lobHandler, tm);
+ assertEquals(content, type.nullSafeGet(rs, new String[] {"column"}, null));
+ tmControl.replay();
+ type.nullSafeSet(ps, content, 1);
+ Synchronization synch = transaction.getSynchronization();
+ assertNotNull(synch);
+ synch.beforeCompletion();
+ synch.afterCompletion(Status.STATUS_COMMITTED);
+ tmControl.verify();
+ }
+
+ public void testBlobStringTypeWithJtaSynchronizationAndRollback() throws Exception {
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockJtaTransaction transaction = new MockJtaTransaction();
+ tm.getStatus();
+ tmControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction, 1);
+
+ String content = "content";
+ byte[] contentBytes = content.getBytes();
+ lobHandler.getBlobAsBytes(rs, "column");
+ lobHandlerControl.setReturnValue(contentBytes);
+ lobCreator.setBlobAsBytes(ps, 1, contentBytes);
+ lobCreatorControl.setMatcher(new ArrayMatcher());
+
+ lobHandlerControl.replay();
+ lobCreatorControl.replay();
+
+ BlobStringType type = new BlobStringType(lobHandler, tm);
+ assertEquals(content, type.nullSafeGet(rs, new String[] {"column"}, null));
+ tmControl.replay();
+ type.nullSafeSet(ps, content, 1);
+ Synchronization synch = transaction.getSynchronization();
+ assertNotNull(synch);
+ synch.afterCompletion(Status.STATUS_ROLLEDBACK);
+ tmControl.verify();
+ }
+
+ public void testBlobByteArrayType() throws Exception {
+ byte[] content = "content".getBytes();
+ lobHandler.getBlobAsBytes(rs, "column");
+ lobHandlerControl.setReturnValue(content);
+ lobCreator.setBlobAsBytes(ps, 1, content);
+ lobCreatorControl.setVoidCallable(1);
+
+ lobHandlerControl.replay();
+ lobCreatorControl.replay();
+
+ BlobByteArrayType type = new BlobByteArrayType(lobHandler, null);
+ assertEquals(1, type.sqlTypes().length);
+ assertEquals(Types.BLOB, type.sqlTypes()[0]);
+ assertEquals(byte[].class, type.returnedClass());
+ assertTrue(type.equals(new byte[] {(byte) 255}, new byte[] {(byte) 255}));
+ assertTrue(Arrays.equals(new byte[] {(byte) 255}, (byte[]) type.deepCopy(new byte[] {(byte) 255})));
+ assertTrue(type.isMutable());
+
+ assertEquals(content, type.nullSafeGet(rs, new String[] {"column"}, null));
+ TransactionSynchronizationManager.initSynchronization();
+ try {
+ type.nullSafeSet(ps, content, 1);
+ List synchs = TransactionSynchronizationManager.getSynchronizations();
+ assertEquals(1, synchs.size());
+ ((TransactionSynchronization) synchs.get(0)).beforeCompletion();
+ ((TransactionSynchronization) synchs.get(0)).afterCompletion(TransactionSynchronization.STATUS_COMMITTED);
+ }
+ finally {
+ TransactionSynchronizationManager.clearSynchronization();
+ }
+ }
+
+ public void testBlobByteArrayTypeWithJtaSynchronization() throws Exception {
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockJtaTransaction transaction = new MockJtaTransaction();
+ tm.getStatus();
+ tmControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction, 1);
+
+ byte[] content = "content".getBytes();
+ lobHandler.getBlobAsBytes(rs, "column");
+ lobHandlerControl.setReturnValue(content);
+ lobCreator.setBlobAsBytes(ps, 1, content);
+ lobCreatorControl.setVoidCallable(1);
+
+ lobHandlerControl.replay();
+ lobCreatorControl.replay();
+
+ BlobByteArrayType type = new BlobByteArrayType(lobHandler, tm);
+ assertEquals(content, type.nullSafeGet(rs, new String[] {"column"}, null));
+ tmControl.replay();
+ type.nullSafeSet(ps, content, 1);
+ Synchronization synch = transaction.getSynchronization();
+ assertNotNull(synch);
+ synch.beforeCompletion();
+ synch.afterCompletion(Status.STATUS_COMMITTED);
+ tmControl.verify();
+ }
+
+ public void testBlobByteArrayTypeWithJtaSynchronizationAndRollback() throws Exception {
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockJtaTransaction transaction = new MockJtaTransaction();
+ tm.getStatus();
+ tmControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction, 1);
+
+ byte[] content = "content".getBytes();
+ lobHandler.getBlobAsBytes(rs, "column");
+ lobHandlerControl.setReturnValue(content);
+ lobCreator.setBlobAsBytes(ps, 1, content);
+ lobCreatorControl.setVoidCallable(1);
+
+ lobHandlerControl.replay();
+ lobCreatorControl.replay();
+
+ BlobByteArrayType type = new BlobByteArrayType(lobHandler, tm);
+ assertEquals(content, type.nullSafeGet(rs, new String[] {"column"}, null));
+ tmControl.replay();
+ type.nullSafeSet(ps, content, 1);
+ Synchronization synch = transaction.getSynchronization();
+ assertNotNull(synch);
+ synch.afterCompletion(Status.STATUS_ROLLEDBACK);
+ tmControl.verify();
+ }
+
+ public void testBlobSerializableType() throws Exception {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject("content");
+ oos.close();
+
+ lobHandler.getBlobAsBinaryStream(rs, "column");
+ lobHandlerControl.setReturnValue(new ByteArrayInputStream(baos.toByteArray()));
+ lobCreator.setBlobAsBytes(ps, 1, baos.toByteArray());
+ lobCreatorControl.setMatcher(new ArrayMatcher());
+
+ lobHandlerControl.replay();
+ lobCreatorControl.replay();
+
+ BlobSerializableType type = new BlobSerializableType(lobHandler, null);
+ assertEquals(1, type.sqlTypes().length);
+ assertEquals(Types.BLOB, type.sqlTypes()[0]);
+ assertEquals(Serializable.class, type.returnedClass());
+ assertTrue(type.isMutable());
+
+ assertEquals("content", type.nullSafeGet(rs, new String[] {"column"}, null));
+ TransactionSynchronizationManager.initSynchronization();
+ try {
+ type.nullSafeSet(ps, "content", 1);
+ List synchs = TransactionSynchronizationManager.getSynchronizations();
+ assertEquals(1, synchs.size());
+ ((TransactionSynchronization) synchs.get(0)).beforeCompletion();
+ ((TransactionSynchronization) synchs.get(0)).afterCompletion(TransactionSynchronization.STATUS_COMMITTED);
+ }
+ finally {
+ TransactionSynchronizationManager.clearSynchronization();
+ }
+ }
+
+ public void testBlobSerializableTypeWithNull() throws Exception {
+ lobHandler.getBlobAsBinaryStream(rs, "column");
+ lobHandlerControl.setReturnValue(null);
+ lobCreator.setBlobAsBytes(ps, 1, null);
+
+ lobHandlerControl.replay();
+ lobCreatorControl.replay();
+
+ BlobSerializableType type = new BlobSerializableType(lobHandler, null);
+ assertEquals(null, type.nullSafeGet(rs, new String[] {"column"}, null));
+ TransactionSynchronizationManager.initSynchronization();
+ try {
+ type.nullSafeSet(ps, null, 1);
+ List synchs = TransactionSynchronizationManager.getSynchronizations();
+ assertEquals(1, synchs.size());
+ ((TransactionSynchronization) synchs.get(0)).beforeCompletion();
+ }
+ finally {
+ TransactionSynchronizationManager.clearSynchronization();
+ }
+ }
+
+ public void testBlobSerializableTypeWithJtaSynchronization() throws Exception {
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockJtaTransaction transaction = new MockJtaTransaction();
+ tm.getStatus();
+ tmControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction, 1);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject("content");
+ oos.close();
+
+ lobHandler.getBlobAsBinaryStream(rs, "column");
+ lobHandlerControl.setReturnValue(new ByteArrayInputStream(baos.toByteArray()));
+ lobCreator.setBlobAsBytes(ps, 1, baos.toByteArray());
+ lobCreatorControl.setMatcher(new ArrayMatcher());
+
+ lobHandlerControl.replay();
+ lobCreatorControl.replay();
+
+ BlobSerializableType type = new BlobSerializableType(lobHandler, tm);
+ assertEquals(1, type.sqlTypes().length);
+ assertEquals(Types.BLOB, type.sqlTypes()[0]);
+ assertEquals(Serializable.class, type.returnedClass());
+ assertTrue(type.isMutable());
+
+ assertEquals("content", type.nullSafeGet(rs, new String[] {"column"}, null));
+ tmControl.replay();
+ type.nullSafeSet(ps, "content", 1);
+ Synchronization synch = transaction.getSynchronization();
+ assertNotNull(synch);
+ synch.beforeCompletion();
+ synch.afterCompletion(Status.STATUS_COMMITTED);
+ tmControl.verify();
+ }
+
+ public void testBlobSerializableTypeWithJtaSynchronizationAndRollback() throws Exception {
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockJtaTransaction transaction = new MockJtaTransaction();
+ tm.getStatus();
+ tmControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction, 1);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject("content");
+ oos.close();
+
+ lobHandler.getBlobAsBinaryStream(rs, "column");
+ lobHandlerControl.setReturnValue(new ByteArrayInputStream(baos.toByteArray()));
+ lobCreator.setBlobAsBytes(ps, 1, baos.toByteArray());
+ lobCreatorControl.setMatcher(new ArrayMatcher());
+
+ lobHandlerControl.replay();
+ lobCreatorControl.replay();
+
+ BlobSerializableType type = new BlobSerializableType(lobHandler, tm);
+ assertEquals(1, type.sqlTypes().length);
+ assertEquals(Types.BLOB, type.sqlTypes()[0]);
+ assertEquals(Serializable.class, type.returnedClass());
+ assertTrue(type.isMutable());
+
+ assertEquals("content", type.nullSafeGet(rs, new String[] {"column"}, null));
+ tmControl.replay();
+ type.nullSafeSet(ps, "content", 1);
+ Synchronization synch = transaction.getSynchronization();
+ assertNotNull(synch);
+ synch.afterCompletion(Status.STATUS_ROLLEDBACK);
+ tmControl.verify();
+ }
+
+ public void testHbm2JavaStyleInitialization() throws Exception {
+ rsControl.reset();
+ psControl.reset();
+ lobHandlerControl.reset();
+ lobCreatorControl.reset();
+
+ ClobStringType cst = null;
+ BlobByteArrayType bbat = null;
+ BlobSerializableType bst = null;
+ try {
+ cst = new ClobStringType();
+ bbat = new BlobByteArrayType();
+ bst = new BlobSerializableType();
+ }
+ catch (Exception ex) {
+ fail("Should not have thrown exception on initialization");
+ }
+
+ try {
+ cst.nullSafeGet(rs, new String[] {"column"}, null);
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ try {
+ bbat.nullSafeGet(rs, new String[] {"column"}, null);
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ try {
+ bst.nullSafeGet(rs, new String[] {"column"}, null);
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ protected void tearDown() {
+ try {
+ rsControl.verify();
+ psControl.verify();
+ lobHandlerControl.verify();
+ lobCreatorControl.verify();
+ }
+ catch (IllegalStateException ex) {
+ // ignore: test method didn't call replay
+ }
+ assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/support/OpenSessionInViewTests.java b/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/support/OpenSessionInViewTests.java
new file mode 100644
index 00000000000..e8bbea99e83
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/support/OpenSessionInViewTests.java
@@ -0,0 +1,661 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.orm.hibernate3.support;
+
+import java.io.IOException;
+import java.sql.Connection;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.transaction.TransactionManager;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+import org.hibernate.FlushMode;
+import org.hibernate.HibernateException;
+import org.hibernate.SessionFactory;
+import org.hibernate.Transaction;
+import org.hibernate.classic.Session;
+import org.hibernate.engine.SessionFactoryImplementor;
+
+import org.springframework.mock.web.MockFilterConfig;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.mock.web.PassThroughFilterChain;
+import org.springframework.orm.hibernate3.HibernateAccessor;
+import org.springframework.orm.hibernate3.HibernateTransactionManager;
+import org.springframework.orm.hibernate3.SessionFactoryUtils;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.support.DefaultTransactionDefinition;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.StaticWebApplicationContext;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapter;
+
+/**
+ * @author Juergen Hoeller
+ * @since 05.03.2005
+ */
+public class OpenSessionInViewTests extends TestCase {
+
+ public void testOpenSessionInViewInterceptorWithSingleSession() throws Exception {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+
+ OpenSessionInViewInterceptor rawInterceptor = new OpenSessionInViewInterceptor();
+ rawInterceptor.setSessionFactory(sf);
+ HandlerInterceptor interceptor = new WebRequestHandlerInterceptorAdapter(rawInterceptor);
+
+ MockServletContext sc = new MockServletContext();
+ MockHttpServletRequest request = new MockHttpServletRequest(sc);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 2);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.setFlushMode(FlushMode.NEVER);
+ sessionControl.setVoidCallable(1);
+ sfControl.replay();
+ sessionControl.replay();
+ interceptor.preHandle(request, response, "handler");
+ assertTrue(TransactionSynchronizationManager.hasResource(sf));
+
+ // check that further invocations simply participate
+ interceptor.preHandle(request, response, "handler");
+
+ assertEquals(session, SessionFactoryUtils.getSession(sf, false));
+
+ interceptor.preHandle(request, response, "handler");
+ interceptor.postHandle(request, response, "handler", null);
+ interceptor.afterCompletion(request, response, "handler", null);
+
+ interceptor.postHandle(request, response, "handler", null);
+ interceptor.afterCompletion(request, response, "handler", null);
+
+ interceptor.preHandle(request, response, "handler");
+ interceptor.postHandle(request, response, "handler", null);
+ interceptor.afterCompletion(request, response, "handler", null);
+
+ sfControl.verify();
+ sessionControl.verify();
+
+ sfControl.reset();
+ sessionControl.reset();
+ sfControl.replay();
+ sessionControl.replay();
+ interceptor.postHandle(request, response, "handler", null);
+ assertTrue(TransactionSynchronizationManager.hasResource(sf));
+ sfControl.verify();
+ sessionControl.verify();
+
+ sfControl.reset();
+ sessionControl.reset();
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ interceptor.afterCompletion(request, response, "handler", null);
+ assertFalse(TransactionSynchronizationManager.hasResource(sf));
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testOpenSessionInViewInterceptorWithSingleSessionAndJtaTm() throws Exception {
+ MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
+ final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ tm.getTransaction();
+ tmControl.setReturnValue(null, 2);
+
+ OpenSessionInViewInterceptor rawInterceptor = new OpenSessionInViewInterceptor();
+ rawInterceptor.setSessionFactory(sf);
+ HandlerInterceptor interceptor = new WebRequestHandlerInterceptorAdapter(rawInterceptor);
+
+ MockServletContext sc = new MockServletContext();
+ MockHttpServletRequest request = new MockHttpServletRequest(sc);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ sf.getTransactionManager();
+ sfControl.setReturnValue(tm, 2);
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.isOpen();
+ sessionControl.setReturnValue(true, 1);
+ session.setFlushMode(FlushMode.NEVER);
+ sessionControl.setVoidCallable(1);
+
+ tmControl.replay();
+ sfControl.replay();
+ sessionControl.replay();
+
+ interceptor.preHandle(request, response, "handler");
+ assertTrue(TransactionSynchronizationManager.hasResource(sf));
+
+ // check that further invocations simply participate
+ interceptor.preHandle(request, response, "handler");
+
+ assertEquals(session, SessionFactoryUtils.getSession(sf, false));
+
+ interceptor.preHandle(request, response, "handler");
+ interceptor.postHandle(request, response, "handler", null);
+ interceptor.afterCompletion(request, response, "handler", null);
+
+ interceptor.postHandle(request, response, "handler", null);
+ interceptor.afterCompletion(request, response, "handler", null);
+
+ interceptor.preHandle(request, response, "handler");
+ interceptor.postHandle(request, response, "handler", null);
+ interceptor.afterCompletion(request, response, "handler", null);
+
+ sfControl.verify();
+ sessionControl.verify();
+
+ sfControl.reset();
+ sessionControl.reset();
+ sfControl.replay();
+ sessionControl.replay();
+ interceptor.postHandle(request, response, "handler", null);
+ assertTrue(TransactionSynchronizationManager.hasResource(sf));
+ sfControl.verify();
+ sessionControl.verify();
+
+ sfControl.reset();
+ sessionControl.reset();
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ interceptor.afterCompletion(request, response, "handler", null);
+ assertFalse(TransactionSynchronizationManager.hasResource(sf));
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testOpenSessionInViewInterceptorWithSingleSessionAndFlush() throws Exception {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+
+ OpenSessionInViewInterceptor rawInterceptor = new OpenSessionInViewInterceptor();
+ rawInterceptor.setSessionFactory(sf);
+ rawInterceptor.setFlushMode(HibernateAccessor.FLUSH_AUTO);
+ HandlerInterceptor interceptor = new WebRequestHandlerInterceptorAdapter(rawInterceptor);
+
+ MockServletContext sc = new MockServletContext();
+ MockHttpServletRequest request = new MockHttpServletRequest(sc);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf);
+ sfControl.replay();
+ sessionControl.replay();
+ interceptor.preHandle(request, response, "handler");
+ assertTrue(TransactionSynchronizationManager.hasResource(sf));
+ sfControl.verify();
+ sessionControl.verify();
+
+ sfControl.reset();
+ sessionControl.reset();
+ session.flush();
+ sessionControl.setVoidCallable(1);
+ sfControl.replay();
+ sessionControl.replay();
+ interceptor.postHandle(request, response, "handler", null);
+ assertTrue(TransactionSynchronizationManager.hasResource(sf));
+ sfControl.verify();
+ sessionControl.verify();
+
+ sfControl.reset();
+ sessionControl.reset();
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+ interceptor.afterCompletion(request, response, "handler", null);
+ assertFalse(TransactionSynchronizationManager.hasResource(sf));
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testOpenSessionInViewInterceptorAndDeferredClose() throws Exception {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+
+ OpenSessionInViewInterceptor rawInterceptor = new OpenSessionInViewInterceptor();
+ rawInterceptor.setSessionFactory(sf);
+ rawInterceptor.setSingleSession(false);
+ HandlerInterceptor interceptor = new WebRequestHandlerInterceptorAdapter(rawInterceptor);
+
+ MockServletContext sc = new MockServletContext();
+ MockHttpServletRequest request = new MockHttpServletRequest(sc);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf, 1);
+ session.setFlushMode(FlushMode.NEVER);
+ sessionControl.setVoidCallable(1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ interceptor.preHandle(request, response, "handler");
+ org.hibernate.Session sess = SessionFactoryUtils.getSession(sf, true);
+ SessionFactoryUtils.releaseSession(sess, sf);
+
+ // check that further invocations simply participate
+ interceptor.preHandle(request, response, "handler");
+
+ interceptor.preHandle(request, response, "handler");
+ interceptor.postHandle(request, response, "handler", null);
+ interceptor.afterCompletion(request, response, "handler", null);
+
+ interceptor.postHandle(request, response, "handler", null);
+ interceptor.afterCompletion(request, response, "handler", null);
+
+ interceptor.preHandle(request, response, "handler");
+ interceptor.postHandle(request, response, "handler", null);
+ interceptor.afterCompletion(request, response, "handler", null);
+
+ sfControl.verify();
+ sessionControl.verify();
+ sfControl.reset();
+ sessionControl.reset();
+
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ interceptor.postHandle(request, response, "handler", null);
+ interceptor.afterCompletion(request, response, "handler", null);
+ sfControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testOpenSessionInViewFilterWithSingleSession() throws Exception {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf);
+ session.setFlushMode(FlushMode.NEVER);
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ MockControl sf2Control = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf2 = (SessionFactory) sf2Control.getMock();
+ MockControl session2Control = MockControl.createControl(Session.class);
+ Session session2 = (Session) session2Control.getMock();
+
+ sf2.openSession();
+ sf2Control.setReturnValue(session2, 1);
+ session2.getSessionFactory();
+ session2Control.setReturnValue(sf);
+ session2.setFlushMode(FlushMode.AUTO);
+ session2Control.setVoidCallable(1);
+ session2.close();
+ session2Control.setReturnValue(null, 1);
+ sf2Control.replay();
+ session2Control.replay();
+
+ MockServletContext sc = new MockServletContext();
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(sc);
+ wac.getDefaultListableBeanFactory().registerSingleton("sessionFactory", sf);
+ wac.getDefaultListableBeanFactory().registerSingleton("mySessionFactory", sf2);
+ wac.refresh();
+ sc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
+ MockHttpServletRequest request = new MockHttpServletRequest(sc);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ MockFilterConfig filterConfig = new MockFilterConfig(wac.getServletContext(), "filter");
+ MockFilterConfig filterConfig2 = new MockFilterConfig(wac.getServletContext(), "filter2");
+ filterConfig2.addInitParameter("sessionFactoryBeanName", "mySessionFactory");
+ filterConfig2.addInitParameter("flushMode", "AUTO");
+
+ final OpenSessionInViewFilter filter = new OpenSessionInViewFilter();
+ filter.init(filterConfig);
+ final OpenSessionInViewFilter filter2 = new OpenSessionInViewFilter();
+ filter2.init(filterConfig2);
+
+ final FilterChain filterChain = new FilterChain() {
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) {
+ assertTrue(TransactionSynchronizationManager.hasResource(sf));
+ servletRequest.setAttribute("invoked", Boolean.TRUE);
+ }
+ };
+
+ final FilterChain filterChain2 = new FilterChain() {
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse)
+ throws IOException, ServletException {
+ assertTrue(TransactionSynchronizationManager.hasResource(sf2));
+ filter.doFilter(servletRequest, servletResponse, filterChain);
+ }
+ };
+
+ FilterChain filterChain3 = new PassThroughFilterChain(filter2, filterChain2);
+
+ assertFalse(TransactionSynchronizationManager.hasResource(sf));
+ assertFalse(TransactionSynchronizationManager.hasResource(sf2));
+ filter2.doFilter(request, response, filterChain3);
+ assertFalse(TransactionSynchronizationManager.hasResource(sf));
+ assertFalse(TransactionSynchronizationManager.hasResource(sf2));
+ assertNotNull(request.getAttribute("invoked"));
+
+ sfControl.verify();
+ sessionControl.verify();
+ sf2Control.verify();
+ session2Control.verify();
+
+ wac.close();
+ }
+
+ public void testOpenSessionInViewFilterWithSingleSessionAndPreBoundSession() throws Exception {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf);
+ session.setFlushMode(FlushMode.NEVER);
+ sessionControl.setVoidCallable(1);
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ MockServletContext sc = new MockServletContext();
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(sc);
+ wac.getDefaultListableBeanFactory().registerSingleton("sessionFactory", sf);
+ wac.refresh();
+ sc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
+ MockHttpServletRequest request = new MockHttpServletRequest(sc);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ MockFilterConfig filterConfig = new MockFilterConfig(wac.getServletContext(), "filter");
+ MockFilterConfig filterConfig2 = new MockFilterConfig(wac.getServletContext(), "filter2");
+ filterConfig2.addInitParameter("sessionFactoryBeanName", "mySessionFactory");
+
+ OpenSessionInViewInterceptor rawInterceptor = new OpenSessionInViewInterceptor();
+ rawInterceptor.setSessionFactory(sf);
+ HandlerInterceptor interceptor = new WebRequestHandlerInterceptorAdapter(rawInterceptor);
+
+ interceptor.preHandle(request, response, "handler");
+
+ final OpenSessionInViewFilter filter = new OpenSessionInViewFilter();
+ filter.init(filterConfig);
+
+ final FilterChain filterChain = new FilterChain() {
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) {
+ assertTrue(TransactionSynchronizationManager.hasResource(sf));
+ servletRequest.setAttribute("invoked", Boolean.TRUE);
+ }
+ };
+
+ assertTrue(TransactionSynchronizationManager.hasResource(sf));
+ filter.doFilter(request, response, filterChain);
+ assertTrue(TransactionSynchronizationManager.hasResource(sf));
+ assertNotNull(request.getAttribute("invoked"));
+
+ interceptor.postHandle(request, response, "handler", null);
+ interceptor.afterCompletion(request, response, "handler", null);
+
+ sfControl.verify();
+ sessionControl.verify();
+
+ wac.close();
+ }
+
+ public void testOpenSessionInViewFilterWithDeferredClose() throws Exception {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ final MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.NEVER, 1);
+ session.setFlushMode(FlushMode.NEVER);
+ sessionControl.setVoidCallable(1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ MockControl sf2Control = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf2 = (SessionFactory) sf2Control.getMock();
+ final MockControl session2Control = MockControl.createControl(Session.class);
+ final Session session2 = (Session) session2Control.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ Connection con = (Connection) conControl.getMock();
+
+ sf2.openSession();
+ sf2Control.setReturnValue(session2, 1);
+ session2.beginTransaction();
+ session2Control.setReturnValue(tx, 1);
+ session2.connection();
+ session2Control.setReturnValue(con, 2);
+ tx.commit();
+ txControl.setVoidCallable(1);
+ session2.isConnected();
+ session2Control.setReturnValue(true, 1);
+ con.isReadOnly();
+ conControl.setReturnValue(false, 1);
+ session2.setFlushMode(FlushMode.NEVER);
+ session2Control.setVoidCallable(1);
+
+ sf2Control.replay();
+ session2Control.replay();
+ txControl.replay();
+ conControl.replay();
+
+ MockServletContext sc = new MockServletContext();
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(sc);
+ wac.getDefaultListableBeanFactory().registerSingleton("sessionFactory", sf);
+ wac.getDefaultListableBeanFactory().registerSingleton("mySessionFactory", sf2);
+ wac.refresh();
+ sc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
+ MockHttpServletRequest request = new MockHttpServletRequest(sc);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ MockFilterConfig filterConfig = new MockFilterConfig(wac.getServletContext(), "filter");
+ MockFilterConfig filterConfig2 = new MockFilterConfig(wac.getServletContext(), "filter2");
+ filterConfig.addInitParameter("singleSession", "false");
+ filterConfig2.addInitParameter("singleSession", "false");
+ filterConfig2.addInitParameter("sessionFactoryBeanName", "mySessionFactory");
+
+ final OpenSessionInViewFilter filter = new OpenSessionInViewFilter();
+ filter.init(filterConfig);
+ final OpenSessionInViewFilter filter2 = new OpenSessionInViewFilter();
+ filter2.init(filterConfig2);
+
+ final FilterChain filterChain = new FilterChain() {
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) {
+ HibernateTransactionManager tm = new HibernateTransactionManager(sf);
+ TransactionStatus ts = tm.getTransaction(
+ new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_SUPPORTS));
+ org.hibernate.Session sess = SessionFactoryUtils.getSession(sf, true);
+ SessionFactoryUtils.releaseSession(sess, sf);
+ tm.commit(ts);
+
+ sessionControl.verify();
+ sessionControl.reset();
+
+ session.close();
+ sessionControl.setReturnValue(null, 1);
+ sessionControl.replay();
+
+ servletRequest.setAttribute("invoked", Boolean.TRUE);
+ }
+ };
+
+ final FilterChain filterChain2 = new FilterChain() {
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse)
+ throws IOException, ServletException {
+
+ HibernateTransactionManager tm = new HibernateTransactionManager(sf2);
+ TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition());
+ tm.commit(ts);
+
+ session2Control.verify();
+ session2Control.reset();
+
+ session2.close();
+ session2Control.setReturnValue(null, 1);
+ session2Control.replay();
+
+ filter.doFilter(servletRequest, servletResponse, filterChain);
+ }
+ };
+
+ FilterChain filterChain3 = new PassThroughFilterChain(filter2, filterChain2);
+
+ filter2.doFilter(request, response, filterChain3);
+ assertNotNull(request.getAttribute("invoked"));
+
+ sfControl.verify();
+ sessionControl.verify();
+ sf2Control.verify();
+ session2Control.verify();
+ txControl.verify();
+ conControl.verify();
+
+ wac.close();
+ }
+
+ public void testOpenSessionInViewFilterWithDeferredCloseAndAlreadyActiveDeferredClose() throws Exception {
+ MockControl sfControl = MockControl.createControl(SessionFactory.class);
+ final SessionFactory sf = (SessionFactory) sfControl.getMock();
+ final MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+
+ sf.openSession();
+ sfControl.setReturnValue(session, 1);
+ session.getSessionFactory();
+ sessionControl.setReturnValue(sf);
+ session.getFlushMode();
+ sessionControl.setReturnValue(FlushMode.NEVER, 1);
+ session.setFlushMode(FlushMode.NEVER);
+ sessionControl.setVoidCallable(1);
+ sfControl.replay();
+ sessionControl.replay();
+
+ MockServletContext sc = new MockServletContext();
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(sc);
+ wac.getDefaultListableBeanFactory().registerSingleton("sessionFactory", sf);
+ wac.refresh();
+ sc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
+ MockHttpServletRequest request = new MockHttpServletRequest(sc);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ MockFilterConfig filterConfig = new MockFilterConfig(wac.getServletContext(), "filter");
+ MockFilterConfig filterConfig2 = new MockFilterConfig(wac.getServletContext(), "filter2");
+ filterConfig.addInitParameter("singleSession", "false");
+ filterConfig2.addInitParameter("singleSession", "false");
+ filterConfig2.addInitParameter("sessionFactoryBeanName", "mySessionFactory");
+
+ OpenSessionInViewInterceptor rawInterceptor = new OpenSessionInViewInterceptor();
+ rawInterceptor.setSessionFactory(sf);
+ rawInterceptor.setSingleSession(false);
+ HandlerInterceptor interceptor = new WebRequestHandlerInterceptorAdapter(rawInterceptor);
+
+ interceptor.preHandle(request, response, "handler");
+
+ final OpenSessionInViewFilter filter = new OpenSessionInViewFilter();
+ filter.init(filterConfig);
+ final OpenSessionInViewFilter filter2 = new OpenSessionInViewFilter();
+ filter2.init(filterConfig2);
+
+ final FilterChain filterChain = new FilterChain() {
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) {
+ HibernateTransactionManager tm = new HibernateTransactionManager(sf);
+ TransactionStatus ts = tm.getTransaction(
+ new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_SUPPORTS));
+ org.hibernate.Session sess = SessionFactoryUtils.getSession(sf, true);
+ SessionFactoryUtils.releaseSession(sess, sf);
+ tm.commit(ts);
+
+ sessionControl.verify();
+ sessionControl.reset();
+ try {
+ session.close();
+ }
+ catch (HibernateException ex) {
+ }
+ sessionControl.setReturnValue(null, 1);
+ sessionControl.replay();
+
+ servletRequest.setAttribute("invoked", Boolean.TRUE);
+ }
+ };
+
+ FilterChain filterChain2 = new FilterChain() {
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse)
+ throws IOException, ServletException {
+ filter.doFilter(servletRequest, servletResponse, filterChain);
+ }
+ };
+
+ filter.doFilter(request, response, filterChain2);
+ assertNotNull(request.getAttribute("invoked"));
+
+ interceptor.postHandle(request, response, "handler", null);
+ interceptor.afterCompletion(request, response, "handler", null);
+
+ sfControl.verify();
+ sessionControl.verify();
+
+ wac.close();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/support/ScopedBeanInterceptorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/support/ScopedBeanInterceptorTests.java
new file mode 100644
index 00000000000..4d74833ab97
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/support/ScopedBeanInterceptorTests.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.orm.hibernate3.support;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.aop.scope.ScopedObject;
+
+/**
+ * @author Costin Leau
+ */
+public class ScopedBeanInterceptorTests extends TestCase {
+
+ public void testInterceptorWithPlainObject() throws Exception {
+ ScopedBeanInterceptor interceptor = new ScopedBeanInterceptor();
+ final Object realObject = new Object();
+
+ ScopedObject scoped = new ScopedObject() {
+ public Object getTargetObject() {
+ return realObject;
+ }
+ public void removeFromScope() {
+ // do nothing
+ }
+ };
+
+ // default contract is to return null for default behavior
+ assertEquals(null, interceptor.getEntityName(realObject));
+ assertEquals(realObject.getClass().getName(), interceptor.getEntityName(scoped));
+ }
+
+ public void testInterceptorWithCglibProxy() throws Exception {
+ ScopedBeanInterceptor interceptor = new ScopedBeanInterceptor();
+ final Object realObject = new Object();
+ ProxyFactory proxyFactory = new ProxyFactory();
+ proxyFactory.setTarget(realObject);
+ proxyFactory.setProxyTargetClass(true);
+ final Object proxy = proxyFactory.getProxy();
+
+ ScopedObject scoped = new ScopedObject() {
+ public Object getTargetObject() {
+ return proxy;
+ }
+ public void removeFromScope() {
+ // do nothing
+ }
+ };
+
+ assertEquals(realObject.getClass().getName(), interceptor.getEntityName(scoped));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/typeDefinitions.xml b/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/typeDefinitions.xml
new file mode 100644
index 00000000000..bd12f319b7f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/hibernate3/typeDefinitions.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ value1
+ othervalue
+
+
+
+
+
+
+
+
+ myvalue
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/jdo/JdoInterceptorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/orm/jdo/JdoInterceptorTests.java
new file mode 100644
index 00000000000..46093da105e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/jdo/JdoInterceptorTests.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.orm.jdo;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Method;
+
+import javax.jdo.PersistenceManager;
+import javax.jdo.PersistenceManagerFactory;
+
+import junit.framework.TestCase;
+
+import org.aopalliance.intercept.Interceptor;
+import org.aopalliance.intercept.Invocation;
+import org.aopalliance.intercept.MethodInvocation;
+import org.easymock.MockControl;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class JdoInterceptorTests extends TestCase {
+
+ public void testInterceptor() {
+ MockControl pmfControl = MockControl.createControl(PersistenceManagerFactory.class);
+ PersistenceManagerFactory pmf = (PersistenceManagerFactory) pmfControl.getMock();
+ MockControl pmControl = MockControl.createControl(PersistenceManager.class);
+ PersistenceManager pm = (PersistenceManager) pmControl.getMock();
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ JdoInterceptor interceptor = new JdoInterceptor();
+ interceptor.setPersistenceManagerFactory(pmf);
+ try {
+ interceptor.invoke(new TestInvocation(pmf));
+ }
+ catch (Throwable t) {
+ fail("Should not have thrown Throwable: " + t.getMessage());
+ }
+
+ pmfControl.verify();
+ pmControl.verify();
+ }
+
+ public void testInterceptorWithPrebound() {
+ MockControl pmfControl = MockControl.createControl(PersistenceManagerFactory.class);
+ PersistenceManagerFactory pmf = (PersistenceManagerFactory) pmfControl.getMock();
+ MockControl pmControl = MockControl.createControl(PersistenceManager.class);
+ PersistenceManager pm = (PersistenceManager) pmControl.getMock();
+ pmfControl.replay();
+ pmControl.replay();
+
+ TransactionSynchronizationManager.bindResource(pmf, new PersistenceManagerHolder(pm));
+ JdoInterceptor interceptor = new JdoInterceptor();
+ interceptor.setPersistenceManagerFactory(pmf);
+ try {
+ interceptor.invoke(new TestInvocation(pmf));
+ }
+ catch (Throwable t) {
+ fail("Should not have thrown Throwable: " + t.getMessage());
+ }
+ finally {
+ TransactionSynchronizationManager.unbindResource(pmf);
+ }
+
+ pmfControl.verify();
+ pmControl.verify();
+ }
+
+
+ private static class TestInvocation implements MethodInvocation {
+
+ private PersistenceManagerFactory persistenceManagerFactory;
+
+ public TestInvocation(PersistenceManagerFactory persistenceManagerFactory) {
+ this.persistenceManagerFactory = persistenceManagerFactory;
+ }
+
+ public Object proceed() throws Throwable {
+ if (!TransactionSynchronizationManager.hasResource(this.persistenceManagerFactory)) {
+ throw new IllegalStateException("PersistenceManager not bound");
+ }
+ return null;
+ }
+
+ public Object[] getArguments() {
+ return null;
+ }
+
+ public int getCurrentInterceptorIndex() {
+ return 0;
+ }
+
+ public int getNumberOfInterceptors() {
+ return 0;
+ }
+
+ public Interceptor getInterceptor(int i) {
+ return null;
+ }
+
+ public Method getMethod() {
+ return null;
+ }
+
+ public AccessibleObject getStaticPart() {
+ return getMethod();
+ }
+
+ public Object getArgument(int i) {
+ return null;
+ }
+
+ public void setArgument(int i, Object handler) {
+ }
+
+ public int getArgumentCount() {
+ return 0;
+ }
+
+ public Object getThis() {
+ return null;
+ }
+
+ public Object getProxy() {
+ return null;
+ }
+
+ public Invocation cloneInstance() {
+ return null;
+ }
+
+ public void release() {
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/jdo/JdoTemplateTests.java b/org.springframework.testsuite/src/test/java/org/springframework/orm/jdo/JdoTemplateTests.java
new file mode 100644
index 00000000000..f5d40a09ca1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/jdo/JdoTemplateTests.java
@@ -0,0 +1,787 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.orm.jdo;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import javax.jdo.JDODataStoreException;
+import javax.jdo.JDOException;
+import javax.jdo.JDOFatalDataStoreException;
+import javax.jdo.JDOFatalUserException;
+import javax.jdo.JDOObjectNotFoundException;
+import javax.jdo.JDOOptimisticVerificationException;
+import javax.jdo.JDOUserException;
+import javax.jdo.PersistenceManager;
+import javax.jdo.PersistenceManagerFactory;
+import javax.jdo.Query;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+
+/**
+ * @author Juergen Hoeller
+ * @since 03.06.2003
+ */
+public class JdoTemplateTests extends TestCase {
+
+ private MockControl pmfControl;
+ private PersistenceManagerFactory pmf;
+ private MockControl pmControl;
+ private PersistenceManager pm;
+
+ protected void setUp() {
+ pmfControl = MockControl.createControl(PersistenceManagerFactory.class);
+ pmf = (PersistenceManagerFactory) pmfControl.getMock();
+ pmControl = MockControl.createControl(PersistenceManager.class);
+ pm = (PersistenceManager) pmControl.getMock();
+ pmf.getConnectionFactory();
+ pmfControl.setReturnValue(null, 1);
+ }
+
+ protected void tearDown() {
+ try {
+ pmfControl.verify();
+ pmControl.verify();
+ }
+ catch (IllegalStateException ex) {
+ // ignore: test method didn't call replay
+ }
+ }
+
+ public void testTemplateExecuteWithNotAllowCreate() {
+ JdoTemplate jt = new JdoTemplate();
+ jt.setPersistenceManagerFactory(pmf);
+ jt.setAllowCreate(false);
+ try {
+ jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm) {
+ return null;
+ }
+ });
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ public void testTemplateExecuteWithNotAllowCreateAndThreadBound() {
+ pmfControl.replay();
+ pmControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ jt.setAllowCreate(false);
+ TransactionSynchronizationManager.bindResource(pmf, new PersistenceManagerHolder(pm));
+ final List l = new ArrayList();
+ l.add("test");
+ List result = (List) jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm) {
+ return l;
+ }
+ });
+ assertTrue("Correct result list", result == l);
+ TransactionSynchronizationManager.unbindResource(pmf);
+ }
+
+ public void testTemplateExecuteWithNewPersistenceManager() {
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ final List l = new ArrayList();
+ l.add("test");
+ List result = (List) jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm) {
+ return l;
+ }
+ });
+ assertTrue("Correct result list", result == l);
+ }
+
+ public void testTemplateExecuteWithThreadBoundAndFlushEager() {
+ MockControl dialectControl = MockControl.createControl(JdoDialect.class);
+ JdoDialect dialect = (JdoDialect) dialectControl.getMock();
+
+ dialect.flush(pm);
+ dialectControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+ dialectControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ jt.setJdoDialect(dialect);
+ jt.setFlushEager(true);
+ jt.setAllowCreate(false);
+ TransactionSynchronizationManager.bindResource(pmf, new PersistenceManagerHolder(pm));
+ final List l = new ArrayList();
+ l.add("test");
+ List result = (List) jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm) {
+ return l;
+ }
+ });
+ assertTrue("Correct result list", result == l);
+ TransactionSynchronizationManager.unbindResource(pmf);
+ dialectControl.verify();
+ }
+
+ public void testGetObjectById() {
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.getObjectById("0", true);
+ pmControl.setReturnValue("A");
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ assertEquals("A", jt.getObjectById("0"));
+ }
+
+ public void testGetObjectByIdWithClassAndValue() {
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.getObjectById(String.class, "0");
+ pmControl.setReturnValue("A");
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ assertEquals("A", jt.getObjectById(String.class, "0"));
+ }
+
+ public void testEvict() {
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.evict("0");
+ pmControl.setVoidCallable(1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ jt.evict("0");
+ }
+
+ public void testEvictAllWithCollection() {
+ Collection coll = new HashSet();
+
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.evictAll(coll);
+ pmControl.setVoidCallable(1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ jt.evictAll(coll);
+ }
+
+ public void testEvictAll() {
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.evictAll();
+ pmControl.setVoidCallable(1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ jt.evictAll();
+ }
+
+ public void testRefresh() {
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.refresh("0");
+ pmControl.setVoidCallable(1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ jt.refresh("0");
+ }
+
+ public void testRefreshAllWithCollection() {
+ Collection coll = new HashSet();
+
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.refreshAll(coll);
+ pmControl.setVoidCallable(1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ jt.refreshAll(coll);
+ }
+
+ public void testRefreshAll() {
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.refreshAll();
+ pmControl.setVoidCallable(1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ jt.refreshAll();
+ }
+
+ public void testMakePersistent() {
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.makePersistent("0");
+ pmControl.setReturnValue(null, 1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ jt.makePersistent("0");
+ }
+
+ public void testMakePersistentAll() {
+ Collection coll = new HashSet();
+
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.makePersistentAll(coll);
+ pmControl.setReturnValue(null, 1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ jt.makePersistentAll(coll);
+ }
+
+ public void testDeletePersistent() {
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.deletePersistent("0");
+ pmControl.setVoidCallable(1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ jt.deletePersistent("0");
+ }
+
+ public void testDeletePersistentAll() {
+ Collection coll = new HashSet();
+
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.deletePersistentAll(coll);
+ pmControl.setVoidCallable(1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ jt.deletePersistentAll(coll);
+ }
+
+ public void testDetachCopy() {
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.detachCopy("0");
+ pmControl.setReturnValue("0x", 1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ assertEquals("0x", jt.detachCopy("0"));
+ }
+
+ public void testDetachCopyAll() {
+ Collection attached = new HashSet();
+ Collection detached = new HashSet();
+
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.detachCopyAll(attached);
+ pmControl.setReturnValue(detached, 1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ assertEquals(detached, jt.detachCopyAll(attached));
+ }
+
+ public void testAttachCopy() {
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.makePersistent("0x");
+ pmControl.setReturnValue("0", 1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ assertEquals("0", jt.attachCopy("0x"));
+ }
+
+ public void testAttachCopyAll() {
+ Collection detached = new HashSet();
+ Collection attached = new HashSet();
+
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.makePersistentAll(detached);
+ pmControl.setReturnValue(attached, 1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ assertEquals(attached, jt.attachCopyAll(detached));
+ }
+
+ public void testFlush() {
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.flush();
+ pmControl.setVoidCallable(1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ jt.flush();
+ }
+
+ public void testFlushWithDialect() {
+ MockControl dialectControl = MockControl.createControl(JdoDialect.class);
+ JdoDialect dialect = (JdoDialect) dialectControl.getMock();
+
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ dialect.flush(pm);
+ dialectControl.setVoidCallable(1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+ dialectControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ jt.setJdoDialect(dialect);
+ jt.flush();
+ dialectControl.verify();
+ }
+
+ public void testFind() {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.newQuery(String.class);
+ pmControl.setReturnValue(query);
+ Collection coll = new HashSet();
+ query.execute();
+ queryControl.setReturnValue(coll);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+ queryControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ assertEquals(coll, jt.find(String.class));
+ queryControl.verify();
+ }
+
+ public void testFindWithFilter() {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.newQuery(String.class, "a == b");
+ pmControl.setReturnValue(query);
+ Collection coll = new HashSet();
+ query.execute();
+ queryControl.setReturnValue(coll);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+ queryControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ assertEquals(coll, jt.find(String.class, "a == b"));
+ queryControl.verify();
+ }
+
+ public void testFindWithFilterAndOrdering() {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.newQuery(String.class, "a == b");
+ pmControl.setReturnValue(query);
+ query.setOrdering("c asc");
+ queryControl.setVoidCallable(1);
+ Collection coll = new HashSet();
+ query.execute();
+ queryControl.setReturnValue(coll);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+ queryControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ assertEquals(coll, jt.find(String.class, "a == b", "c asc"));
+ queryControl.verify();
+ }
+
+ public void testFindWithParameterArray() {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.newQuery(String.class, "a == b");
+ pmControl.setReturnValue(query);
+ query.declareParameters("params");
+ queryControl.setVoidCallable(1);
+ Object[] values = new Object[0];
+ Collection coll = new HashSet();
+ query.executeWithArray(values);
+ queryControl.setReturnValue(coll);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+ queryControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ assertEquals(coll, jt.find(String.class, "a == b", "params", values));
+ queryControl.verify();
+ }
+
+ public void testFindWithParameterArrayAndOrdering() {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.newQuery(String.class, "a == b");
+ pmControl.setReturnValue(query);
+ query.declareParameters("params");
+ queryControl.setVoidCallable(1);
+ query.setOrdering("c asc");
+ queryControl.setVoidCallable(1);
+ Object[] values = new Object[0];
+ Collection coll = new HashSet();
+ query.executeWithArray(values);
+ queryControl.setReturnValue(coll);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+ queryControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ assertEquals(coll, jt.find(String.class, "a == b", "params", values, "c asc"));
+ queryControl.verify();
+ }
+
+ public void testFindWithParameterMap() {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.newQuery(String.class, "a == b");
+ pmControl.setReturnValue(query);
+ query.declareParameters("params");
+ queryControl.setVoidCallable(1);
+ Map values = new HashMap();
+ Collection coll = new HashSet();
+ query.executeWithMap(values);
+ queryControl.setReturnValue(coll);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+ queryControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ assertEquals(coll, jt.find(String.class, "a == b", "params", values));
+ queryControl.verify();
+ }
+
+ public void testFindWithParameterMapAndOrdering() {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.newQuery(String.class, "a == b");
+ pmControl.setReturnValue(query);
+ query.declareParameters("params");
+ queryControl.setVoidCallable(1);
+ query.setOrdering("c asc");
+ queryControl.setVoidCallable(1);
+ Map values = new HashMap();
+ Collection coll = new HashSet();
+ query.executeWithMap(values);
+ queryControl.setReturnValue(coll);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+ queryControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ assertEquals(coll, jt.find(String.class, "a == b", "params", values, "c asc"));
+ queryControl.verify();
+ }
+
+ public void testFindWithLanguageAndQueryObject() {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.newQuery(Query.SQL, "some SQL");
+ pmControl.setReturnValue(query);
+ Collection coll = new HashSet();
+ query.execute();
+ queryControl.setReturnValue(coll);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+ queryControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ assertEquals(coll, jt.find(Query.SQL, "some SQL"));
+ queryControl.verify();
+ }
+
+ public void testFindWithQueryString() {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.newQuery("single string query");
+ pmControl.setReturnValue(query);
+ Collection coll = new HashSet();
+ query.execute();
+ queryControl.setReturnValue(coll);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+ queryControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ assertEquals(coll, jt.find("single string query"));
+ queryControl.verify();
+ }
+
+ public void testFindByNamedQuery() {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm);
+ pm.newNamedQuery(String.class, "some query name");
+ pmControl.setReturnValue(query);
+ Collection coll = new HashSet();
+ query.execute();
+ queryControl.setReturnValue(coll);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+ queryControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ assertEquals(coll, jt.findByNamedQuery(String.class, "some query name"));
+ queryControl.verify();
+ }
+
+ public void testTemplateExceptions() {
+ try {
+ createTemplate().execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm) {
+ throw new JDOObjectNotFoundException();
+ }
+ });
+ fail("Should have thrown JdoObjectRetrievalFailureException");
+ }
+ catch (JdoObjectRetrievalFailureException ex) {
+ // expected
+ }
+
+ try {
+ createTemplate().execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm) {
+ throw new JDOOptimisticVerificationException();
+ }
+ });
+ fail("Should have thrown JdoOptimisticLockingFailureException");
+ }
+ catch (JdoOptimisticLockingFailureException ex) {
+ // expected
+ }
+
+ try {
+ createTemplate().execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm) {
+ throw new JDODataStoreException();
+ }
+ });
+ fail("Should have thrown JdoResourceFailureException");
+ }
+ catch (JdoResourceFailureException ex) {
+ // expected
+ }
+
+ try {
+ createTemplate().execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm) {
+ throw new JDOFatalDataStoreException();
+ }
+ });
+ fail("Should have thrown JdoResourceFailureException");
+ }
+ catch (JdoResourceFailureException ex) {
+ // expected
+ }
+
+ try {
+ createTemplate().execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm) {
+ throw new JDOUserException();
+ }
+ });
+ fail("Should have thrown JdoUsageException");
+ }
+ catch (JdoUsageException ex) {
+ // expected
+ }
+
+ try {
+ createTemplate().execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm) {
+ throw new JDOFatalUserException();
+ }
+ });
+ fail("Should have thrown JdoUsageException");
+ }
+ catch (JdoUsageException ex) {
+ // expected
+ }
+
+ try {
+ createTemplate().execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm) {
+ throw new JDOException();
+ }
+ });
+ fail("Should have thrown JdoSystemException");
+ }
+ catch (JdoSystemException ex) {
+ // expected
+ }
+ }
+
+ public void testTranslateException() {
+ MockControl dialectControl = MockControl.createControl(JdoDialect.class);
+ JdoDialect dialect = (JdoDialect) dialectControl.getMock();
+ final JDOException ex = new JDOException();
+ dialect.translateException(ex);
+ dialectControl.setReturnValue(new DataIntegrityViolationException("test", ex));
+ dialectControl.replay();
+ try {
+ JdoTemplate template = createTemplate();
+ template.setJdoDialect(dialect);
+ template.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm) {
+ throw ex;
+ }
+ });
+ fail("Should have thrown DataIntegrityViolationException");
+ }
+ catch (DataIntegrityViolationException dive) {
+ // expected
+ }
+ dialectControl.verify();
+ }
+
+ private JdoTemplate createTemplate() {
+ pmfControl.reset();
+ pmControl.reset();
+ pmf.getConnectionFactory();
+ pmfControl.setReturnValue(null, 1);
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+ return new JdoTemplate(pmf);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/jdo/JdoTransactionManagerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/orm/jdo/JdoTransactionManagerTests.java
new file mode 100644
index 00000000000..0294cfcee57
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/jdo/JdoTransactionManagerTests.java
@@ -0,0 +1,1209 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.orm.jdo;
+
+import java.lang.reflect.Proxy;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+import java.sql.Savepoint;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jdo.JDOFatalDataStoreException;
+import javax.jdo.PersistenceManager;
+import javax.jdo.PersistenceManagerFactory;
+import javax.jdo.Query;
+import javax.jdo.Transaction;
+import javax.sql.DataSource;
+import javax.transaction.Status;
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.beans.TestBean;
+import org.springframework.jdbc.datasource.ConnectionHandle;
+import org.springframework.jdbc.datasource.ConnectionHolder;
+import org.springframework.jdbc.datasource.SimpleConnectionHandle;
+import org.springframework.transaction.InvalidIsolationLevelException;
+import org.springframework.transaction.MockJtaTransaction;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.jta.JtaTransactionManager;
+import org.springframework.transaction.support.TransactionCallback;
+import org.springframework.transaction.support.TransactionCallbackWithoutResult;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+import org.springframework.transaction.support.TransactionTemplate;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class JdoTransactionManagerTests extends TestCase {
+
+ private MockControl pmfControl, pmControl, txControl;
+
+ private PersistenceManagerFactory pmf;
+
+ private PersistenceManager pm;
+
+ private Transaction tx;
+
+
+ protected void setUp() {
+ pmfControl = MockControl.createControl(PersistenceManagerFactory.class);
+ pmf = (PersistenceManagerFactory) pmfControl.getMock();
+ pmControl = MockControl.createControl(PersistenceManager.class);
+ pm = (PersistenceManager) pmControl.getMock();
+ txControl = MockControl.createControl(Transaction.class);
+ tx = (Transaction) txControl.getMock();
+ pmf.getConnectionFactory();
+ pmfControl.setReturnValue(null, 1);
+ }
+
+ protected void tearDown() {
+ try {
+ pmfControl.verify();
+ pmControl.verify();
+ }
+ catch (IllegalStateException ex) {
+ // ignore: test method didn't call replay
+ }
+ assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ }
+
+ public void testTransactionCommit() {
+ pmf.getConnectionFactory();
+ pmfControl.setReturnValue(null, 2);
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 1);
+ pm.currentTransaction();
+ pmControl.setReturnValue(tx, 3);
+ pm.flush();
+ pmControl.setVoidCallable(2);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ tx.begin();
+ txControl.setVoidCallable(1);
+ tx.getRollbackOnly();
+ txControl.setReturnValue(false, 1);
+ tx.commit();
+ txControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+ txControl.replay();
+
+ PlatformTransactionManager tm = new JdoTransactionManager(pmf);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ final List l = new ArrayList();
+ l.add("test");
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
+
+ TransactionAwarePersistenceManagerFactoryProxy proxyFactory =
+ new TransactionAwarePersistenceManagerFactoryProxy();
+ proxyFactory.setTargetPersistenceManagerFactory(pmf);
+ PersistenceManagerFactory proxy = (PersistenceManagerFactory) proxyFactory.getObject();
+ assertEquals(pm.toString(), proxy.getPersistenceManager().toString());
+ proxy.getPersistenceManager().flush();
+ proxy.getPersistenceManager().close();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ return jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm2) {
+ pm2.flush();
+ return l;
+ }
+ });
+ }
+ });
+ assertTrue("Correct result list", result == l);
+
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ }
+
+ public void testTransactionRollback() {
+ pmf.getConnectionFactory();
+ pmfControl.setReturnValue(null, 2);
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 1);
+ pm.currentTransaction();
+ pmControl.setReturnValue(tx, 2);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ tx.begin();
+ txControl.setVoidCallable(1);
+ tx.isActive();
+ txControl.setReturnValue(true, 1);
+ tx.rollback();
+ txControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+ txControl.replay();
+
+ PlatformTransactionManager tm = new JdoTransactionManager(pmf);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ try {
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
+ JdoTemplate jt = new JdoTemplate(pmf);
+ return jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm) {
+ throw new RuntimeException("application exception");
+ }
+ });
+ }
+ });
+ fail("Should have thrown RuntimeException");
+ }
+ catch (RuntimeException ex) {
+ // expected
+ }
+
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ }
+
+ public void testTransactionRollbackWithAlreadyRolledBack() {
+ pmf.getConnectionFactory();
+ pmfControl.setReturnValue(null, 2);
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 1);
+ pm.currentTransaction();
+ pmControl.setReturnValue(tx, 2);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ tx.begin();
+ txControl.setVoidCallable(1);
+ tx.isActive();
+ txControl.setReturnValue(false, 1);
+ pmfControl.replay();
+ pmControl.replay();
+ txControl.replay();
+
+ PlatformTransactionManager tm = new JdoTransactionManager(pmf);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ try {
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
+ JdoTemplate jt = new JdoTemplate(pmf);
+ return jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm) {
+ throw new RuntimeException("application exception");
+ }
+ });
+ }
+ });
+ fail("Should have thrown RuntimeException");
+ }
+ catch (RuntimeException ex) {
+ // expected
+ }
+
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ }
+
+ public void testTransactionRollbackOnly() {
+ pmf.getConnectionFactory();
+ pmfControl.setReturnValue(null, 2);
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 1);
+ pm.currentTransaction();
+ pmControl.setReturnValue(tx, 2);
+ pm.flush();
+ pmControl.setVoidCallable(1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ tx.begin();
+ txControl.setVoidCallable(1);
+ tx.isActive();
+ txControl.setReturnValue(true, 1);
+ tx.rollback();
+ txControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+ txControl.replay();
+
+ PlatformTransactionManager tm = new JdoTransactionManager(pmf);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
+ JdoTemplate jt = new JdoTemplate(pmf);
+ jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm2) {
+ pm2.flush();
+ return null;
+ }
+ });
+ status.setRollbackOnly();
+ return null;
+ }
+ });
+
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+ }
+
+ public void testParticipatingTransactionWithCommit() {
+ pmf.getConnectionFactory();
+ pmfControl.setReturnValue(null, 2);
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 1);
+ pm.currentTransaction();
+ pmControl.setReturnValue(tx, 3);
+ pm.flush();
+ pmControl.setVoidCallable(1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ tx.begin();
+ txControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+ txControl.replay();
+
+ PlatformTransactionManager tm = new JdoTransactionManager(pmf);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ final List l = new ArrayList();
+ l.add("test");
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ txControl.reset();
+ tx.isActive();
+ txControl.setReturnValue(true, 1);
+ tx.getRollbackOnly();
+ txControl.setReturnValue(false, 1);
+ tx.commit();
+ txControl.setVoidCallable(1);
+ txControl.replay();
+
+ return tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ JdoTemplate jt = new JdoTemplate(pmf);
+ return jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm2) {
+ pm2.flush();
+ return l;
+ }
+ });
+ }
+ });
+ }
+ });
+ assertTrue("Correct result list", result == l);
+ }
+
+ public void testParticipatingTransactionWithRollback() {
+ pmf.getConnectionFactory();
+ pmfControl.setReturnValue(null, 2);
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 1);
+ pm.currentTransaction();
+ pmControl.setReturnValue(tx, 3);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ tx.isActive();
+ txControl.setReturnValue(false, 1);
+ tx.begin();
+ txControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+ txControl.replay();
+
+ PlatformTransactionManager tm = new JdoTransactionManager(pmf);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ try {
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ txControl.reset();
+ tx.isActive();
+ txControl.setReturnValue(true, 3);
+ tx.setRollbackOnly();
+ txControl.setVoidCallable(1);
+ tx.rollback();
+ txControl.setVoidCallable(1);
+ txControl.replay();
+
+ return tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ JdoTemplate jt = new JdoTemplate(pmf);
+ return jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm) {
+ throw new RuntimeException("application exception");
+ }
+ });
+ }
+ });
+ }
+ });
+ fail("Should have thrown RuntimeException");
+ }
+ catch (RuntimeException ex) {
+ // expected
+ }
+ }
+
+ public void testParticipatingTransactionWithRollbackOnly() {
+ pmf.getConnectionFactory();
+ pmfControl.setReturnValue(null, 2);
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 1);
+ pm.currentTransaction();
+ pmControl.setReturnValue(tx, 5);
+ pm.flush();
+ pmControl.setVoidCallable(1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ tx.begin();
+ txControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+ txControl.replay();
+
+ PlatformTransactionManager tm = new JdoTransactionManager(pmf);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ final List l = new ArrayList();
+ l.add("test");
+
+ try {
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ txControl.reset();
+ tx.isActive();
+ txControl.setReturnValue(true, 1);
+ tx.setRollbackOnly();
+ txControl.setVoidCallable(1);
+ tx.getRollbackOnly();
+ txControl.setReturnValue(true, 1);
+ tx.commit();
+ txControl.setThrowable(new JDOFatalDataStoreException(), 1);
+ tx.isActive();
+ txControl.setReturnValue(false, 1);
+ txControl.replay();
+
+ return tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ JdoTemplate jt = new JdoTemplate(pmf);
+ jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm2) {
+ pm2.flush();
+ return l;
+ }
+ });
+ status.setRollbackOnly();
+ return null;
+ }
+ });
+ }
+ });
+ fail("Should have thrown JdoResourceFailureException");
+ }
+ catch (JdoResourceFailureException ex) {
+ // expected
+ }
+ }
+
+ public void testParticipatingTransactionWithWithRequiresNew() {
+ pmf.getConnectionFactory();
+ pmfControl.setReturnValue(null, 2);
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 2);
+ pm.currentTransaction();
+ pmControl.setReturnValue(tx, 6);
+ tx.begin();
+ txControl.setVoidCallable(1);
+ pm.flush();
+ pmControl.setVoidCallable(1);
+ pm.close();
+ pmControl.setVoidCallable(2);
+ pmfControl.replay();
+ pmControl.replay();
+ txControl.replay();
+
+ PlatformTransactionManager tm = new JdoTransactionManager(pmf);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ final List l = new ArrayList();
+ l.add("test");
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ txControl.verify();
+ txControl.reset();
+ tx.isActive();
+ txControl.setReturnValue(true, 1);
+ tx.begin();
+ txControl.setVoidCallable(1);
+ tx.getRollbackOnly();
+ txControl.setReturnValue(false, 2);
+ tx.commit();
+ txControl.setVoidCallable(2);
+ txControl.replay();
+
+ return tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ JdoTemplate jt = new JdoTemplate(pmf);
+ return jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm2) {
+ pm2.flush();
+ return l;
+ }
+ });
+ }
+ });
+ }
+ });
+ assertTrue("Correct result list", result == l);
+ }
+
+ public void testParticipatingTransactionWithWithRequiresNewAndPrebound() {
+ pmf.getConnectionFactory();
+ pmfControl.setReturnValue(null, 3);
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 1);
+ pm.currentTransaction();
+ pmControl.setReturnValue(tx, 6);
+ tx.begin();
+ txControl.setVoidCallable(1);
+ pm.flush();
+ pmControl.setVoidCallable(1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+ txControl.replay();
+
+ PlatformTransactionManager tm = new JdoTransactionManager(pmf);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ final List l = new ArrayList();
+ l.add("test");
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ TransactionSynchronizationManager.bindResource(pmf, new PersistenceManagerHolder(pm));
+ assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ txControl.verify();
+ txControl.reset();
+ tx.isActive();
+ txControl.setReturnValue(true, 1);
+ tx.begin();
+ txControl.setVoidCallable(1);
+ tx.getRollbackOnly();
+ txControl.setReturnValue(false, 2);
+ tx.commit();
+ txControl.setVoidCallable(2);
+ txControl.replay();
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm2) {
+ return null;
+ }
+ });
+
+ return tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ JdoTemplate jt = new JdoTemplate(pmf);
+ return jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm2) {
+ pm2.flush();
+ return l;
+ }
+ });
+ }
+ });
+ }
+ });
+ assertTrue("Correct result list", result == l);
+
+ assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
+ TransactionSynchronizationManager.unbindResource(pmf);
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ }
+
+ public void testJtaTransactionCommit() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.commit();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 1);
+ pm.flush();
+ pmControl.setVoidCallable(2);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ JtaTransactionManager ptm = new JtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ final List l = new ArrayList();
+ l.add("test");
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+ JdoTemplate jt = new JdoTemplate(pmf);
+ jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm2) {
+ assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
+ pm2.flush();
+ return l;
+ }
+ });
+ Object result = jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm2) {
+ assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
+ pm2.flush();
+ return l;
+ }
+ });
+ assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
+ return result;
+ }
+ });
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+ assertTrue("Correct result list", result == l);
+
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ utControl.verify();
+ }
+
+ public void testParticipatingJtaTransactionWithWithRequiresNewAndPrebound() throws Exception {
+ final MockControl utControl = MockControl.createControl(UserTransaction.class);
+ final UserTransaction ut = (UserTransaction) utControl.getMock();
+ final MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ final TransactionManager tm = (TransactionManager) tmControl.getMock();
+
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ pmf.getConnectionFactory();
+ pmfControl.setReturnValue(null, 1);
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 1);
+ pm.flush();
+ pmControl.setVoidCallable(1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ JtaTransactionManager ptm = new JtaTransactionManager(ut, tm);
+ final TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ final List l = new ArrayList();
+ l.add("test");
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ TransactionSynchronizationManager.bindResource(pmf, new PersistenceManagerHolder(pm));
+ assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ try {
+ utControl.verify();
+ utControl.reset();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ MockJtaTransaction transaction = new MockJtaTransaction();
+ tm.suspend();
+ tmControl.setReturnValue(transaction, 1);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 4);
+ ut.commit();
+ utControl.setVoidCallable(2);
+ tm.resume(transaction);
+ tmControl.setVoidCallable(1);
+ utControl.replay();
+ tmControl.replay();
+ }
+ catch (Exception ex) {
+ }
+
+ JdoTemplate jt = new JdoTemplate(pmf);
+ jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm2) {
+ return null;
+ }
+ });
+
+ return tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ JdoTemplate jt = new JdoTemplate(pmf);
+ return jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm2) {
+ pm2.flush();
+ return l;
+ }
+ });
+ }
+ });
+ }
+ });
+ assertTrue("Correct result list", result == l);
+
+ assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
+ TransactionSynchronizationManager.unbindResource(pmf);
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ utControl.verify();
+ }
+
+
+ public void testTransactionCommitWithPropagationSupports() {
+ pmf.getConnectionFactory();
+ pmfControl.setReturnValue(null, 2);
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ PlatformTransactionManager tm = new JdoTransactionManager(pmf);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
+ final List l = new ArrayList();
+ l.add("test");
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+ assertTrue("Is not new transaction", !status.isNewTransaction());
+ JdoTemplate jt = new JdoTemplate(pmf);
+ return jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm) {
+ return l;
+ }
+ });
+ }
+ });
+ assertTrue("Correct result list", result == l);
+
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+ }
+
+ public void testInvalidIsolation() {
+ pmf.getConnectionFactory();
+ pmfControl.setReturnValue(null, 1);
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 1);
+ pm.currentTransaction();
+ pmControl.setReturnValue(null, 1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ PlatformTransactionManager tm = new JdoTransactionManager(pmf);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
+ try {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ }
+ });
+ fail("Should have thrown InvalidIsolationLevelException");
+ }
+ catch (InvalidIsolationLevelException ex) {
+ // expected
+ }
+ }
+
+ public void testTransactionCommitWithPrebound() {
+ pmf.getConnectionFactory();
+ pmfControl.setReturnValue(null, 2);
+ pm.currentTransaction();
+ pmControl.setReturnValue(tx, 3);
+ tx.isActive();
+ txControl.setReturnValue(false, 1);
+ tx.begin();
+ txControl.setVoidCallable(1);
+ tx.getRollbackOnly();
+ txControl.setReturnValue(false, 1);
+ tx.commit();
+ txControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+ txControl.replay();
+
+ PlatformTransactionManager tm = new JdoTransactionManager(pmf);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ final List l = new ArrayList();
+ l.add("test");
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ TransactionSynchronizationManager.bindResource(pmf, new PersistenceManagerHolder(pm));
+ assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
+ JdoTemplate jt = new JdoTemplate(pmf);
+ return jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm) {
+ return l;
+ }
+ });
+ }
+ });
+ assertTrue("Correct result list", result == l);
+
+ assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
+ TransactionSynchronizationManager.unbindResource(pmf);
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ }
+
+ public void testTransactionCommitWithDataSource() throws SQLException {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ MockControl dialectControl = MockControl.createControl(JdoDialect.class);
+ JdoDialect dialect = (JdoDialect) dialectControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ final Connection con = (Connection) conControl.getMock();
+ ConnectionHandle conHandle = new SimpleConnectionHandle(con);
+
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 1);
+ pm.currentTransaction();
+ pmControl.setReturnValue(tx, 3);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ TransactionTemplate tt = new TransactionTemplate();
+ dialect.beginTransaction(tx, tt);
+ dialectControl.setReturnValue(null, 1);
+ dialect.getJdbcConnection(pm, false);
+ dialectControl.setReturnValue(conHandle, 1);
+ dialect.releaseJdbcConnection(conHandle, pm);
+ dialectControl.setVoidCallable(1);
+ dialect.cleanupTransaction(null);
+ dialectControl.setVoidCallable(1);
+ tx.getRollbackOnly();
+ txControl.setReturnValue(false, 1);
+ tx.commit();
+ txControl.setVoidCallable(1);
+ pmfControl.replay();
+ dsControl.replay();
+ dialectControl.replay();
+ pmControl.replay();
+ txControl.replay();
+ conControl.replay();
+
+ JdoTransactionManager tm = new JdoTransactionManager();
+ tm.setPersistenceManagerFactory(pmf);
+ tm.setDataSource(ds);
+ tm.setJdoDialect(dialect);
+ tt.setTransactionManager(tm);
+ final List l = new ArrayList();
+ l.add("test");
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
+ assertTrue("Has thread con", TransactionSynchronizationManager.hasResource(ds));
+ JdoTemplate jt = new JdoTemplate(pmf);
+ return jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm) {
+ return l;
+ }
+ });
+ }
+ });
+ assertTrue("Correct result list", result == l);
+
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+ assertTrue("Hasn't thread con", !TransactionSynchronizationManager.hasResource(ds));
+ dsControl.verify();
+ dialectControl.verify();
+ conControl.verify();
+ }
+
+ public void testTransactionCommitWithAutoDetectedDataSource() throws SQLException {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ MockControl dialectControl = MockControl.createControl(JdoDialect.class);
+ JdoDialect dialect = (JdoDialect) dialectControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ final Connection con = (Connection) conControl.getMock();
+ ConnectionHandle conHandle = new SimpleConnectionHandle(con);
+
+ pmfControl.reset();
+ pmf.getConnectionFactory();
+ pmfControl.setReturnValue(ds, 2);
+ con.getMetaData();
+ conControl.setReturnValue(null, 1);
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 1);
+ pm.currentTransaction();
+ pmControl.setReturnValue(tx, 3);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ TransactionTemplate tt = new TransactionTemplate();
+ dialect.beginTransaction(tx, tt);
+ dialectControl.setReturnValue(null, 1);
+ dialect.getJdbcConnection(pm, false);
+ dialectControl.setReturnValue(conHandle, 1);
+ dialect.releaseJdbcConnection(conHandle, pm);
+ dialectControl.setVoidCallable(1);
+ dialect.cleanupTransaction(null);
+ dialectControl.setVoidCallable(1);
+ tx.getRollbackOnly();
+ txControl.setReturnValue(false, 1);
+ tx.commit();
+ txControl.setVoidCallable(1);
+ pmfControl.replay();
+ dsControl.replay();
+ dialectControl.replay();
+ pmControl.replay();
+ txControl.replay();
+ conControl.replay();
+
+ JdoTransactionManager tm = new JdoTransactionManager();
+ tm.setPersistenceManagerFactory(pmf);
+ tm.setJdoDialect(dialect);
+ tm.afterPropertiesSet();
+ tt.setTransactionManager(tm);
+ final List l = new ArrayList();
+ l.add("test");
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
+ assertTrue("Has thread con", TransactionSynchronizationManager.hasResource(ds));
+ JdoTemplate jt = new JdoTemplate(pmf);
+ return jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm) {
+ return l;
+ }
+ });
+ }
+ });
+ assertTrue("Correct result list", result == l);
+
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+ assertTrue("Hasn't thread con", !TransactionSynchronizationManager.hasResource(ds));
+ dsControl.verify();
+ dialectControl.verify();
+ conControl.verify();
+ }
+
+ public void testTransactionCommitWithAutoDetectedDataSourceAndNoConnection() throws SQLException {
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ MockControl dialectControl = MockControl.createControl(JdoDialect.class);
+ final JdoDialect dialect = (JdoDialect) dialectControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+
+ pmfControl.reset();
+ pmf.getConnectionFactory();
+ pmfControl.setReturnValue(ds, 1);
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 1);
+ pm.currentTransaction();
+ pmControl.setReturnValue(tx, 3);
+ pm.flush();
+ pmControl.setVoidCallable(1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ TransactionTemplate tt = new TransactionTemplate();
+ dialect.beginTransaction(tx, tt);
+ dialectControl.setReturnValue(null, 1);
+ dialect.getJdbcConnection(pm, false);
+ dialectControl.setReturnValue(null, 1);
+ dialect.cleanupTransaction(null);
+ dialectControl.setVoidCallable(1);
+ tx.getRollbackOnly();
+ txControl.setReturnValue(false, 1);
+ tx.commit();
+ txControl.setVoidCallable(1);
+ pmfControl.replay();
+ dsControl.replay();
+ dialectControl.replay();
+ pmControl.replay();
+ txControl.replay();
+ conControl.replay();
+
+ JdoTransactionManager tm = new JdoTransactionManager();
+ tm.setPersistenceManagerFactory(pmf);
+ tm.setJdoDialect(dialect);
+ tm.afterPropertiesSet();
+ tt.setTransactionManager(tm);
+ final List l = new ArrayList();
+ l.add("test");
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
+ assertTrue("Hasn't thread con", !TransactionSynchronizationManager.hasResource(ds));
+ JdoTemplate jt = new JdoTemplate();
+ jt.setPersistenceManagerFactory(pmf);
+ jt.setJdoDialect(dialect);
+ return jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm2) {
+ pm2.flush();
+ return l;
+ }
+ });
+ }
+ });
+ assertTrue("Correct result list", result == l);
+
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+ assertTrue("Hasn't thread con", !TransactionSynchronizationManager.hasResource(ds));
+ dsControl.verify();
+ dialectControl.verify();
+ conControl.verify();
+ }
+
+ public void testExistingTransactionWithPropagationNestedAndRollback() throws SQLException {
+ doTestExistingTransactionWithPropagationNestedAndRollback(false);
+ }
+
+ public void testExistingTransactionWithManualSavepointAndRollback() throws SQLException {
+ doTestExistingTransactionWithPropagationNestedAndRollback(true);
+ }
+
+ private void doTestExistingTransactionWithPropagationNestedAndRollback(final boolean manualSavepoint)
+ throws SQLException {
+
+ MockControl dsControl = MockControl.createControl(DataSource.class);
+ final DataSource ds = (DataSource) dsControl.getMock();
+ MockControl dialectControl = MockControl.createControl(JdoDialect.class);
+ JdoDialect dialect = (JdoDialect) dialectControl.getMock();
+ MockControl conControl = MockControl.createControl(Connection.class);
+ final Connection con = (Connection) conControl.getMock();
+ MockControl mdControl = MockControl.createControl(DatabaseMetaData.class);
+ DatabaseMetaData md = (DatabaseMetaData) mdControl.getMock();
+ MockControl spControl = MockControl.createControl(Savepoint.class);
+ Savepoint sp = (Savepoint) spControl.getMock();
+
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 1);
+ pm.currentTransaction();
+ pmControl.setReturnValue(tx, 3);
+ pm.flush();
+ pmControl.setVoidCallable(1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ md.supportsSavepoints();
+ mdControl.setReturnValue(true, 1);
+ con.getMetaData();
+ conControl.setReturnValue(md, 1);
+ con.setSavepoint(ConnectionHolder.SAVEPOINT_NAME_PREFIX + 1);
+ conControl.setReturnValue(sp, 1);
+ con.rollback(sp);
+ conControl.setVoidCallable(1);
+ final TransactionTemplate tt = new TransactionTemplate();
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED);
+ dialect.beginTransaction(tx, tt);
+ dialectControl.setReturnValue(null, 1);
+ ConnectionHandle conHandle = new SimpleConnectionHandle(con);
+ dialect.getJdbcConnection(pm, false);
+ dialectControl.setReturnValue(conHandle, 1);
+ dialect.releaseJdbcConnection(conHandle, pm);
+ dialectControl.setVoidCallable(1);
+ dialect.cleanupTransaction(null);
+ dialectControl.setVoidCallable(1);
+ if (!manualSavepoint) {
+ tx.isActive();
+ txControl.setReturnValue(true, 1);
+ }
+ tx.getRollbackOnly();
+ txControl.setReturnValue(false, 1);
+ tx.commit();
+ txControl.setVoidCallable(1);
+ pmfControl.replay();
+ dsControl.replay();
+ dialectControl.replay();
+ pmControl.replay();
+ txControl.replay();
+ conControl.replay();
+ mdControl.replay();
+ spControl.replay();
+
+ JdoTransactionManager tm = new JdoTransactionManager();
+ tm.setNestedTransactionAllowed(true);
+ tm.setPersistenceManagerFactory(pmf);
+ tm.setDataSource(ds);
+ tm.setJdoDialect(dialect);
+ tt.setTransactionManager(tm);
+ final List l = new ArrayList();
+ l.add("test");
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
+ assertTrue("Has thread con", TransactionSynchronizationManager.hasResource(ds));
+ if (manualSavepoint) {
+ Object savepoint = status.createSavepoint();
+ status.rollbackToSavepoint(savepoint);
+ }
+ else {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(pmf));
+ assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
+ status.setRollbackOnly();
+ }
+ });
+ }
+ JdoTemplate jt = new JdoTemplate(pmf);
+ return jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm2) {
+ pm2.flush();
+ return l;
+ }
+ });
+ }
+ });
+ assertTrue("Correct result list", result == l);
+
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+ assertTrue("Hasn't thread con", !TransactionSynchronizationManager.hasResource(ds));
+ dsControl.verify();
+ dialectControl.verify();
+ conControl.verify();
+ mdControl.verify();
+ spControl.verify();
+ }
+
+ public void testTransactionTimeoutWithJdoDialect() throws SQLException {
+ doTestTransactionTimeoutWithJdoDialect(true);
+ }
+
+ public void testTransactionTimeoutWithJdoDialectAndPmProxy() throws SQLException {
+ doTestTransactionTimeoutWithJdoDialect(false);
+ }
+
+ private void doTestTransactionTimeoutWithJdoDialect(final boolean exposeNativePm) throws SQLException {
+ MockControl queryControl = MockControl.createControl(Query.class);
+ Query query = (Query) queryControl.getMock();
+ MockControl dialectControl = MockControl.createControl(JdoDialect.class);
+ final JdoDialect dialect = (JdoDialect) dialectControl.getMock();
+
+ TransactionTemplate tt = new TransactionTemplate();
+
+ pmf.getConnectionFactory();
+ pmfControl.setReturnValue(null, 2);
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 1);
+ pm.currentTransaction();
+ pmControl.setReturnValue(tx, 3);
+ dialect.beginTransaction(tx, tt);
+ dialectControl.setReturnValue(null, 1);
+ if (!exposeNativePm) {
+ dialect.applyQueryTimeout(query, 10);
+ }
+ dialect.cleanupTransaction(null);
+ dialectControl.setVoidCallable(1);
+ pm.newQuery(TestBean.class);
+ pmControl.setReturnValue(query, 1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ tx.getRollbackOnly();
+ txControl.setReturnValue(false, 1);
+ tx.commit();
+ txControl.setVoidCallable(1);
+
+ pmfControl.replay();
+ pmControl.replay();
+ txControl.replay();
+ queryControl.replay();
+ dialectControl.replay();
+
+ JdoTransactionManager tm = new JdoTransactionManager(pmf);
+ tm.setJdoDialect(dialect);
+ tt.setTransactionManager(tm);
+ tt.setTimeout(10);
+
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
+ JdoTemplate jt = new JdoTemplate(pmf);
+ jt.setJdoDialect(dialect);
+ if (exposeNativePm) {
+ jt.setExposeNativePersistenceManager(true);
+ }
+ return jt.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm2) {
+ if (exposeNativePm) {
+ assertSame(pm, pm2);
+ }
+ else {
+ assertTrue(Proxy.isProxyClass(pm2.getClass()));
+ }
+ pm2.newQuery(TestBean.class);
+ return null;
+ }
+ });
+ }
+ });
+
+ assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ dialectControl.verify();
+ queryControl.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/jdo/LocalPersistenceManagerFactoryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/orm/jdo/LocalPersistenceManagerFactoryTests.java
new file mode 100644
index 00000000000..5ad9c14d397
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/jdo/LocalPersistenceManagerFactoryTests.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.orm.jdo;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.jdo.JDOFatalUserException;
+import javax.jdo.PersistenceManagerFactory;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class LocalPersistenceManagerFactoryTests extends TestCase {
+
+ public void testLocalPersistenceManagerFactoryBean() throws IOException {
+ MockControl pmfControl = MockControl.createControl(PersistenceManagerFactory.class);
+ final PersistenceManagerFactory pmf = (PersistenceManagerFactory) pmfControl.getMock();
+ LocalPersistenceManagerFactoryBean pmfb = new LocalPersistenceManagerFactoryBean() {
+ protected PersistenceManagerFactory newPersistenceManagerFactory(Map props) {
+ return pmf;
+ }
+ };
+ pmfb.setJdoProperties(new Properties());
+ pmfb.afterPropertiesSet();
+ assertSame(pmf, pmfb.getObject());
+ }
+
+ public void testLocalPersistenceManagerFactoryBeanWithInvalidSettings() throws IOException {
+ LocalPersistenceManagerFactoryBean pmfb = new LocalPersistenceManagerFactoryBean();
+ try {
+ pmfb.afterPropertiesSet();
+ fail("Should have thrown JDOFatalUserException");
+ }
+ catch (JDOFatalUserException ex) {
+ // expected
+ }
+ }
+
+ public void testLocalPersistenceManagerFactoryBeanWithIncompleteProperties() throws IOException {
+ LocalPersistenceManagerFactoryBean pmfb = new LocalPersistenceManagerFactoryBean();
+ Properties props = new Properties();
+ props.setProperty("myKey", "myValue");
+ pmfb.setJdoProperties(props);
+ try {
+ pmfb.afterPropertiesSet();
+ fail("Should have thrown JDOFatalUserException");
+ }
+ catch (JDOFatalUserException ex) {
+ // expected
+ }
+ }
+
+ public void testLocalPersistenceManagerFactoryBeanWithInvalidProperty() throws IOException {
+ LocalPersistenceManagerFactoryBean pmfb = new LocalPersistenceManagerFactoryBean() {
+ protected PersistenceManagerFactory newPersistenceManagerFactory(Map props) {
+ throw new IllegalArgumentException((String) props.get("myKey"));
+ }
+ };
+ Properties props = new Properties();
+ props.setProperty("myKey", "myValue");
+ pmfb.setJdoProperties(props);
+ try {
+ pmfb.afterPropertiesSet();
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ assertTrue("Correct exception", "myValue".equals(ex.getMessage()));
+ }
+ }
+
+ public void testLocalPersistenceManagerFactoryBeanWithFile() throws IOException {
+ LocalPersistenceManagerFactoryBean pmfb = new LocalPersistenceManagerFactoryBean() {
+ protected PersistenceManagerFactory newPersistenceManagerFactory(Map props) {
+ throw new IllegalArgumentException((String) props.get("myKey"));
+ }
+ };
+ pmfb.setConfigLocation(new ClassPathResource("test.properties", getClass()));
+ try {
+ pmfb.afterPropertiesSet();
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ assertTrue("Correct exception", "myValue".equals(ex.getMessage()));
+ }
+ }
+
+ public void testLocalPersistenceManagerFactoryBeanWithName() throws IOException {
+ LocalPersistenceManagerFactoryBean pmfb = new LocalPersistenceManagerFactoryBean() {
+ protected PersistenceManagerFactory newPersistenceManagerFactory(String name) {
+ throw new IllegalArgumentException(name);
+ }
+ };
+ pmfb.setPersistenceManagerFactoryName("myName");
+ try {
+ pmfb.afterPropertiesSet();
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ assertTrue("Correct exception", "myName".equals(ex.getMessage()));
+ }
+ }
+
+ public void testLocalPersistenceManagerFactoryBeanWithNameAndProperties() throws IOException {
+ LocalPersistenceManagerFactoryBean pmfb = new LocalPersistenceManagerFactoryBean() {
+ protected PersistenceManagerFactory newPersistenceManagerFactory(String name) {
+ throw new IllegalArgumentException(name);
+ }
+ };
+ pmfb.setPersistenceManagerFactoryName("myName");
+ pmfb.getJdoPropertyMap().put("myKey", "myValue");
+ try {
+ pmfb.afterPropertiesSet();
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ assertTrue(ex.getMessage().indexOf("persistenceManagerFactoryName") != -1);
+ assertTrue(ex.getMessage().indexOf("jdoProp") != -1);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/jdo/support/JdoDaoSupportTests.java b/org.springframework.testsuite/src/test/java/org/springframework/orm/jdo/support/JdoDaoSupportTests.java
new file mode 100644
index 00000000000..89b3987b111
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/jdo/support/JdoDaoSupportTests.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.orm.jdo.support;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jdo.PersistenceManagerFactory;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.orm.jdo.JdoTemplate;
+
+/**
+ * @author Juergen Hoeller
+ * @since 30.07.2003
+ */
+public class JdoDaoSupportTests extends TestCase {
+
+ public void testJdoDaoSupportWithPersistenceManagerFactory() throws Exception {
+ MockControl pmfControl = MockControl.createControl(PersistenceManagerFactory.class);
+ PersistenceManagerFactory pmf = (PersistenceManagerFactory) pmfControl.getMock();
+ pmf.getConnectionFactory();
+ pmfControl.setReturnValue(null, 1);
+ pmfControl.replay();
+ final List test = new ArrayList();
+ JdoDaoSupport dao = new JdoDaoSupport() {
+ protected void initDao() {
+ test.add("test");
+ }
+ };
+ dao.setPersistenceManagerFactory(pmf);
+ dao.afterPropertiesSet();
+ assertEquals("Correct PersistenceManagerFactory", pmf, dao.getPersistenceManagerFactory());
+ assertEquals("Correct JdoTemplate", pmf, dao.getJdoTemplate().getPersistenceManagerFactory());
+ assertEquals("initDao called", test.size(), 1);
+ pmfControl.verify();
+ }
+
+ public void testJdoDaoSupportWithJdoTemplate() throws Exception {
+ JdoTemplate template = new JdoTemplate();
+ final List test = new ArrayList();
+ JdoDaoSupport dao = new JdoDaoSupport() {
+ protected void initDao() {
+ test.add("test");
+ }
+ };
+ dao.setJdoTemplate(template);
+ dao.afterPropertiesSet();
+ assertEquals("Correct JdoTemplate", template, dao.getJdoTemplate());
+ assertEquals("initDao called", test.size(), 1);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/jdo/support/OpenPersistenceManagerInViewTests.java b/org.springframework.testsuite/src/test/java/org/springframework/orm/jdo/support/OpenPersistenceManagerInViewTests.java
new file mode 100644
index 00000000000..cd34f0a5b84
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/jdo/support/OpenPersistenceManagerInViewTests.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.orm.jdo.support;
+
+import java.io.IOException;
+
+import javax.jdo.PersistenceManager;
+import javax.jdo.PersistenceManagerFactory;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.mock.web.MockFilterConfig;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.mock.web.PassThroughFilterChain;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.StaticWebApplicationContext;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapter;
+
+/**
+ * @author Juergen Hoeller
+ * @since 15.06.2004
+ */
+public class OpenPersistenceManagerInViewTests extends TestCase {
+
+ public void testOpenPersistenceManagerInViewInterceptor() throws Exception {
+ MockControl pmfControl = MockControl.createControl(PersistenceManagerFactory.class);
+ PersistenceManagerFactory pmf = (PersistenceManagerFactory) pmfControl.getMock();
+ MockControl pmControl = MockControl.createControl(PersistenceManager.class);
+ PersistenceManager pm = (PersistenceManager) pmControl.getMock();
+
+ OpenPersistenceManagerInViewInterceptor rawInterceptor = new OpenPersistenceManagerInViewInterceptor();
+ rawInterceptor.setPersistenceManagerFactory(pmf);
+ HandlerInterceptor interceptor = new WebRequestHandlerInterceptorAdapter(rawInterceptor);
+
+ MockServletContext sc = new MockServletContext();
+ MockHttpServletRequest request = new MockHttpServletRequest(sc);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 1);
+ pmfControl.replay();
+ pmControl.replay();
+ interceptor.preHandle(request, response, "handler");
+ assertTrue(TransactionSynchronizationManager.hasResource(pmf));
+
+ // check that further invocations simply participate
+ interceptor.preHandle(request, response, "handler");
+
+ interceptor.preHandle(request, response, "handler");
+ interceptor.postHandle(request, response, "handler", null);
+ interceptor.afterCompletion(request, response, "handler", null);
+
+ interceptor.postHandle(request, response, "handler", null);
+ interceptor.afterCompletion(request, response, "handler", null);
+
+ interceptor.preHandle(request, response, "handler");
+ interceptor.postHandle(request, response, "handler", null);
+ interceptor.afterCompletion(request, response, "handler", null);
+
+ pmfControl.verify();
+ pmControl.verify();
+
+ pmfControl.reset();
+ pmControl.reset();
+ pmfControl.replay();
+ pmControl.replay();
+ interceptor.postHandle(request, response, "handler", null);
+ assertTrue(TransactionSynchronizationManager.hasResource(pmf));
+ pmfControl.verify();
+ pmControl.verify();
+
+ pmfControl.reset();
+ pmControl.reset();
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+ interceptor.afterCompletion(request, response, "handler", null);
+ assertFalse(TransactionSynchronizationManager.hasResource(pmf));
+ pmfControl.verify();
+ pmControl.verify();
+ }
+
+ public void testOpenPersistenceManagerInViewFilter() throws Exception {
+ MockControl pmfControl = MockControl.createControl(PersistenceManagerFactory.class);
+ final PersistenceManagerFactory pmf = (PersistenceManagerFactory) pmfControl.getMock();
+ MockControl pmControl = MockControl.createControl(PersistenceManager.class);
+ PersistenceManager pm = (PersistenceManager) pmControl.getMock();
+
+ pmf.getPersistenceManager();
+ pmfControl.setReturnValue(pm, 1);
+ pm.close();
+ pmControl.setVoidCallable(1);
+ pmfControl.replay();
+ pmControl.replay();
+
+ MockControl pmf2Control = MockControl.createControl(PersistenceManagerFactory.class);
+ final PersistenceManagerFactory pmf2 = (PersistenceManagerFactory) pmf2Control.getMock();
+ MockControl pm2Control = MockControl.createControl(PersistenceManager.class);
+ PersistenceManager pm2 = (PersistenceManager) pm2Control.getMock();
+
+ pmf2.getPersistenceManager();
+ pmf2Control.setReturnValue(pm2, 1);
+ pm2.close();
+ pm2Control.setVoidCallable(1);
+ pmf2Control.replay();
+ pm2Control.replay();
+
+ MockServletContext sc = new MockServletContext();
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(sc);
+ wac.getDefaultListableBeanFactory().registerSingleton("persistenceManagerFactory", pmf);
+ wac.getDefaultListableBeanFactory().registerSingleton("myPersistenceManagerFactory", pmf2);
+ wac.refresh();
+ sc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
+ MockHttpServletRequest request = new MockHttpServletRequest(sc);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ MockFilterConfig filterConfig = new MockFilterConfig(wac.getServletContext(), "filter");
+ MockFilterConfig filterConfig2 = new MockFilterConfig(wac.getServletContext(), "filter2");
+ filterConfig2.addInitParameter("persistenceManagerFactoryBeanName", "myPersistenceManagerFactory");
+
+ final OpenPersistenceManagerInViewFilter filter = new OpenPersistenceManagerInViewFilter();
+ filter.init(filterConfig);
+ final OpenPersistenceManagerInViewFilter filter2 = new OpenPersistenceManagerInViewFilter();
+ filter2.init(filterConfig2);
+
+ final FilterChain filterChain = new FilterChain() {
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) {
+ assertTrue(TransactionSynchronizationManager.hasResource(pmf));
+ servletRequest.setAttribute("invoked", Boolean.TRUE);
+ }
+ };
+
+ final FilterChain filterChain2 = new FilterChain() {
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse)
+ throws IOException, ServletException {
+ assertTrue(TransactionSynchronizationManager.hasResource(pmf2));
+ filter.doFilter(servletRequest, servletResponse, filterChain);
+ }
+ };
+
+ FilterChain filterChain3 = new PassThroughFilterChain(filter2, filterChain2);
+
+ assertFalse(TransactionSynchronizationManager.hasResource(pmf));
+ assertFalse(TransactionSynchronizationManager.hasResource(pmf2));
+ filter2.doFilter(request, response, filterChain3);
+ assertFalse(TransactionSynchronizationManager.hasResource(pmf));
+ assertFalse(TransactionSynchronizationManager.hasResource(pmf2));
+ assertNotNull(request.getAttribute("invoked"));
+
+ pmfControl.verify();
+ pmControl.verify();
+ pmf2Control.verify();
+ pm2Control.verify();
+
+ wac.close();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/jdo/test.properties b/org.springframework.testsuite/src/test/java/org/springframework/orm/jdo/test.properties
new file mode 100644
index 00000000000..cd4acea9278
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/jdo/test.properties
@@ -0,0 +1 @@
+myKey=myValue
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/toplink/MockSessionFactory.java b/org.springframework.testsuite/src/test/java/org/springframework/orm/toplink/MockSessionFactory.java
new file mode 100644
index 00000000000..be223561394
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/toplink/MockSessionFactory.java
@@ -0,0 +1,37 @@
+
+package org.springframework.orm.toplink;
+
+import oracle.toplink.sessions.Session;
+
+/**
+ * @author Juergen Hoeller
+ * @since 28.04.2005
+ */
+public class MockSessionFactory implements SessionFactory {
+
+ private Session session;
+
+ public MockSessionFactory(Session session) {
+ this.session = session;
+ }
+
+ public void setSession(Session session) {
+ this.session = session;
+ }
+
+ public Session createSession() {
+ return this.session;
+ }
+
+ public Session createManagedClientSession() {
+ return this.session;
+ }
+
+ public Session createTransactionAwareSession() {
+ return this.session;
+ }
+
+ public void close() {
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/toplink/SessionBrokerFactoryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/orm/toplink/SessionBrokerFactoryTests.java
new file mode 100644
index 00000000000..c8dbcd3899e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/toplink/SessionBrokerFactoryTests.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.orm.toplink;
+
+import junit.framework.TestCase;
+import oracle.toplink.exceptions.ValidationException;
+import oracle.toplink.publicinterface.UnitOfWork;
+import oracle.toplink.sessionbroker.SessionBroker;
+import oracle.toplink.sessions.Session;
+
+/**
+ * @author James Clark
+ */
+public class SessionBrokerFactoryTests extends TestCase {
+
+ /*
+ * When acquiring ClientSessionBrokers, the SessionBroker can throw RuntimeExceptions indicating
+ * that this SessionBroker is not capable of creating "client" Sessions. We need to handle
+ * these differently depending on how the SessionFactory is being used. If we are creating a
+ * plain Session than we can return the original SessionBroker.
+ */
+ public void testSessionBrokerThrowingValidationException() {
+ SessionBroker broker = new MockSingleSessionBroker();
+ SessionBrokerSessionFactory factory = new SessionBrokerSessionFactory(broker);
+
+ assertEquals(factory.createSession(), broker);
+ try {
+ factory.createManagedClientSession();
+ fail("Should have thrown ValidationException");
+ }
+ catch (ValidationException ex) {
+ // expected
+ }
+ }
+
+ /**
+ * Insure that the managed TopLink Session proxy is behaving correctly
+ * when it has been initialized with a SessionBroker.
+ */
+ public void testManagedSessionBroker() {
+ SessionBroker client = new MockClientSessionBroker();
+ SessionBroker broker = new MockServerSessionBroker(client);
+ SessionBrokerSessionFactory factory = new SessionBrokerSessionFactory(broker);
+
+ assertEquals(client, factory.createSession());
+
+ Session session = factory.createManagedClientSession();
+ assertEquals(client, session.getActiveSession());
+ assertNotNull(session.getActiveUnitOfWork());
+ assertEquals(session.getActiveUnitOfWork(), session.getActiveUnitOfWork());
+ }
+
+
+ private class MockSingleSessionBroker extends SessionBroker {
+
+ public MockSingleSessionBroker() {
+ }
+
+ public SessionBroker acquireClientSessionBroker() {
+ throw new ValidationException();
+ }
+ }
+
+
+ private class MockServerSessionBroker extends SessionBroker {
+
+ private SessionBroker client;
+
+ public MockServerSessionBroker(SessionBroker client) {
+ this.client = client;
+ }
+
+ public SessionBroker acquireClientSessionBroker() {
+ return client;
+ }
+ }
+
+
+ private class MockClientSessionBroker extends SessionBroker {
+
+ public MockClientSessionBroker() {
+ }
+
+ public UnitOfWork acquireUnitOfWork() {
+ return new UnitOfWork(this);
+ }
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/toplink/SessionFactoryUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/orm/toplink/SessionFactoryUtilsTests.java
new file mode 100644
index 00000000000..99dcc54994a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/toplink/SessionFactoryUtilsTests.java
@@ -0,0 +1,106 @@
+/*
+ * Created on Mar 18, 2005
+ *
+ */
+
+package org.springframework.orm.toplink;
+
+import junit.framework.TestCase;
+import oracle.toplink.sessions.Session;
+import org.easymock.MockControl;
+
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+
+/**
+ * @author Juergen Hoeller
+ * @author James Clark
+ * @since 28.04.2005
+ */
+public class SessionFactoryUtilsTests extends TestCase {
+
+ /**
+ * When no Session is bound and allowCreate is "false", we should throw an IllegalStateException.
+ * When no Session is bound, and allowCreate is "true", we should get a Session but it should not
+ * be bound to the Thread afterwards.
+ */
+ public void testNoSessionBound() {
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+
+ SessionFactory factory = new SingleSessionFactory(session);
+
+ session.hasExternalTransactionController();
+ sessionControl.setReturnValue(false, 1);
+
+ sessionControl.replay();
+ try {
+ Session boundSession = SessionFactoryUtils.getSession(factory, false);
+ fail();
+ }
+ catch (Throwable t) {
+ assertTrue(t.getClass().equals(IllegalStateException.class));
+ }
+
+ Session boundSession = SessionFactoryUtils.getSession(factory, true);
+ assertTrue(session == boundSession);
+ assertFalse(TransactionSynchronizationManager.hasResource(factory));
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ }
+
+ /**
+ * When called with no previous Session bound, "allowCreate", and "allowSynchronization",
+ * Session should be returned, it should be bound to the Thread, and a synchronization listener
+ * should be in the list of thread synchronizations.
+ */
+ public void testNoSessionBoundAllowAndInit() {
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+
+ SessionFactory factory = new SingleSessionFactory(session);
+
+ session.hasExternalTransactionController();
+ sessionControl.setReturnValue(false, 1);
+
+ sessionControl.replay();
+
+ Session boundSession = SessionFactoryUtils.getSession(factory, true);
+ assertTrue(session == boundSession);
+
+ SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(factory);
+ assertTrue(holder == null);
+
+ TransactionSynchronizationManager.initSynchronization();
+
+ boundSession = SessionFactoryUtils.getSession(factory, true);
+ assertTrue(session == boundSession);
+ assertTrue(TransactionSynchronizationManager.getSynchronizations().size() == 1);
+ assertTrue(TransactionSynchronizationManager.hasResource(factory));
+ assertTrue(session == ((SessionHolder) TransactionSynchronizationManager.getResource(factory)).getSession());
+
+ TransactionSynchronizationManager.clearSynchronization();
+ TransactionSynchronizationManager.unbindResource(factory);
+ }
+
+ public void testNoSessionBoundAllowAndNoInit() {
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+
+ SessionFactory factory = new SingleSessionFactory(session);
+
+ session.hasExternalTransactionController();
+ sessionControl.setReturnValue(false, 2);
+
+ sessionControl.replay();
+
+ Session boundSession = SessionFactoryUtils.getSession(factory, true);
+ assertTrue(session == boundSession);
+
+ SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(factory);
+ assertTrue(holder == null);
+
+ boundSession = SessionFactoryUtils.getSession(factory, true);
+ assertTrue(session == boundSession);
+ assertFalse(TransactionSynchronizationManager.hasResource(factory));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/toplink/TopLinkInterceptorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/orm/toplink/TopLinkInterceptorTests.java
new file mode 100644
index 00000000000..819133c2ddc
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/toplink/TopLinkInterceptorTests.java
@@ -0,0 +1,98 @@
+/*
+ * Created on Mar 20, 2005
+ *
+ */
+
+package org.springframework.orm.toplink;
+
+import junit.framework.TestCase;
+import org.aopalliance.intercept.MethodInvocation;
+import org.easymock.MockControl;
+
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+
+import oracle.toplink.sessions.Session;
+
+/**
+ * @author Juergen Hoeller
+ * @author James Clark
+ * @since 28.04.2005
+ */
+public class TopLinkInterceptorTests extends TestCase {
+
+ public void testInterceptorWithNoSessionBoundAndNoSynchronizations() throws Throwable {
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ MockControl methodInvocationControl = MockControl.createControl(MethodInvocation.class);
+ MethodInvocation methodInvocation = (MethodInvocation) methodInvocationControl.getMock();
+
+ SessionFactory factory = new SingleSessionFactory(session);
+
+ TopLinkInterceptor interceptor = new TopLinkInterceptor();
+ interceptor.setSessionFactory(factory);
+
+ methodInvocation.proceed();
+ methodInvocationControl.setReturnValue(null, 1);
+ session.release();
+ sessionControl.setVoidCallable(1);
+
+ methodInvocationControl.replay();
+ sessionControl.replay();
+
+ try {
+ interceptor.invoke(methodInvocation);
+ }
+ catch (Throwable t) {
+ System.out.println(t);
+ t.printStackTrace();
+ fail();
+ }
+
+ assertFalse(TransactionSynchronizationManager.hasResource(factory));
+
+ sessionControl.verify();
+ methodInvocationControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testInterceptorWithNoSessionBoundAndSynchronizationsActive() {
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+ MockControl methodInvocationControl = MockControl.createControl(MethodInvocation.class);
+ MethodInvocation methodInvocation = (MethodInvocation) methodInvocationControl.getMock();
+
+ SessionFactory factory = new SingleSessionFactory(session);
+
+ TopLinkInterceptor interceptor = new TopLinkInterceptor();
+ interceptor.setSessionFactory(factory);
+
+ try {
+ methodInvocation.proceed();
+ }
+ catch (Throwable e) {
+ fail();
+ }
+ methodInvocationControl.setReturnValue(null, 1);
+
+ methodInvocationControl.replay();
+ sessionControl.replay();
+
+ TransactionSynchronizationManager.initSynchronization();
+ try {
+ interceptor.invoke(methodInvocation);
+ }
+ catch (Throwable t) {
+ fail();
+ }
+
+ assertTrue(TransactionSynchronizationManager.hasResource(factory));
+ assertTrue(TransactionSynchronizationManager.getSynchronizations().size() == 1);
+
+ TransactionSynchronizationManager.clearSynchronization();
+ TransactionSynchronizationManager.unbindResource(factory);
+
+ sessionControl.verify();
+ methodInvocationControl.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/toplink/TopLinkJtaTransactionTests.java b/org.springframework.testsuite/src/test/java/org/springframework/orm/toplink/TopLinkJtaTransactionTests.java
new file mode 100644
index 00000000000..398a814749d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/toplink/TopLinkJtaTransactionTests.java
@@ -0,0 +1,321 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.orm.toplink;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.transaction.Status;
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+
+import junit.framework.TestCase;
+import oracle.toplink.exceptions.TopLinkException;
+import oracle.toplink.sessions.Session;
+import org.easymock.MockControl;
+
+import org.springframework.transaction.MockJtaTransaction;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.jta.JtaTransactionManager;
+import org.springframework.transaction.support.TransactionCallback;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+import org.springframework.transaction.support.TransactionTemplate;
+
+/**
+ * @author Juergen Hoeller
+ * @author James Clark
+ * @since 28.04.2005
+ */
+public class TopLinkJtaTransactionTests extends TestCase {
+
+ public void testParticipatingJtaTransactionWithWithRequiresNew() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockControl tx1Control = MockControl.createControl(javax.transaction.Transaction.class);
+ javax.transaction.Transaction tx1 = (javax.transaction.Transaction) tx1Control.getMock();
+
+ MockControl session1Control = MockControl.createControl(Session.class);
+ Session session1 = (Session) session1Control.getMock();
+ MockControl session2Control = MockControl.createControl(Session.class);
+ final Session session2 = (Session) session2Control.getMock();
+ final MockSessionFactory sf = new MockSessionFactory(session1);
+
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 5);
+ ut.begin();
+ utControl.setVoidCallable(2);
+ tm.suspend();
+ tmControl.setReturnValue(tx1, 1);
+ tm.resume(tx1);
+ tmControl.setVoidCallable(1);
+ ut.commit();
+ utControl.setVoidCallable(2);
+
+// session1.hasExternalTransactionController();
+// session1Control.setReturnValue(true,1);
+ session1.release();
+ session1Control.setVoidCallable(1);
+// session2.hasExternalTransactionController();
+// session2Control.setReturnValue(true,1);
+ session2.release();
+ session2Control.setVoidCallable(1);
+
+ utControl.replay();
+ tmControl.replay();
+ session1Control.replay();
+ session2Control.replay();
+
+ JtaTransactionManager ptm = new JtaTransactionManager();
+ ptm.setUserTransaction(ut);
+ ptm.setTransactionManager(tm);
+ final TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ SessionFactoryUtils.getSession(sf, true);
+ final SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sf);
+ assertTrue("Has thread session", holder != null);
+ sf.setSession(session2);
+
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ TopLinkTemplate ht = new TopLinkTemplate(sf);
+ return ht.executeFind(new TopLinkCallback() {
+ public Object doInTopLink(Session session) {
+ assertTrue("Not enclosing session", session != holder.getSession());
+ return null;
+ }
+ });
+ }
+ });
+ assertTrue("Same thread session as before",
+ holder.getSession() == SessionFactoryUtils.getSession(sf, false));
+ return null;
+ }
+ });
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+
+ utControl.verify();
+ tmControl.verify();
+ session1Control.verify();
+ session2Control.verify();
+ }
+
+ public void testJtaTransactionCommit() throws Exception {
+ doTestJtaTransactionCommit(Status.STATUS_NO_TRANSACTION);
+ }
+
+ public void testJtaTransactionCommitWithExisting() throws Exception {
+ doTestJtaTransactionCommit(Status.STATUS_ACTIVE);
+ }
+
+ private void doTestJtaTransactionCommit(int status) throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(status, 1);
+ if (status == Status.STATUS_NO_TRANSACTION) {
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.commit();
+ utControl.setVoidCallable(1);
+ }
+ else {
+ ut.getStatus();
+ utControl.setReturnValue(status, 1);
+ }
+ utControl.replay();
+
+ final MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ final SessionFactory sf = new SingleSessionFactory(session);
+
+ sessionControl.replay();
+
+ JtaTransactionManager ptm = new JtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ final List l = new ArrayList();
+ l.add("test");
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ try {
+ assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ TopLinkTemplate ht = new TopLinkTemplate(sf);
+ List htl = ht.executeFind(new TopLinkCallback() {
+ public Object doInTopLink(Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session, sess);
+ return l;
+ }
+ });
+
+ ht = new TopLinkTemplate(sf);
+ htl = ht.executeFind(new TopLinkCallback() {
+ public Object doInTopLink(Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session, sess);
+ return l;
+ }
+ });
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+
+ sessionControl.verify();
+ sessionControl.reset();
+
+ try {
+ session.release();
+ sessionControl.setVoidCallable(1);
+ }
+ catch (TopLinkException e) {
+ }
+ sessionControl.replay();
+ return htl;
+ }
+ catch (Error err) {
+ err.printStackTrace();
+ throw err;
+ }
+ }
+ });
+
+ assertTrue("Correct result list", result == l);
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ sessionControl.verify();
+ }
+
+ public void testJtaTransactionCommitWithJtaTm() throws Exception {
+ doTestJtaTransactionCommitWithJtaTm(Status.STATUS_NO_TRANSACTION);
+ }
+
+ public void testJtaTransactionCommitWithJtaTmAndExisting() throws Exception {
+ doTestJtaTransactionCommitWithJtaTm(Status.STATUS_ACTIVE);
+ }
+
+ private void doTestJtaTransactionCommitWithJtaTm(int status) throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(status, 1);
+ if (status == Status.STATUS_NO_TRANSACTION) {
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.commit();
+ utControl.setVoidCallable(1);
+ }
+ else {
+ ut.getStatus();
+ utControl.setReturnValue(status, 1);
+ }
+
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockJtaTransaction transaction = new MockJtaTransaction();
+ tm.getStatus();
+ tmControl.setReturnValue(Status.STATUS_ACTIVE, 6);
+ tm.getTransaction();
+ tmControl.setReturnValue(transaction, 6);
+
+ final MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ final SessionFactory sf = new SingleSessionFactory(session);
+
+ utControl.replay();
+ tmControl.replay();
+ sessionControl.replay();
+
+ JtaTransactionManager ptm = new JtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ final List l = new ArrayList();
+ l.add("test");
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ try {
+ assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+
+ TopLinkTemplate ht = new TopLinkTemplate(sf);
+ List htl = ht.executeFind(new TopLinkCallback() {
+ public Object doInTopLink(Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session, sess);
+ return l;
+ }
+ });
+
+ ht = new TopLinkTemplate(sf);
+ htl = ht.executeFind(new TopLinkCallback() {
+ public Object doInTopLink(Session sess) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ assertEquals(session, sess);
+ return l;
+ }
+ });
+
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ sessionControl.verify();
+ sessionControl.reset();
+ try {
+ session.release();
+ sessionControl.setVoidCallable(1);
+ }
+ catch (TopLinkException e) {
+ }
+ sessionControl.replay();
+ return htl;
+ }
+ catch (Error err) {
+ err.printStackTrace();
+ throw err;
+ }
+ }
+ });
+
+ assertTrue("Correct result list", result == l);
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ sessionControl.verify();
+ }
+
+ protected void tearDown() {
+ assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/toplink/TopLinkTemplateTests.java b/org.springframework.testsuite/src/test/java/org/springframework/orm/toplink/TopLinkTemplateTests.java
new file mode 100644
index 00000000000..73adb96ea18
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/toplink/TopLinkTemplateTests.java
@@ -0,0 +1,117 @@
+/*
+ * Created on Mar 20, 2005
+ *
+ */
+
+package org.springframework.orm.toplink;
+
+import junit.framework.TestCase;
+import oracle.toplink.exceptions.TopLinkException;
+import oracle.toplink.sessions.Session;
+import org.easymock.MockControl;
+
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+
+/**
+ * @author Juergen Hoeller
+ * @author James Clark
+ * @since 28.04.2005
+ */
+public class TopLinkTemplateTests extends TestCase {
+
+ public void testTemplateNotAllowingCreate() {
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+
+ SessionFactory factory = new SingleSessionFactory(session);
+
+ TopLinkTemplate template = new TopLinkTemplate();
+ template.setAllowCreate(false);
+ template.setSessionFactory(factory);
+ try {
+ template.execute(new TopLinkCallback() {
+ public Object doInTopLink(Session session) throws TopLinkException {
+ return null;
+ }
+ });
+ fail();
+ }
+ catch (Exception e) {
+ }
+ }
+
+ public void testTemplateWithCreate() {
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+
+ SessionFactory factory = new SingleSessionFactory(session);
+
+ session.release();
+ sessionControl.setVoidCallable(1);
+
+ sessionControl.replay();
+
+ TopLinkTemplate template = new TopLinkTemplate();
+ template.setAllowCreate(true);
+ template.setSessionFactory(factory);
+ template.execute(new TopLinkCallback() {
+ public Object doInTopLink(Session session) throws TopLinkException {
+ assertTrue(session != null);
+ return null;
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.hasResource(factory));
+
+ sessionControl.verify();
+ }
+
+ public void testTemplateWithExistingSessionAndNoCreate() {
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+
+ SessionFactory factory = new SingleSessionFactory(session);
+
+ sessionControl.replay();
+
+ SessionHolder sessionHolder = new SessionHolder(factory.createSession());
+ TransactionSynchronizationManager.bindResource(factory, sessionHolder);
+
+ TopLinkTemplate template = new TopLinkTemplate();
+ template.setAllowCreate(false);
+ template.setSessionFactory(factory);
+ template.execute(new TopLinkCallback() {
+ public Object doInTopLink(Session session) throws TopLinkException {
+ assertTrue(session != null);
+ return null;
+ }
+ });
+ assertTrue(TransactionSynchronizationManager.hasResource(factory));
+ sessionControl.verify();
+ TransactionSynchronizationManager.unbindResource(factory);
+ }
+
+ public void testTemplateWithExistingSessionAndCreateAllowed() {
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ Session session = (Session) sessionControl.getMock();
+
+ SessionFactory factory = new SingleSessionFactory(session);
+
+ sessionControl.replay();
+
+ SessionHolder sessionHolder = new SessionHolder(factory.createSession());
+ TransactionSynchronizationManager.bindResource(factory, sessionHolder);
+
+ TopLinkTemplate template = new TopLinkTemplate();
+ template.setAllowCreate(true);
+ template.setSessionFactory(factory);
+ template.execute(new TopLinkCallback() {
+ public Object doInTopLink(Session session) throws TopLinkException {
+ assertTrue(session != null);
+ return null;
+ }
+ });
+ assertTrue(TransactionSynchronizationManager.hasResource(factory));
+ sessionControl.verify();
+ TransactionSynchronizationManager.unbindResource(factory);
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/orm/toplink/TopLinkTransactionManagerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/orm/toplink/TopLinkTransactionManagerTests.java
new file mode 100644
index 00000000000..0b97b6654b4
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/orm/toplink/TopLinkTransactionManagerTests.java
@@ -0,0 +1,496 @@
+/*
+ * Created on Mar 20, 2005
+ *
+ */
+
+package org.springframework.orm.toplink;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+import oracle.toplink.sessions.Session;
+import oracle.toplink.sessions.UnitOfWork;
+import org.easymock.MockControl;
+
+import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.UnexpectedRollbackException;
+import org.springframework.transaction.support.TransactionCallback;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+import org.springframework.transaction.support.TransactionTemplate;
+
+/**
+ * @author Juergen Hoeller
+ * @author James Clark
+ * @since 28.04.2005
+ */
+public class TopLinkTransactionManagerTests extends TestCase {
+
+ public void testTransactionCommit() {
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ MockControl uowControl = MockControl.createControl(UnitOfWork.class);
+ UnitOfWork uow = (UnitOfWork) uowControl.getMock();
+
+ final SessionFactory sf = new MockSessionFactory(session);
+
+ // during commit, TM must get the active UnitOfWork
+ session.getActiveUnitOfWork();
+ sessionControl.setReturnValue(uow, 2);
+ uow.beginEarlyTransaction();
+ uowControl.setVoidCallable(1);
+ uow.commit();
+ uowControl.setVoidCallable();
+ // session should be released when it was bound explicitly by the TM
+ session.release();
+ sessionControl.setVoidCallable();
+
+ sessionControl.replay();
+ uowControl.replay();
+
+ TopLinkTransactionManager tm = new TopLinkTransactionManager();
+ tm.setJdbcExceptionTranslator(new SQLStateSQLExceptionTranslator());
+ tm.setSessionFactory(sf);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
+ tt.setTimeout(10);
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ TopLinkTemplate template = new TopLinkTemplate(sf);
+ return template.execute(new TopLinkCallback() {
+ public Object doInTopLink(Session session) {
+ return null;
+ }
+ });
+ }
+ });
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ sessionControl.verify();
+ uowControl.verify();
+ }
+
+ public void testTransactionRollback() {
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ MockControl uowControl = MockControl.createControl(UnitOfWork.class);
+ UnitOfWork uow = (UnitOfWork) uowControl.getMock();
+
+ final SessionFactory sf = new MockSessionFactory(session);
+
+ session.getActiveUnitOfWork();
+ sessionControl.setReturnValue(uow, 1);
+ uow.beginEarlyTransaction();
+ uowControl.setVoidCallable(1);
+ session.release();
+ sessionControl.setVoidCallable(1);
+
+ sessionControl.replay();
+ uowControl.replay();
+
+ TopLinkTransactionManager tm = new TopLinkTransactionManager();
+ tm.setSessionFactory(sf);
+ tm.setJdbcExceptionTranslator(new SQLStateSQLExceptionTranslator());
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
+ tt.setTimeout(10);
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ try {
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ TopLinkTemplate template = new TopLinkTemplate(sf);
+ return template.execute(new TopLinkCallback() {
+ public Object doInTopLink(Session session) {
+ throw new RuntimeException("failure");
+ }
+ });
+ }
+ });
+ fail("Should have propagated RuntimeException");
+ }
+ catch (RuntimeException ex) {
+ assertTrue(ex.getMessage().equals("failure"));
+ }
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ sessionControl.verify();
+ uowControl.verify();
+ }
+
+ public void testTransactionRollbackOnly() {
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+
+ final SessionFactory sf = new MockSessionFactory(session);
+ session.release();
+ sessionControl.setVoidCallable();
+ sessionControl.replay();
+
+ TopLinkTransactionManager tm = new TopLinkTransactionManager();
+ tm.setSessionFactory(sf);
+ tm.setLazyDatabaseTransaction(true);
+ tm.setJdbcExceptionTranslator(new SQLStateSQLExceptionTranslator());
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
+ tt.setTimeout(10);
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread session",
+ TransactionSynchronizationManager.hasResource(sf));
+ TopLinkTemplate template = new TopLinkTemplate(sf);
+ template.execute(new TopLinkCallback() {
+ public Object doInTopLink(Session session) {
+ return null;
+ }
+ });
+ status.setRollbackOnly();
+ return null;
+ }
+ });
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ sessionControl.verify();
+ }
+
+ public void testParticipatingTransactionWithCommit() {
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ MockControl uowControl = MockControl.createControl(UnitOfWork.class);
+ UnitOfWork uow = (UnitOfWork) uowControl.getMock();
+
+ final SessionFactory sf = new MockSessionFactory(session);
+
+ session.getActiveUnitOfWork();
+ sessionControl.setReturnValue(uow, 2);
+ uow.beginEarlyTransaction();
+ uowControl.setVoidCallable(1);
+ uow.commit();
+ uowControl.setVoidCallable();
+ session.release();
+ sessionControl.setVoidCallable();
+
+ sessionControl.replay();
+ uowControl.replay();
+
+ PlatformTransactionManager tm = new TopLinkTransactionManager(sf);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ return tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ TopLinkTemplate ht = new TopLinkTemplate(sf);
+ return ht.executeFind(new TopLinkCallback() {
+ public Object doInTopLink(Session injectedSession) {
+ assertTrue(session == injectedSession);
+ return null;
+ }
+ });
+ }
+ });
+ }
+ });
+
+ sessionControl.verify();
+ uowControl.verify();
+ }
+
+ public void testParticipatingTransactionWithRollback() {
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+
+ final SessionFactory sf = new MockSessionFactory(session);
+
+ session.release();
+ sessionControl.setVoidCallable();
+
+ sessionControl.replay();
+
+ TopLinkTransactionManager tm = new TopLinkTransactionManager(sf);
+ tm.setLazyDatabaseTransaction(true);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ try {
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ return tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ TopLinkTemplate ht = new TopLinkTemplate(sf);
+ return ht.executeFind(new TopLinkCallback() {
+ public Object doInTopLink(Session session) {
+ throw new RuntimeException("application exception");
+ }
+ });
+ }
+ });
+ }
+ });
+ fail("Should not thrown RuntimeException");
+ }
+ catch (RuntimeException ex) {
+ assertTrue(ex.getMessage().equals("application exception"));
+ }
+ sessionControl.verify();
+ }
+
+ public void testParticipatingTransactionWithRollbackOnly() {
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ final SessionFactory sf = new MockSessionFactory(session);
+
+ session.release();
+ sessionControl.setVoidCallable();
+
+ sessionControl.replay();
+
+ TopLinkTransactionManager tm = new TopLinkTransactionManager(sf);
+ tm.setLazyDatabaseTransaction(true);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+
+ try {
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ TopLinkTemplate ht = new TopLinkTemplate(sf);
+ ht.execute(new TopLinkCallback() {
+ public Object doInTopLink(Session session) {
+ return null;
+ }
+ });
+ status.setRollbackOnly();
+ return null;
+ }
+ });
+ return null;
+ }
+ });
+ fail("Should have thrown UnexpectedRollbackException");
+ }
+ catch (UnexpectedRollbackException ex) {
+ // expected
+ }
+
+ sessionControl.verify();
+ }
+
+ public void testParticipatingTransactionWithWithRequiresNew() {
+ MockControl session1Control = MockControl.createControl(Session.class);
+ final Session session1 = (Session) session1Control.getMock();
+ MockControl session2Control = MockControl.createControl(Session.class);
+ final Session session2 = (Session) session2Control.getMock();
+
+ MockControl uow1Control = MockControl.createControl(UnitOfWork.class);
+ UnitOfWork uow1 = (UnitOfWork) uow1Control.getMock();
+ MockControl uow2Control = MockControl.createControl(UnitOfWork.class);
+ UnitOfWork uow2 = (UnitOfWork) uow2Control.getMock();
+
+ final MockSessionFactory sf = new MockSessionFactory(session1);
+
+ session2.getActiveUnitOfWork();
+ session2Control.setReturnValue(uow2, 2);
+ uow2.beginEarlyTransaction();
+ uow2Control.setVoidCallable(1);
+ uow2.commit();
+ uow2Control.setVoidCallable();
+ session2.release();
+ session2Control.setVoidCallable();
+
+ session1.getActiveUnitOfWork();
+ session1Control.setReturnValue(uow1, 2);
+ uow1.beginEarlyTransaction();
+ uow1Control.setVoidCallable(1);
+ uow1.commit();
+ uow1Control.setVoidCallable();
+ session1.release();
+ session1Control.setVoidCallable();
+
+ session1Control.replay();
+ uow1Control.replay();
+ session2Control.replay();
+ uow2Control.replay();
+
+ PlatformTransactionManager tm = new TopLinkTransactionManager(sf);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ final SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sf);
+ assertTrue("Has thread session", holder != null);
+ sf.setSession(session2);
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ TopLinkTemplate ht = new TopLinkTemplate(sf);
+ return ht.execute(new TopLinkCallback() {
+ public Object doInTopLink(Session session) {
+ assertTrue("Not enclosing session", session != holder.getSession());
+ return null;
+ }
+ });
+ }
+ });
+ assertTrue("Same thread session as before",
+ holder.getSession() == SessionFactoryUtils.getSession(sf, false));
+ return null;
+ }
+ });
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+
+ session1Control.verify();
+ session2Control.verify();
+ uow1Control.verify();
+ uow2Control.verify();
+ }
+
+ public void testParticipatingTransactionWithWithNotSupported() {
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ MockControl uowControl = MockControl.createControl(UnitOfWork.class);
+ UnitOfWork uow = (UnitOfWork) uowControl.getMock();
+
+ final SessionFactory sf = new MockSessionFactory(session);
+
+ session.getActiveUnitOfWork();
+ sessionControl.setReturnValue(uow, 2);
+ uow.beginEarlyTransaction();
+ uowControl.setVoidCallable(1);
+ uow.commit();
+ uowControl.setVoidCallable();
+ session.release();
+ sessionControl.setVoidCallable(2);
+
+ sessionControl.replay();
+ uowControl.replay();
+
+ TopLinkTransactionManager tm = new TopLinkTransactionManager(sf);
+ final TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sf);
+ assertTrue("Has thread session", holder != null);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ TopLinkTemplate ht = new TopLinkTemplate(sf);
+
+ return ht.execute(new TopLinkCallback() {
+ public Object doInTopLink(Session session) {
+ return null;
+ }
+ });
+ }
+ });
+ assertTrue("Same thread session as before", holder.getSession() == SessionFactoryUtils.getSession(sf, false));
+ return null;
+ }
+ });
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+
+ sessionControl.verify();
+ uowControl.verify();
+ }
+
+ public void testTransactionWithPropagationSupports() {
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+
+ final SessionFactory sf = new MockSessionFactory(session);
+
+ // not a new transaction, won't start a new one
+ session.release();
+ sessionControl.setVoidCallable();
+
+ sessionControl.replay();
+
+ PlatformTransactionManager tm = new TopLinkTransactionManager(sf);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+
+ tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("Is not new transaction", !status.isNewTransaction());
+ TopLinkTemplate ht = new TopLinkTemplate(sf);
+ ht.execute(new TopLinkCallback() {
+ public Object doInTopLink(Session session) {
+ return null;
+ }
+ });
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ return null;
+ }
+ });
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ sessionControl.verify();
+ }
+
+ public void testTransactionCommitWithReadOnly() {
+ MockControl sessionControl = MockControl.createControl(Session.class);
+ final Session session = (Session) sessionControl.getMock();
+ MockControl uowControl = MockControl.createControl(UnitOfWork.class);
+ UnitOfWork uow = (UnitOfWork) uowControl.getMock();
+
+ final SessionFactory sf = new MockSessionFactory(session);
+
+ session.release();
+ sessionControl.setVoidCallable();
+
+ sessionControl.replay();
+ uowControl.replay();
+
+ TopLinkTransactionManager tm = new TopLinkTransactionManager(sf);
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.setReadOnly(true);
+ final List l = new ArrayList();
+ l.add("test");
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+
+ Object result = tt.execute(new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
+ TopLinkTemplate ht = new TopLinkTemplate(sf);
+ return ht.executeFind(new TopLinkCallback() {
+ public Object doInTopLink(Session session) {
+ return l;
+ }
+ });
+ }
+ });
+ assertTrue("Correct result list", result == l);
+
+ assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
+ assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
+ sessionControl.verify();
+ uowControl.verify();
+ }
+
+ protected void tearDown() {
+ assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/remoting/httpinvoker/HttpInvokerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/remoting/httpinvoker/HttpInvokerTests.java
new file mode 100644
index 00000000000..25a3bd2717b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/remoting/httpinvoker/HttpInvokerTests.java
@@ -0,0 +1,469 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.remoting.httpinvoker;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import junit.framework.TestCase;
+import org.aopalliance.intercept.MethodInvocation;
+
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.BeanClassLoaderAware;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.remoting.RemoteAccessException;
+import org.springframework.remoting.support.DefaultRemoteInvocationExecutor;
+import org.springframework.remoting.support.RemoteInvocation;
+import org.springframework.remoting.support.RemoteInvocationFactory;
+import org.springframework.remoting.support.RemoteInvocationResult;
+
+/**
+ * @author Juergen Hoeller
+ * @since 09.08.2004
+ */
+public class HttpInvokerTests extends TestCase {
+
+ public void testHttpInvokerProxyFactoryBeanAndServiceExporter() throws Throwable {
+ doTestHttpInvokerProxyFactoryBeanAndServiceExporter(false);
+ }
+
+ public void testHttpInvokerProxyFactoryBeanAndServiceExporterWithExplicitClassLoader() throws Throwable {
+ doTestHttpInvokerProxyFactoryBeanAndServiceExporter(true);
+ }
+
+ private void doTestHttpInvokerProxyFactoryBeanAndServiceExporter(boolean explicitClassLoader) throws Throwable {
+ TestBean target = new TestBean("myname", 99);
+
+ final HttpInvokerServiceExporter exporter = new HttpInvokerServiceExporter();
+ exporter.setServiceInterface(ITestBean.class);
+ exporter.setService(target);
+ exporter.afterPropertiesSet();
+
+ HttpInvokerProxyFactoryBean pfb = new HttpInvokerProxyFactoryBean();
+ pfb.setServiceInterface(ITestBean.class);
+ pfb.setServiceUrl("http://myurl");
+
+ pfb.setHttpInvokerRequestExecutor(new AbstractHttpInvokerRequestExecutor() {
+ protected RemoteInvocationResult doExecuteRequest(
+ HttpInvokerClientConfiguration config, ByteArrayOutputStream baos) throws Exception {
+ assertEquals("http://myurl", config.getServiceUrl());
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ request.setContent(baos.toByteArray());
+ exporter.handleRequest(request, response);
+ return readRemoteInvocationResult(
+ new ByteArrayInputStream(response.getContentAsByteArray()), config.getCodebaseUrl());
+ }
+ });
+ if (explicitClassLoader) {
+ ((BeanClassLoaderAware) pfb.getHttpInvokerRequestExecutor()).setBeanClassLoader(getClass().getClassLoader());
+ }
+
+ pfb.afterPropertiesSet();
+ ITestBean proxy = (ITestBean) pfb.getObject();
+ assertEquals("myname", proxy.getName());
+ assertEquals(99, proxy.getAge());
+ proxy.setAge(50);
+ assertEquals(50, proxy.getAge());
+ proxy.setStringArray(new String[] {"str1", "str2"});
+ assertTrue(Arrays.equals(new String[] {"str1", "str2"}, proxy.getStringArray()));
+
+ try {
+ proxy.exceptional(new IllegalStateException());
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ try {
+ proxy.exceptional(new IllegalAccessException());
+ fail("Should have thrown IllegalAccessException");
+ }
+ catch (IllegalAccessException ex) {
+ // expected
+ }
+ }
+
+ public void testHttpInvokerProxyFactoryBeanAndServiceExporterWithIOException() throws Exception {
+ TestBean target = new TestBean("myname", 99);
+
+ final HttpInvokerServiceExporter exporter = new HttpInvokerServiceExporter();
+ exporter.setServiceInterface(ITestBean.class);
+ exporter.setService(target);
+ exporter.afterPropertiesSet();
+
+ HttpInvokerProxyFactoryBean pfb = new HttpInvokerProxyFactoryBean();
+ pfb.setServiceInterface(ITestBean.class);
+ pfb.setServiceUrl("http://myurl");
+
+ pfb.setHttpInvokerRequestExecutor(new HttpInvokerRequestExecutor() {
+ public RemoteInvocationResult executeRequest(
+ HttpInvokerClientConfiguration config, RemoteInvocation invocation) throws IOException {
+ throw new IOException("argh");
+ }
+ });
+
+ pfb.afterPropertiesSet();
+ ITestBean proxy = (ITestBean) pfb.getObject();
+ try {
+ proxy.setAge(50);
+ fail("Should have thrown RemoteAccessException");
+ }
+ catch (RemoteAccessException ex) {
+ // expected
+ assertTrue(ex.getCause() instanceof IOException);
+ }
+ }
+
+ public void testHttpInvokerProxyFactoryBeanAndServiceExporterWithGzipCompression() throws Throwable {
+ TestBean target = new TestBean("myname", 99);
+
+ final HttpInvokerServiceExporter exporter = new HttpInvokerServiceExporter() {
+ protected InputStream decorateInputStream(HttpServletRequest request, InputStream is) throws IOException {
+ if ("gzip".equals(request.getHeader("Compression"))) {
+ return new GZIPInputStream(is);
+ }
+ else {
+ return is;
+ }
+ }
+ protected OutputStream decorateOutputStream(
+ HttpServletRequest request, HttpServletResponse response, OutputStream os) throws IOException {
+ if ("gzip".equals(request.getHeader("Compression"))) {
+ return new GZIPOutputStream(os);
+ }
+ else {
+ return os;
+ }
+ }
+ };
+ exporter.setServiceInterface(ITestBean.class);
+ exporter.setService(target);
+ exporter.afterPropertiesSet();
+
+ HttpInvokerProxyFactoryBean pfb = new HttpInvokerProxyFactoryBean();
+ pfb.setServiceInterface(ITestBean.class);
+ pfb.setServiceUrl("http://myurl");
+
+ pfb.setHttpInvokerRequestExecutor(new AbstractHttpInvokerRequestExecutor() {
+ protected RemoteInvocationResult doExecuteRequest(
+ HttpInvokerClientConfiguration config, ByteArrayOutputStream baos)
+ throws IOException, ClassNotFoundException {
+ assertEquals("http://myurl", config.getServiceUrl());
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addHeader("Compression", "gzip");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ request.setContent(baos.toByteArray());
+ try {
+ exporter.handleRequest(request, response);
+ }
+ catch (ServletException ex) {
+ throw new IOException(ex.toString());
+ }
+ return readRemoteInvocationResult(
+ new ByteArrayInputStream(response.getContentAsByteArray()), config.getCodebaseUrl());
+ }
+ protected OutputStream decorateOutputStream(OutputStream os) throws IOException {
+ return new GZIPOutputStream(os);
+ }
+ protected InputStream decorateInputStream(InputStream is) throws IOException {
+ return new GZIPInputStream(is);
+ }
+ });
+
+ pfb.afterPropertiesSet();
+ ITestBean proxy = (ITestBean) pfb.getObject();
+ assertEquals("myname", proxy.getName());
+ assertEquals(99, proxy.getAge());
+ proxy.setAge(50);
+ assertEquals(50, proxy.getAge());
+
+ try {
+ proxy.exceptional(new IllegalStateException());
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ try {
+ proxy.exceptional(new IllegalAccessException());
+ fail("Should have thrown IllegalAccessException");
+ }
+ catch (IllegalAccessException ex) {
+ // expected
+ }
+ }
+
+ public void testHttpInvokerProxyFactoryBeanAndServiceExporterWithWrappedInvocations() throws Throwable {
+ TestBean target = new TestBean("myname", 99);
+
+ final HttpInvokerServiceExporter exporter = new HttpInvokerServiceExporter() {
+ protected RemoteInvocation doReadRemoteInvocation(ObjectInputStream ois)
+ throws IOException, ClassNotFoundException {
+ Object obj = ois.readObject();
+ if (!(obj instanceof TestRemoteInvocationWrapper)) {
+ throw new IOException("Deserialized object needs to be assignable to type [" +
+ TestRemoteInvocationWrapper.class.getName() + "]: " + obj);
+ }
+ return ((TestRemoteInvocationWrapper) obj).remoteInvocation;
+ }
+ protected void doWriteRemoteInvocationResult(RemoteInvocationResult result, ObjectOutputStream oos)
+ throws IOException {
+ oos.writeObject(new TestRemoteInvocationResultWrapper(result));
+ }
+ };
+ exporter.setServiceInterface(ITestBean.class);
+ exporter.setService(target);
+ exporter.afterPropertiesSet();
+
+ HttpInvokerProxyFactoryBean pfb = new HttpInvokerProxyFactoryBean();
+ pfb.setServiceInterface(ITestBean.class);
+ pfb.setServiceUrl("http://myurl");
+
+ pfb.setHttpInvokerRequestExecutor(new AbstractHttpInvokerRequestExecutor() {
+ protected RemoteInvocationResult doExecuteRequest(
+ HttpInvokerClientConfiguration config, ByteArrayOutputStream baos) throws Exception {
+ assertEquals("http://myurl", config.getServiceUrl());
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ request.setContent(baos.toByteArray());
+ exporter.handleRequest(request, response);
+ return readRemoteInvocationResult(
+ new ByteArrayInputStream(response.getContentAsByteArray()), config.getCodebaseUrl());
+ }
+ protected void doWriteRemoteInvocation(RemoteInvocation invocation, ObjectOutputStream oos) throws IOException {
+ oos.writeObject(new TestRemoteInvocationWrapper(invocation));
+ }
+ protected RemoteInvocationResult doReadRemoteInvocationResult(ObjectInputStream ois)
+ throws IOException, ClassNotFoundException {
+ Object obj = ois.readObject();
+ if (!(obj instanceof TestRemoteInvocationResultWrapper)) {
+ throw new IOException("Deserialized object needs to be assignable to type ["
+ + TestRemoteInvocationResultWrapper.class.getName() + "]: " + obj);
+ }
+ return ((TestRemoteInvocationResultWrapper) obj).remoteInvocationResult;
+ }
+ });
+
+ pfb.afterPropertiesSet();
+ ITestBean proxy = (ITestBean) pfb.getObject();
+ assertEquals("myname", proxy.getName());
+ assertEquals(99, proxy.getAge());
+ proxy.setAge(50);
+ assertEquals(50, proxy.getAge());
+
+ try {
+ proxy.exceptional(new IllegalStateException());
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ try {
+ proxy.exceptional(new IllegalAccessException());
+ fail("Should have thrown IllegalAccessException");
+ }
+ catch (IllegalAccessException ex) {
+ // expected
+ }
+ }
+
+ public void testHttpInvokerProxyFactoryBeanAndServiceExporterWithInvocationAttributes() throws Exception {
+ TestBean target = new TestBean("myname", 99);
+
+ final HttpInvokerServiceExporter exporter = new HttpInvokerServiceExporter();
+ exporter.setServiceInterface(ITestBean.class);
+ exporter.setService(target);
+ exporter.setRemoteInvocationExecutor(new DefaultRemoteInvocationExecutor() {
+ public Object invoke(RemoteInvocation invocation, Object targetObject)
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+ assertNotNull(invocation.getAttributes());
+ assertEquals(1, invocation.getAttributes().size());
+ assertEquals("myValue", invocation.getAttributes().get("myKey"));
+ assertEquals("myValue", invocation.getAttribute("myKey"));
+ return super.invoke(invocation, targetObject);
+ }
+ });
+ exporter.afterPropertiesSet();
+
+ HttpInvokerProxyFactoryBean pfb = new HttpInvokerProxyFactoryBean();
+ pfb.setServiceInterface(ITestBean.class);
+ pfb.setServiceUrl("http://myurl");
+ pfb.setRemoteInvocationFactory(new RemoteInvocationFactory() {
+ public RemoteInvocation createRemoteInvocation(MethodInvocation methodInvocation) {
+ RemoteInvocation invocation = new RemoteInvocation(methodInvocation);
+ invocation.addAttribute("myKey", "myValue");
+ try {
+ invocation.addAttribute("myKey", "myValue");
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected: already defined
+ }
+ assertNotNull(invocation.getAttributes());
+ assertEquals(1, invocation.getAttributes().size());
+ assertEquals("myValue", invocation.getAttributes().get("myKey"));
+ assertEquals("myValue", invocation.getAttribute("myKey"));
+ return invocation;
+ }
+ });
+
+ pfb.setHttpInvokerRequestExecutor(new AbstractHttpInvokerRequestExecutor() {
+ protected RemoteInvocationResult doExecuteRequest(
+ HttpInvokerClientConfiguration config, ByteArrayOutputStream baos) throws Exception {
+ assertEquals("http://myurl", config.getServiceUrl());
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ request.setContent(baos.toByteArray());
+ exporter.handleRequest(request, response);
+ return readRemoteInvocationResult(
+ new ByteArrayInputStream(response.getContentAsByteArray()), config.getCodebaseUrl());
+ }
+ });
+
+ pfb.afterPropertiesSet();
+ ITestBean proxy = (ITestBean) pfb.getObject();
+ assertEquals("myname", proxy.getName());
+ assertEquals(99, proxy.getAge());
+ }
+
+ public void testHttpInvokerProxyFactoryBeanAndServiceExporterWithCustomInvocationObject() throws Exception {
+ TestBean target = new TestBean("myname", 99);
+
+ final HttpInvokerServiceExporter exporter = new HttpInvokerServiceExporter();
+ exporter.setServiceInterface(ITestBean.class);
+ exporter.setService(target);
+ exporter.setRemoteInvocationExecutor(new DefaultRemoteInvocationExecutor() {
+ public Object invoke(RemoteInvocation invocation, Object targetObject)
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+ assertTrue(invocation instanceof TestRemoteInvocation);
+ assertNull(invocation.getAttributes());
+ assertNull(invocation.getAttribute("myKey"));
+ return super.invoke(invocation, targetObject);
+ }
+ });
+ exporter.afterPropertiesSet();
+
+ HttpInvokerProxyFactoryBean pfb = new HttpInvokerProxyFactoryBean();
+ pfb.setServiceInterface(ITestBean.class);
+ pfb.setServiceUrl("http://myurl");
+ pfb.setRemoteInvocationFactory(new RemoteInvocationFactory() {
+ public RemoteInvocation createRemoteInvocation(MethodInvocation methodInvocation) {
+ RemoteInvocation invocation = new TestRemoteInvocation(methodInvocation);
+ assertNull(invocation.getAttributes());
+ assertNull(invocation.getAttribute("myKey"));
+ return invocation;
+ }
+ });
+
+ pfb.setHttpInvokerRequestExecutor(new AbstractHttpInvokerRequestExecutor() {
+ protected RemoteInvocationResult doExecuteRequest(
+ HttpInvokerClientConfiguration config, ByteArrayOutputStream baos) throws Exception {
+ assertEquals("http://myurl", config.getServiceUrl());
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ request.setContent(baos.toByteArray());
+ exporter.handleRequest(request, response);
+ return readRemoteInvocationResult(
+ new ByteArrayInputStream(response.getContentAsByteArray()), config.getCodebaseUrl());
+ }
+ });
+
+ pfb.afterPropertiesSet();
+ ITestBean proxy = (ITestBean) pfb.getObject();
+ assertEquals("myname", proxy.getName());
+ assertEquals(99, proxy.getAge());
+ }
+
+ public void testHttpInvokerWithSpecialLocalMethods() throws Exception {
+ String serviceUrl = "http://myurl";
+ HttpInvokerProxyFactoryBean pfb = new HttpInvokerProxyFactoryBean();
+ pfb.setServiceInterface(ITestBean.class);
+ pfb.setServiceUrl(serviceUrl);
+
+ pfb.setHttpInvokerRequestExecutor(new HttpInvokerRequestExecutor() {
+ public RemoteInvocationResult executeRequest(
+ HttpInvokerClientConfiguration config, RemoteInvocation invocation) throws IOException {
+ throw new IOException("argh");
+ }
+ });
+
+ pfb.afterPropertiesSet();
+ ITestBean proxy = (ITestBean) pfb.getObject();
+
+ // shouldn't go through to remote service
+ assertTrue(proxy.toString().indexOf("HTTP invoker") != -1);
+ assertTrue(proxy.toString().indexOf(serviceUrl) != -1);
+ assertEquals(proxy.hashCode(), proxy.hashCode());
+ assertTrue(proxy.equals(proxy));
+
+ // should go through
+ try {
+ proxy.setAge(50);
+ fail("Should have thrown RemoteAccessException");
+ }
+ catch (RemoteAccessException ex) {
+ // expected
+ assertTrue(ex.getCause() instanceof IOException);
+ }
+ }
+
+
+ private static class TestRemoteInvocation extends RemoteInvocation {
+
+ public TestRemoteInvocation(MethodInvocation methodInvocation) {
+ super(methodInvocation);
+ }
+ }
+
+
+ private static class TestRemoteInvocationWrapper implements Serializable {
+
+ private final RemoteInvocation remoteInvocation;
+
+ public TestRemoteInvocationWrapper(RemoteInvocation remoteInvocation) {
+ this.remoteInvocation = remoteInvocation;
+ }
+ }
+
+
+ private static class TestRemoteInvocationResultWrapper implements Serializable {
+
+ private final RemoteInvocationResult remoteInvocationResult;
+
+ public TestRemoteInvocationResultWrapper(RemoteInvocationResult remoteInvocationResult) {
+ this.remoteInvocationResult = remoteInvocationResult;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/remoting/jaxrpc/JaxRpcSupportTests.java b/org.springframework.testsuite/src/test/java/org/springframework/remoting/jaxrpc/JaxRpcSupportTests.java
new file mode 100644
index 00000000000..8444157bf12
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/remoting/jaxrpc/JaxRpcSupportTests.java
@@ -0,0 +1,705 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.remoting.jaxrpc;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.xml.namespace.QName;
+import javax.xml.rpc.Call;
+import javax.xml.rpc.Service;
+import javax.xml.rpc.ServiceException;
+import javax.xml.rpc.ServiceFactory;
+import javax.xml.rpc.Stub;
+
+import junit.framework.TestCase;
+import org.easymock.ArgumentsMatcher;
+import org.easymock.MockControl;
+
+import org.springframework.remoting.RemoteAccessException;
+import org.springframework.remoting.RemoteLookupFailureException;
+import org.springframework.util.ObjectUtils;
+
+/**
+ * @author Juergen Hoeller
+ * @since 18.12.2003
+ */
+public class JaxRpcSupportTests extends TestCase {
+
+ public void testLocalJaxRpcServiceFactoryBeanWithServiceNameAndNamespace() throws Exception {
+ LocalJaxRpcServiceFactoryBean factory = new LocalJaxRpcServiceFactoryBean();
+ factory.setServiceFactoryClass(MockServiceFactory.class);
+ factory.setNamespaceUri("myNamespace");
+ factory.setServiceName("myService1");
+ factory.afterPropertiesSet();
+ assertEquals(MockServiceFactory.service1, factory.getObject());
+ }
+
+ public void testLocalJaxRpcServiceFactoryBeanWithServiceNameAndWsdl() throws Exception {
+ LocalJaxRpcServiceFactoryBean factory = new LocalJaxRpcServiceFactoryBean();
+ factory.setServiceFactoryClass(MockServiceFactory.class);
+ factory.setServiceName("myService2");
+ factory.setWsdlDocumentUrl(new URL("http://myUrl1"));
+ factory.afterPropertiesSet();
+ assertTrue("Correct singleton value", factory.isSingleton());
+ assertEquals(MockServiceFactory.service2, factory.getObject());
+ }
+
+ public void testLocalJaxRpcServiceFactoryBeanWithServiceNameAndWsdlAndProperties() throws Exception {
+ LocalJaxRpcServiceFactoryBean factory = new LocalJaxRpcServiceFactoryBean();
+ factory.setServiceFactoryClass(MockServiceFactory.class);
+ factory.setServiceName("myService2");
+ factory.setWsdlDocumentUrl(new URL("http://myUrl1"));
+ Properties props = new Properties();
+ props.setProperty("myKey", "myValue");
+ factory.setJaxRpcServiceProperties(props);
+ factory.afterPropertiesSet();
+ assertTrue("Correct singleton value", factory.isSingleton());
+ assertEquals(MockServiceFactory.service1, factory.getObject());
+ }
+
+ public void testLocalJaxRpcServiceFactoryBeanWithJaxRpcServiceInterface() throws Exception {
+ LocalJaxRpcServiceFactoryBean factory = new LocalJaxRpcServiceFactoryBean();
+ factory.setServiceFactoryClass(MockServiceFactory.class);
+ factory.setJaxRpcServiceInterface(IRemoteBean.class);
+ factory.afterPropertiesSet();
+ assertTrue("Correct singleton value", factory.isSingleton());
+ assertEquals(MockServiceFactory.service2, factory.getObject());
+ }
+
+ public void testLocalJaxRpcServiceFactoryBeanWithJaxRpcServiceInterfaceAndWsdl() throws Exception {
+ LocalJaxRpcServiceFactoryBean factory = new LocalJaxRpcServiceFactoryBean();
+ factory.setServiceFactoryClass(MockServiceFactory.class);
+ factory.setWsdlDocumentUrl(new URL("http://myUrl1"));
+ factory.setJaxRpcServiceInterface(IRemoteBean.class);
+ Properties props = new Properties();
+ props.setProperty("myKey", "myValue");
+ factory.setJaxRpcServiceProperties(props);
+ factory.afterPropertiesSet();
+ assertTrue("Correct singleton value", factory.isSingleton());
+ assertEquals(MockServiceFactory.service1, factory.getObject());
+ }
+
+ public void testJaxRpcPortProxyFactoryBean() throws Exception {
+ JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
+ factory.setServiceFactoryClass(MockServiceFactory.class);
+ factory.setNamespaceUri("myNamespace");
+ factory.setServiceName("myService1");
+ factory.setPortName("myPort");
+ factory.setPortInterface(IRemoteBean.class);
+ factory.afterPropertiesSet();
+ assertTrue("Correct singleton value", factory.isSingleton());
+ assertTrue(factory.getPortStub() instanceof Stub);
+
+ assertTrue(factory.getObject() instanceof IRemoteBean);
+ IRemoteBean proxy = (IRemoteBean) factory.getObject();
+ proxy.setName("myName");
+ assertEquals("myName", RemoteBean.name);
+ MockServiceFactory.service1Control.verify();
+ }
+
+ public void testJaxRpcPortProxyFactoryBeanWithProperties() throws Exception {
+ JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
+ factory.setServiceFactoryClass(MockServiceFactory.class);
+ factory.setNamespaceUri("myNamespace");
+ factory.setServiceName("myService1");
+ factory.setPortName("myPort");
+ factory.setUsername("user");
+ factory.setPassword("pw");
+ factory.setEndpointAddress("ea");
+ factory.setMaintainSession(true);
+ factory.setPortInterface(IRemoteBean.class);
+ factory.afterPropertiesSet();
+ assertTrue("Correct singleton value", factory.isSingleton());
+
+ assertTrue(factory.getPortStub() instanceof Stub);
+ Stub stub = (Stub) factory.getPortStub();
+ assertEquals("user", stub._getProperty(Stub.USERNAME_PROPERTY));
+ assertEquals("pw", stub._getProperty(Stub.PASSWORD_PROPERTY));
+ assertEquals("ea", stub._getProperty(Stub.ENDPOINT_ADDRESS_PROPERTY));
+ assertTrue(((Boolean) stub._getProperty(Stub.SESSION_MAINTAIN_PROPERTY)).booleanValue());
+
+ assertTrue(factory.getObject() instanceof IRemoteBean);
+ IRemoteBean proxy = (IRemoteBean) factory.getObject();
+ proxy.setName("myName");
+ assertEquals("myName", RemoteBean.name);
+ MockServiceFactory.service1Control.verify();
+ }
+
+ public void testJaxRpcPortProxyFactoryBeanWithCustomProperties() throws Exception {
+ JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
+ factory.setServiceFactoryClass(MockServiceFactory.class);
+ factory.setNamespaceUri("myNamespace");
+ factory.setServiceName("myService1");
+ factory.setPortName("myPort");
+ factory.setUsername("user");
+ factory.setPassword("pw");
+ Properties customProps = new Properties();
+ customProps.setProperty("myProp", "myValue");
+ factory.setCustomProperties(customProps);
+ factory.setPortInterface(IRemoteBean.class);
+ factory.afterPropertiesSet();
+ assertTrue("Correct singleton value", factory.isSingleton());
+
+ assertTrue(factory.getPortStub() instanceof Stub);
+ Stub stub = (Stub) factory.getPortStub();
+ assertEquals("user", stub._getProperty(Stub.USERNAME_PROPERTY));
+ assertEquals("pw", stub._getProperty(Stub.PASSWORD_PROPERTY));
+ assertEquals("myValue", stub._getProperty("myProp"));
+
+ assertTrue(factory.getObject() instanceof IRemoteBean);
+ IRemoteBean proxy = (IRemoteBean) factory.getObject();
+ proxy.setName("myName");
+ assertEquals("myName", RemoteBean.name);
+ MockServiceFactory.service1Control.verify();
+ }
+
+ public void testJaxRpcPortProxyFactoryBeanWithCustomPropertyMap() throws Exception {
+ JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
+ factory.setServiceFactoryClass(MockServiceFactory.class);
+ factory.setNamespaceUri("myNamespace");
+ factory.setServiceName("myService1");
+ factory.setPortName("myPort");
+ factory.setEndpointAddress("ea");
+ factory.setMaintainSession(true);
+ Map customProps = new HashMap();
+ customProps.put("myProp", new Integer(1));
+ factory.setCustomPropertyMap(customProps);
+ factory.addCustomProperty("myOtherProp", "myOtherValue");
+ factory.setPortInterface(IRemoteBean.class);
+ factory.afterPropertiesSet();
+ assertTrue("Correct singleton value", factory.isSingleton());
+
+ assertTrue(factory.getPortStub() instanceof Stub);
+ Stub stub = (Stub) factory.getPortStub();
+ assertEquals("ea", stub._getProperty(Stub.ENDPOINT_ADDRESS_PROPERTY));
+ assertTrue(((Boolean) stub._getProperty(Stub.SESSION_MAINTAIN_PROPERTY)).booleanValue());
+ assertEquals(new Integer(1), stub._getProperty("myProp"));
+ assertEquals("myOtherValue", stub._getProperty("myOtherProp"));
+
+ assertTrue(factory.getObject() instanceof IRemoteBean);
+ IRemoteBean proxy = (IRemoteBean) factory.getObject();
+ proxy.setName("myName");
+ assertEquals("myName", RemoteBean.name);
+ MockServiceFactory.service1Control.verify();
+ }
+
+ public void testJaxRpcPortProxyFactoryBeanWithDynamicCalls() throws Exception {
+ JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
+ factory.setServiceFactoryClass(CallMockServiceFactory.class);
+ factory.setNamespaceUri("myNamespace");
+ factory.setServiceName("myService1");
+ factory.setPortName("myPort");
+ factory.setServiceInterface(IBusinessBean.class);
+ factory.afterPropertiesSet();
+ assertNull(factory.getPortStub());
+
+ assertTrue(factory.getObject() instanceof IBusinessBean);
+ IBusinessBean proxy = (IBusinessBean) factory.getObject();
+ proxy.setName("myName");
+ MockServiceFactory.service1Control.verify();
+ CallMockServiceFactory.call1Control.verify();
+ }
+
+ public void testJaxRpcPortProxyFactoryBeanWithDynamicCallsAndProperties() throws Exception {
+ JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
+ factory.setServiceFactoryClass(CallWithPropertiesMockServiceFactory.class);
+ factory.setNamespaceUri("myNamespace");
+ factory.setServiceName("myService1");
+ factory.setPortName("myPort");
+ factory.setUsername("user");
+ factory.setPassword("pw");
+ factory.setEndpointAddress("ea");
+ factory.setMaintainSession(true);
+ factory.setServiceInterface(IBusinessBean.class);
+ factory.afterPropertiesSet();
+ assertNull(factory.getPortStub());
+
+ assertTrue(factory.getObject() instanceof IBusinessBean);
+ IBusinessBean proxy = (IBusinessBean) factory.getObject();
+ proxy.setName("myName");
+ MockServiceFactory.service1Control.verify();
+ CallMockServiceFactory.call1Control.verify();
+ }
+
+ public void testJaxRpcPortProxyFactoryBeanWithDynamicCallsAndServiceException() throws Exception {
+ JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
+ factory.setServiceFactoryClass(CallMockServiceFactory.class);
+ factory.setNamespaceUri("myNamespace");
+ factory.setServiceName("myServiceX");
+ factory.setPortName("myPort");
+ factory.setServiceInterface(IRemoteBean.class);
+ try {
+ factory.afterPropertiesSet();
+ fail("Should have thrown RemoteLookupFailureException");
+ }
+ catch (RemoteLookupFailureException ex) {
+ // expected
+ }
+ }
+
+ public void testJaxRpcPortProxyFactoryBeanWithDynamicCallsAndLazyLookupAndServiceException() throws Exception {
+ JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
+ factory.setServiceFactoryClass(CallMockServiceFactory.class);
+ factory.setNamespaceUri("myNamespace");
+ factory.setServiceName("myServiceX");
+ factory.setPortName("myPort");
+ factory.setServiceInterface(IRemoteBean.class);
+ factory.setLookupServiceOnStartup(false);
+ factory.afterPropertiesSet();
+
+ assertTrue(factory.getObject() instanceof IRemoteBean);
+ IRemoteBean proxy = (IRemoteBean) factory.getObject();
+ try {
+ proxy.setName("exception");
+ fail("Should have thrown RemoteException");
+ }
+ catch (RemoteLookupFailureException ex) {
+ // expected
+ assertTrue(ex.getCause() instanceof ServiceException);
+ }
+ }
+
+ public void testJaxRpcPortProxyFactoryBeanWithDynamicCallsAndRemoteException() throws Exception {
+ ExceptionCallMockServiceFactory serviceFactory = new ExceptionCallMockServiceFactory();
+
+ JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
+ factory.setServiceFactory(serviceFactory);
+ factory.setNamespaceUri("myNamespace");
+ factory.setServiceName("myService1");
+ factory.setPortName("myPort");
+ factory.setServiceInterface(IRemoteBean.class);
+ factory.afterPropertiesSet();
+
+ assertTrue(factory.getObject() instanceof IRemoteBean);
+ IRemoteBean proxy = (IRemoteBean) factory.getObject();
+
+ try {
+ proxy.setName("exception");
+ fail("Should have thrown RemoteException");
+ }
+ catch (RemoteException ex) {
+ // expected
+ }
+
+ proxy.setName("myName");
+ assertEquals("myName", RemoteBean.name);
+ proxy.setName("myName");
+ assertEquals("myName", RemoteBean.name);
+
+ assertEquals(1, serviceFactory.serviceCount);
+ MockServiceFactory.service1Control.verify();
+ CallMockServiceFactory.call1Control.verify();
+ ExceptionCallMockServiceFactory.call2Control.verify();
+ }
+
+ public void testJaxRpcPortProxyFactoryBeanWithDynamicCallsAndRemoteExceptionAndRefresh() throws Exception {
+ ExceptionCallMockServiceFactory serviceFactory = new ExceptionCallMockServiceFactory();
+
+ JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
+ factory.setServiceFactory(serviceFactory);
+ factory.setNamespaceUri("myNamespace");
+ factory.setServiceName("myService1");
+ factory.setPortName("myPort");
+ factory.setServiceInterface(IRemoteBean.class);
+ factory.setRefreshServiceAfterConnectFailure(true);
+ factory.afterPropertiesSet();
+
+ assertTrue(factory.getObject() instanceof IRemoteBean);
+ IRemoteBean proxy = (IRemoteBean) factory.getObject();
+
+ try {
+ proxy.setName("exception");
+ fail("Should have thrown RemoteException");
+ }
+ catch (RemoteException ex) {
+ // expected
+ }
+
+ proxy.setName("myName");
+ assertEquals("myName", RemoteBean.name);
+ proxy.setName("myName");
+ assertEquals("myName", RemoteBean.name);
+
+ assertEquals(2, serviceFactory.serviceCount);
+ MockServiceFactory.service1Control.verify();
+ CallMockServiceFactory.call1Control.verify();
+ ExceptionCallMockServiceFactory.call2Control.verify();
+ }
+
+ public void testJaxRpcPortProxyFactoryBeanWithPortInterface() throws Exception {
+ JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
+ factory.setServiceFactoryClass(MockServiceFactory.class);
+ factory.setNamespaceUri("myNamespace");
+ factory.setServiceName("myService1");
+ factory.setPortName("myPort");
+ factory.setPortInterface(IRemoteBean.class);
+ factory.setServiceInterface(IBusinessBean.class);
+ factory.afterPropertiesSet();
+ assertTrue(factory.getObject() instanceof IBusinessBean);
+ assertFalse(factory.getObject() instanceof IRemoteBean);
+ IBusinessBean proxy = (IBusinessBean) factory.getObject();
+ proxy.setName("myName");
+ assertEquals("myName", RemoteBean.name);
+ MockServiceFactory.service1Control.verify();
+ }
+
+ public void testJaxRpcPortProxyFactoryBeanWithPortInterfaceAndServiceException() throws Exception {
+ JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
+ factory.setServiceFactoryClass(MockServiceFactory.class);
+ factory.setNamespaceUri("myNamespace");
+ factory.setServiceName("myServiceX");
+ factory.setPortInterface(IRemoteBean.class);
+ factory.setPortName("myPort");
+ factory.setServiceInterface(IRemoteBean.class);
+ try {
+ factory.afterPropertiesSet();
+ fail("Should have thrown RemoteLookupFailureException");
+ }
+ catch (RemoteLookupFailureException ex) {
+ // expected
+ }
+ }
+
+ public void testJaxRpcPortProxyFactoryBeanWithPortInterfaceAndLazyLookupAndServiceException() throws Exception {
+ JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
+ factory.setServiceFactoryClass(MockServiceFactory.class);
+ factory.setNamespaceUri("myNamespace");
+ factory.setServiceName("myServiceX");
+ factory.setPortName("myPort");
+ factory.setPortInterface(IRemoteBean.class);
+ factory.setServiceInterface(IRemoteBean.class);
+ factory.setLookupServiceOnStartup(false);
+ factory.afterPropertiesSet();
+
+ assertTrue(factory.getObject() instanceof IRemoteBean);
+ IRemoteBean proxy = (IRemoteBean) factory.getObject();
+ try {
+ proxy.setName("exception");
+ fail("Should have thrown Service");
+ }
+ catch (RemoteLookupFailureException ex) {
+ // expected
+ assertTrue(ex.getCause() instanceof ServiceException);
+ }
+ }
+
+ public void testJaxRpcPortProxyFactoryBeanWithPortInterfaceAndRemoteException() throws Exception {
+ MockServiceFactory serviceFactory = new MockServiceFactory();
+
+ JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
+ factory.setServiceFactory(serviceFactory);
+ factory.setNamespaceUri("myNamespace");
+ factory.setServiceName("myService1");
+ factory.setPortName("myPort");
+ factory.setPortInterface(IRemoteBean.class);
+ factory.setServiceInterface(IBusinessBean.class);
+ factory.afterPropertiesSet();
+
+ assertTrue(factory.getObject() instanceof IBusinessBean);
+ assertFalse(factory.getObject() instanceof IRemoteBean);
+ IBusinessBean proxy = (IBusinessBean) factory.getObject();
+
+ try {
+ proxy.setName("exception");
+ fail("Should have thrown RemoteAccessException");
+ }
+ catch (RemoteAccessException ex) {
+ // expected
+ }
+
+ proxy.setName("myName");
+ assertEquals("myName", RemoteBean.name);
+ proxy.setName("myName");
+ assertEquals("myName", RemoteBean.name);
+
+ assertEquals(1, serviceFactory.serviceCount);
+ MockServiceFactory.service1Control.verify();
+ }
+
+ public void testJaxRpcPortProxyFactoryBeanWithPortInterfaceAndRemoteExceptionAndRefresh() throws Exception {
+ ExceptionMockServiceFactory serviceFactory = new ExceptionMockServiceFactory();
+
+ JaxRpcPortProxyFactoryBean factory = new JaxRpcPortProxyFactoryBean();
+ factory.setServiceFactory(serviceFactory);
+ factory.setNamespaceUri("myNamespace");
+ factory.setServiceName("myService1");
+ factory.setPortName("myPort");
+ factory.setPortInterface(IRemoteBean.class);
+ factory.setServiceInterface(IBusinessBean.class);
+ factory.setRefreshServiceAfterConnectFailure(true);
+ factory.afterPropertiesSet();
+
+ assertTrue(factory.getObject() instanceof IBusinessBean);
+ assertFalse(factory.getObject() instanceof IRemoteBean);
+ IBusinessBean proxy = (IBusinessBean) factory.getObject();
+
+ try {
+ proxy.setName("exception");
+ fail("Should have thrown RemoteAccessException");
+ }
+ catch (RemoteAccessException ex) {
+ // expected
+ }
+
+ proxy.setName("myName");
+ assertEquals("myName", RemoteBean.name);
+ proxy.setName("myName");
+ assertEquals("myName", RemoteBean.name);
+
+ assertEquals(2, serviceFactory.serviceCount);
+ MockServiceFactory.service1Control.verify();
+ }
+
+
+ public static class MockServiceFactory extends ServiceFactory {
+
+ protected static MockControl service1Control;
+ protected static Service service1;
+ protected static MockControl service2Control;
+ protected static Service service2;
+ protected int serviceCount = 0;
+
+ public MockServiceFactory() throws Exception {
+ service1Control = MockControl.createControl(Service.class);
+ service1 = (Service) service1Control.getMock();
+ service2Control = MockControl.createControl(Service.class);
+ service2 = (Service) service2Control.getMock();
+ initMocks();
+ service1Control.replay();
+ }
+
+ protected void initMocks() throws Exception {
+ service1.getPort(new QName("myNamespace", "myPort"), IRemoteBean.class);
+ service1Control.setReturnValue(new RemoteBean());
+ }
+
+ public Service createService(QName qName) throws ServiceException {
+ if (!"myNamespace".equals(qName.getNamespaceURI()) || !"myService1".equals(qName.getLocalPart())) {
+ throw new ServiceException("not supported");
+ }
+ serviceCount++;
+ return service1;
+ }
+
+ public Service createService(URL url, QName qName) throws ServiceException {
+ try {
+ if (!(new URL("http://myUrl1")).equals(url) || !"".equals(qName.getNamespaceURI()) ||
+ !"myService2".equals(qName.getLocalPart())) {
+ throw new ServiceException("not supported");
+ }
+ }
+ catch (MalformedURLException ex) {
+ }
+ serviceCount++;
+ return service2;
+ }
+
+ public Service loadService(URL url, QName qName, Properties props) throws ServiceException {
+ try {
+ if (!(new URL("http://myUrl1")).equals(url) || !"".equals(qName.getNamespaceURI()) ||
+ !"myService2".equals(qName.getLocalPart())) {
+ throw new ServiceException("not supported");
+ }
+ }
+ catch (MalformedURLException ex) {
+ }
+ if (props == null || !"myValue".equals(props.getProperty("myKey"))) {
+ throw new ServiceException("invalid properties");
+ }
+ serviceCount++;
+ return service1;
+ }
+
+ public Service loadService(Class ifc) throws ServiceException {
+ if (!IRemoteBean.class.equals(ifc)) {
+ throw new ServiceException("not supported");
+ }
+ serviceCount++;
+ return service2;
+ }
+
+ public Service loadService(URL url, Class ifc, Properties props) throws ServiceException {
+ try {
+ if (!(new URL("http://myUrl1")).equals(url) || !IRemoteBean.class.equals(ifc)) {
+ throw new ServiceException("not supported");
+ }
+ }
+ catch (MalformedURLException ex) {
+ }
+ if (props == null || !"myValue".equals(props.getProperty("myKey"))) {
+ throw new ServiceException("invalid properties");
+ }
+ serviceCount++;
+ return service1;
+ }
+ }
+
+
+ public static class ExceptionMockServiceFactory extends MockServiceFactory {
+
+ public ExceptionMockServiceFactory() throws Exception {
+ super();
+ }
+
+ protected void initMocks() throws Exception {
+ super.initMocks();
+ service1.getPort(new QName("myNamespace", "myPort"), IRemoteBean.class);
+ service1Control.setReturnValue(new RemoteBean());
+ }
+ }
+
+
+ public static class CallMockServiceFactory extends MockServiceFactory {
+
+ protected static MockControl call1Control;
+ protected static Call call1;
+
+ public CallMockServiceFactory() throws Exception {
+ super();
+ }
+
+ protected void initMocks() throws Exception {
+ initStandardCall(1);
+ }
+
+ protected void initStandardCall(int count) throws Exception {
+ call1Control = MockControl.createControl(Call.class);
+ call1 = (Call) call1Control.getMock();
+ service1.createCall(new QName("myNamespace", "myPort"), "setName");
+ service1Control.setReturnValue(call1, count);
+ call1.invoke(new Object[] {"myName"});
+ call1Control.setMatcher(new ArgumentsMatcher() {
+ public boolean matches(Object[] objects, Object[] objects1) {
+ return Arrays.equals((Object[]) objects[0], (Object[]) objects1[0]);
+ }
+ public String toString(Object[] objects) {
+ return ObjectUtils.nullSafeToString(objects[0]);
+ }
+ });
+ call1Control.setReturnValue(null, count);
+ extendStandardCall();
+ call1Control.replay();
+ }
+
+ protected void extendStandardCall() {
+ }
+ }
+
+
+ public static class ExceptionCallMockServiceFactory extends CallMockServiceFactory {
+
+ protected static MockControl call2Control;
+ protected static Call call2;
+
+ public ExceptionCallMockServiceFactory() throws Exception {
+ }
+
+ protected void initMocks() throws Exception {
+ initExceptionCall();
+ initStandardCall(2);
+ }
+
+ protected void initExceptionCall() throws Exception {
+ call2Control = MockControl.createControl(Call.class);
+ call2 = (Call) call2Control.getMock();
+ service1.createCall(new QName("myNamespace", "myPort"), "setName");
+ service1Control.setReturnValue(call2);
+ call2.invoke(new Object[] {"exception"});
+ call2Control.setMatcher(new ArgumentsMatcher() {
+ public boolean matches(Object[] objects, Object[] objects1) {
+ return Arrays.equals((Object[]) objects[0], (Object[]) objects1[0]);
+ }
+ public String toString(Object[] objects) {
+ return ObjectUtils.nullSafeToString(objects[0]);
+ }
+ });
+ call2Control.setThrowable(new RemoteException());
+ call2Control.replay();
+ }
+ }
+
+
+ public static class CallWithPropertiesMockServiceFactory extends CallMockServiceFactory {
+
+ public CallWithPropertiesMockServiceFactory() throws Exception {
+ }
+
+ protected void extendStandardCall() {
+ call1.setProperty(Call.USERNAME_PROPERTY, "user");
+ call1Control.setVoidCallable();
+ call1.setProperty(Call.PASSWORD_PROPERTY, "pw");
+ call1Control.setVoidCallable();
+ call1.setTargetEndpointAddress("ea");
+ call1Control.setVoidCallable();
+ call1.setProperty(Call.SESSION_MAINTAIN_PROPERTY, Boolean.TRUE);
+ call1Control.setVoidCallable();
+ }
+ }
+
+
+ public static interface IBusinessBean {
+
+ public void setName(String name);
+
+ }
+
+
+ public static interface IRemoteBean extends Remote {
+
+ public void setName(String name) throws RemoteException;
+
+ }
+
+
+ public static class RemoteBean implements IRemoteBean, Stub {
+
+ private static String name;
+ private static Map properties;
+
+ public RemoteBean() {
+ properties = new HashMap();
+ }
+
+ public void setName(String nam) throws RemoteException {
+ if ("exception".equals(nam)) {
+ throw new RemoteException();
+ }
+ name = nam;
+ }
+
+ public void _setProperty(String key, Object o) {
+ properties.put(key, o);
+ }
+
+ public Object _getProperty(String key) {
+ return properties.get(key);
+ }
+
+ public Iterator _getPropertyNames() {
+ return properties.keySet().iterator();
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/remoting/rmi/RmiSupportTests.java b/org.springframework.testsuite/src/test/java/org/springframework/remoting/rmi/RmiSupportTests.java
new file mode 100644
index 00000000000..2f2b1e81559
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/remoting/rmi/RmiSupportTests.java
@@ -0,0 +1,452 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.remoting.rmi;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.rmi.ConnectException;
+import java.rmi.ConnectIOException;
+import java.rmi.MarshalException;
+import java.rmi.NoSuchObjectException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.StubNotFoundException;
+import java.rmi.UnknownHostException;
+import java.rmi.UnmarshalException;
+
+import junit.framework.TestCase;
+import org.aopalliance.intercept.MethodInvocation;
+
+import org.springframework.remoting.RemoteAccessException;
+import org.springframework.remoting.RemoteConnectFailureException;
+import org.springframework.remoting.RemoteProxyFailureException;
+import org.springframework.remoting.support.RemoteInvocation;
+
+/**
+ * @author Juergen Hoeller
+ * @since 16.05.2003
+ */
+public class RmiSupportTests extends TestCase {
+
+ public void testRmiProxyFactoryBean() throws Exception {
+ CountingRmiProxyFactoryBean factory = new CountingRmiProxyFactoryBean();
+ factory.setServiceInterface(IRemoteBean.class);
+ factory.setServiceUrl("rmi://localhost:1090/test");
+ factory.afterPropertiesSet();
+ assertTrue("Correct singleton value", factory.isSingleton());
+ assertTrue(factory.getObject() instanceof IRemoteBean);
+ IRemoteBean proxy = (IRemoteBean) factory.getObject();
+ proxy.setName("myName");
+ assertEquals(RemoteBean.name, "myName");
+ assertEquals(1, factory.counter);
+ }
+
+ public void testRmiProxyFactoryBeanWithRemoteException() throws Exception {
+ doTestRmiProxyFactoryBeanWithException(RemoteException.class);
+ }
+
+ public void testRmiProxyFactoryBeanWithConnectException() throws Exception {
+ doTestRmiProxyFactoryBeanWithException(ConnectException.class);
+ }
+
+ public void testRmiProxyFactoryBeanWithConnectIOException() throws Exception {
+ doTestRmiProxyFactoryBeanWithException(ConnectIOException.class);
+ }
+
+ public void testRmiProxyFactoryBeanWithUnknownHostException() throws Exception {
+ doTestRmiProxyFactoryBeanWithException(UnknownHostException.class);
+ }
+
+ public void testRmiProxyFactoryBeanWithNoSuchObjectException() throws Exception {
+ doTestRmiProxyFactoryBeanWithException(NoSuchObjectException.class);
+ }
+
+ public void testRmiProxyFactoryBeanWithStubNotFoundException() throws Exception {
+ doTestRmiProxyFactoryBeanWithException(StubNotFoundException.class);
+ }
+
+ public void testRmiProxyFactoryBeanWithMarshalException() throws Exception {
+ doTestRmiProxyFactoryBeanWithException(MarshalException.class);
+ }
+
+ public void testRmiProxyFactoryBeanWithUnmarshalException() throws Exception {
+ doTestRmiProxyFactoryBeanWithException(UnmarshalException.class);
+ }
+
+ private void doTestRmiProxyFactoryBeanWithException(Class exceptionClass) throws Exception {
+ CountingRmiProxyFactoryBean factory = new CountingRmiProxyFactoryBean();
+ factory.setServiceInterface(IRemoteBean.class);
+ factory.setServiceUrl("rmi://localhost:1090/test");
+ factory.afterPropertiesSet();
+ assertTrue(factory.getObject() instanceof IRemoteBean);
+ IRemoteBean proxy = (IRemoteBean) factory.getObject();
+ try {
+ proxy.setName(exceptionClass.getName());
+ fail("Should have thrown " + exceptionClass.getName());
+ }
+ catch (Exception ex) {
+ if (exceptionClass.isInstance(ex)) {
+ // expected
+ }
+ else {
+ throw ex;
+ }
+ }
+ assertEquals(1, factory.counter);
+ }
+
+ public void testRmiProxyFactoryBeanWithConnectExceptionAndRefresh() throws Exception {
+ doTestRmiProxyFactoryBeanWithExceptionAndRefresh(ConnectException.class);
+ }
+
+ public void testRmiProxyFactoryBeanWithConnectIOExceptionAndRefresh() throws Exception {
+ doTestRmiProxyFactoryBeanWithExceptionAndRefresh(ConnectIOException.class);
+ }
+
+ public void testRmiProxyFactoryBeanWithUnknownHostExceptionAndRefresh() throws Exception {
+ doTestRmiProxyFactoryBeanWithExceptionAndRefresh(UnknownHostException.class);
+ }
+
+ public void testRmiProxyFactoryBeanWithNoSuchObjectExceptionAndRefresh() throws Exception {
+ doTestRmiProxyFactoryBeanWithExceptionAndRefresh(NoSuchObjectException.class);
+ }
+
+ public void testRmiProxyFactoryBeanWithStubNotFoundExceptionAndRefresh() throws Exception {
+ doTestRmiProxyFactoryBeanWithExceptionAndRefresh(StubNotFoundException.class);
+ }
+
+ private void doTestRmiProxyFactoryBeanWithExceptionAndRefresh(Class exceptionClass) throws Exception {
+ CountingRmiProxyFactoryBean factory = new CountingRmiProxyFactoryBean();
+ factory.setServiceInterface(IRemoteBean.class);
+ factory.setServiceUrl("rmi://localhost:1090/test");
+ factory.setRefreshStubOnConnectFailure(true);
+ factory.afterPropertiesSet();
+ assertTrue(factory.getObject() instanceof IRemoteBean);
+ IRemoteBean proxy = (IRemoteBean) factory.getObject();
+ try {
+ proxy.setName(exceptionClass.getName());
+ fail("Should have thrown " + exceptionClass.getName());
+ }
+ catch (Exception ex) {
+ if (exceptionClass.isInstance(ex)) {
+ // expected
+ }
+ else {
+ throw ex;
+ }
+ }
+ assertEquals(2, factory.counter);
+ }
+
+ public void testRmiProxyFactoryBeanWithBusinessInterface() throws Exception {
+ CountingRmiProxyFactoryBean factory = new CountingRmiProxyFactoryBean();
+ factory.setServiceInterface(IBusinessBean.class);
+ factory.setServiceUrl("rmi://localhost:1090/test");
+ factory.afterPropertiesSet();
+ assertTrue(factory.getObject() instanceof IBusinessBean);
+ IBusinessBean proxy = (IBusinessBean) factory.getObject();
+ assertFalse(proxy instanceof IRemoteBean);
+ proxy.setName("myName");
+ assertEquals(RemoteBean.name, "myName");
+ assertEquals(1, factory.counter);
+ }
+
+ public void testRmiProxyFactoryBeanWithWrongBusinessInterface() throws Exception {
+ CountingRmiProxyFactoryBean factory = new CountingRmiProxyFactoryBean();
+ factory.setServiceInterface(IWrongBusinessBean.class);
+ factory.setServiceUrl("rmi://localhost:1090/test");
+ factory.afterPropertiesSet();
+ assertTrue(factory.getObject() instanceof IWrongBusinessBean);
+ IWrongBusinessBean proxy = (IWrongBusinessBean) factory.getObject();
+ assertFalse(proxy instanceof IRemoteBean);
+ try {
+ proxy.setOtherName("name");
+ fail("Should have thrown RemoteProxyFailureException");
+ }
+ catch (RemoteProxyFailureException ex) {
+ assertTrue(ex.getCause() instanceof NoSuchMethodException);
+ assertTrue(ex.getMessage().indexOf("setOtherName") != -1);
+ assertTrue(ex.getMessage().indexOf("IWrongBusinessBean") != -1);
+ }
+ assertEquals(1, factory.counter);
+ }
+
+ public void testRmiProxyFactoryBeanWithBusinessInterfaceAndRemoteException() throws Exception {
+ doTestRmiProxyFactoryBeanWithBusinessInterfaceAndException(
+ RemoteException.class, RemoteAccessException.class);
+ }
+
+ public void testRmiProxyFactoryBeanWithBusinessInterfaceAndConnectException() throws Exception {
+ doTestRmiProxyFactoryBeanWithBusinessInterfaceAndException(
+ ConnectException.class, RemoteConnectFailureException.class);
+ }
+
+ public void testRmiProxyFactoryBeanWithBusinessInterfaceAndConnectIOException() throws Exception {
+ doTestRmiProxyFactoryBeanWithBusinessInterfaceAndException(
+ ConnectIOException.class, RemoteConnectFailureException.class);
+ }
+
+ public void testRmiProxyFactoryBeanWithBusinessInterfaceAndUnknownHostException() throws Exception {
+ doTestRmiProxyFactoryBeanWithBusinessInterfaceAndException(
+ UnknownHostException.class, RemoteConnectFailureException.class);
+ }
+
+ public void testRmiProxyFactoryBeanWithBusinessInterfaceAndNoSuchObjectExceptionException() throws Exception {
+ doTestRmiProxyFactoryBeanWithBusinessInterfaceAndException(
+ NoSuchObjectException.class, RemoteConnectFailureException.class);
+ }
+
+ public void testRmiProxyFactoryBeanWithBusinessInterfaceAndStubNotFoundException() throws Exception {
+ doTestRmiProxyFactoryBeanWithBusinessInterfaceAndException(
+ StubNotFoundException.class, RemoteConnectFailureException.class);
+ }
+
+ private void doTestRmiProxyFactoryBeanWithBusinessInterfaceAndException(
+ Class rmiExceptionClass, Class springExceptionClass) throws Exception {
+
+ CountingRmiProxyFactoryBean factory = new CountingRmiProxyFactoryBean();
+ factory.setServiceInterface(IBusinessBean.class);
+ factory.setServiceUrl("rmi://localhost:1090/test");
+ factory.afterPropertiesSet();
+ assertTrue(factory.getObject() instanceof IBusinessBean);
+ IBusinessBean proxy = (IBusinessBean) factory.getObject();
+ assertFalse(proxy instanceof IRemoteBean);
+ try {
+ proxy.setName(rmiExceptionClass.getName());
+ fail("Should have thrown " + rmiExceptionClass.getName());
+ }
+ catch (Exception ex) {
+ if (springExceptionClass.isInstance(ex)) {
+ // expected
+ }
+ else {
+ throw ex;
+ }
+ }
+ assertEquals(1, factory.counter);
+ }
+
+ public void testRmiProxyFactoryBeanWithBusinessInterfaceAndRemoteExceptionAndRefresh() throws Exception {
+ doTestRmiProxyFactoryBeanWithBusinessInterfaceAndExceptionAndRefresh(
+ RemoteException.class, RemoteAccessException.class);
+ }
+
+ public void testRmiProxyFactoryBeanWithBusinessInterfaceAndConnectExceptionAndRefresh() throws Exception {
+ doTestRmiProxyFactoryBeanWithBusinessInterfaceAndExceptionAndRefresh(
+ ConnectException.class, RemoteConnectFailureException.class);
+ }
+
+ public void testRmiProxyFactoryBeanWithBusinessInterfaceAndConnectIOExceptionAndRefresh() throws Exception {
+ doTestRmiProxyFactoryBeanWithBusinessInterfaceAndExceptionAndRefresh(
+ ConnectIOException.class, RemoteConnectFailureException.class);
+ }
+
+ public void testRmiProxyFactoryBeanWithBusinessInterfaceAndUnknownHostExceptionAndRefresh() throws Exception {
+ doTestRmiProxyFactoryBeanWithBusinessInterfaceAndExceptionAndRefresh(
+ UnknownHostException.class, RemoteConnectFailureException.class);
+ }
+
+ public void testRmiProxyFactoryBeanWithBusinessInterfaceAndNoSuchObjectExceptionAndRefresh() throws Exception {
+ doTestRmiProxyFactoryBeanWithBusinessInterfaceAndExceptionAndRefresh(
+ NoSuchObjectException.class, RemoteConnectFailureException.class);
+ }
+
+ public void testRmiProxyFactoryBeanWithBusinessInterfaceAndStubNotFoundExceptionAndRefresh() throws Exception {
+ doTestRmiProxyFactoryBeanWithBusinessInterfaceAndExceptionAndRefresh(
+ StubNotFoundException.class, RemoteConnectFailureException.class);
+ }
+
+ private void doTestRmiProxyFactoryBeanWithBusinessInterfaceAndExceptionAndRefresh(
+ Class rmiExceptionClass, Class springExceptionClass) throws Exception {
+
+ CountingRmiProxyFactoryBean factory = new CountingRmiProxyFactoryBean();
+ factory.setServiceInterface(IBusinessBean.class);
+ factory.setServiceUrl("rmi://localhost:1090/test");
+ factory.setRefreshStubOnConnectFailure(true);
+ factory.afterPropertiesSet();
+ assertTrue(factory.getObject() instanceof IBusinessBean);
+ IBusinessBean proxy = (IBusinessBean) factory.getObject();
+ assertFalse(proxy instanceof IRemoteBean);
+ try {
+ proxy.setName(rmiExceptionClass.getName());
+ fail("Should have thrown " + rmiExceptionClass.getName());
+ }
+ catch (Exception ex) {
+ if (springExceptionClass.isInstance(ex)) {
+ // expected
+ }
+ else {
+ throw ex;
+ }
+ }
+ if (RemoteConnectFailureException.class.isAssignableFrom(springExceptionClass)) {
+ assertEquals(2, factory.counter);
+ }
+ else {
+ assertEquals(1, factory.counter);
+ }
+ }
+
+ public void testRmiClientInterceptorRequiresUrl() throws Exception{
+ RmiClientInterceptor client = new RmiClientInterceptor();
+ client.setServiceInterface(IRemoteBean.class);
+
+ try {
+ client.afterPropertiesSet();
+ fail("url isn't set, expected IllegalArgumentException");
+ }
+ catch(IllegalArgumentException e){
+ // expected
+ }
+ }
+
+ public void testRemoteInvocation() throws NoSuchMethodException {
+ // let's see if the remote invocation object works
+
+ final RemoteBean rb = new RemoteBean();
+ final Method setNameMethod = rb.getClass().getDeclaredMethod("setName", new Class[] {String.class});
+
+ MethodInvocation mi = new MethodInvocation() {
+ public Method getMethod() {
+ return setNameMethod;
+ }
+ public Object[] getArguments() {
+ return new Object[] {"bla"};
+ }
+ public Object proceed() throws Throwable {
+ throw new UnsupportedOperationException();
+ }
+ public Object getThis() {
+ return rb;
+ }
+ public AccessibleObject getStaticPart() {
+ return setNameMethod;
+ }
+ };
+
+ RemoteInvocation inv = new RemoteInvocation(mi);
+
+ assertEquals("setName", inv.getMethodName());
+ assertEquals("bla", inv.getArguments()[0]);
+ assertEquals(String.class, inv.getParameterTypes()[0]);
+
+ // this is a bit BS, but we need to test it
+ inv = new RemoteInvocation();
+ inv.setArguments(new Object[] { "bla" });
+ assertEquals("bla", inv.getArguments()[0]);
+ inv.setMethodName("setName");
+ assertEquals("setName", inv.getMethodName());
+ inv.setParameterTypes(new Class[] {String.class});
+ assertEquals(String.class, inv.getParameterTypes()[0]);
+
+ inv = new RemoteInvocation("setName", new Class[] {String.class}, new Object[] {"bla"});
+ assertEquals("bla", inv.getArguments()[0]);
+ assertEquals("setName", inv.getMethodName());
+ assertEquals(String.class, inv.getParameterTypes()[0]);
+ }
+
+ public void testRmiInvokerWithSpecialLocalMethods() throws Exception {
+ String serviceUrl = "rmi://localhost:1090/test";
+ RmiProxyFactoryBean factory = new RmiProxyFactoryBean() {
+ protected Remote lookupStub() {
+ return new RmiInvocationHandler() {
+ public String getTargetInterfaceName() {
+ return null;
+ }
+ public Object invoke(RemoteInvocation invocation) throws RemoteException {
+ throw new RemoteException();
+ }
+ };
+ }
+ };
+ factory.setServiceInterface(IBusinessBean.class);
+ factory.setServiceUrl(serviceUrl);
+ factory.afterPropertiesSet();
+ IBusinessBean proxy = (IBusinessBean) factory.getObject();
+
+ // shouldn't go through to remote service
+ assertTrue(proxy.toString().indexOf("RMI invoker") != -1);
+ assertTrue(proxy.toString().indexOf(serviceUrl) != -1);
+ assertEquals(proxy.hashCode(), proxy.hashCode());
+ assertTrue(proxy.equals(proxy));
+
+ // should go through
+ try {
+ proxy.setName("test");
+ fail("Should have thrown RemoteAccessException");
+ }
+ catch (RemoteAccessException ex) {
+ // expected
+ }
+ }
+
+
+ private static class CountingRmiProxyFactoryBean extends RmiProxyFactoryBean {
+
+ private int counter = 0;
+
+ protected Remote lookupStub() {
+ counter++;
+ return new RemoteBean();
+ }
+ }
+
+
+ public static interface IBusinessBean {
+
+ public void setName(String name);
+
+ }
+
+
+ public static interface IWrongBusinessBean {
+
+ public void setOtherName(String name);
+
+ }
+
+
+ public static interface IRemoteBean extends Remote {
+
+ public void setName(String name) throws RemoteException;
+
+ }
+
+
+ public static class RemoteBean implements IRemoteBean {
+
+ private static String name;
+
+ public void setName(String nam) throws RemoteException {
+ if (nam != null && nam.endsWith("Exception")) {
+ RemoteException rex = null;
+ try {
+ Class exClass = Class.forName(nam);
+ Constructor ctor = exClass.getConstructor(new Class[] {String.class});
+ rex = (RemoteException) ctor.newInstance(new Object[] {"myMessage"});
+ }
+ catch (Exception ex) {
+ throw new RemoteException("Illegal exception class name: " + nam, ex);
+ }
+ throw rex;
+ }
+ name = nam;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/remoting/support/RemoteInvocationUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/remoting/support/RemoteInvocationUtilsTests.java
new file mode 100644
index 00000000000..57d532d3e9f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/remoting/support/RemoteInvocationUtilsTests.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.remoting.support;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rick Evans
+ */
+public class RemoteInvocationUtilsTests extends TestCase {
+
+ public void testFillInClientStackTraceIfPossibleSunnyDay() throws Exception {
+ try {
+ throw new IllegalStateException("Mmm");
+ }
+ catch (Exception ex) {
+ int originalStackTraceLngth = ex.getStackTrace().length;
+ RemoteInvocationUtils.fillInClientStackTraceIfPossible(ex);
+ assertTrue("Stack trace not being filled in",
+ ex.getStackTrace().length > originalStackTraceLngth);
+ }
+ }
+
+ public void testFillInClientStackTraceIfPossibleWithNullThrowable() throws Exception {
+ // just want to ensure that it doesn't bomb
+ RemoteInvocationUtils.fillInClientStackTraceIfPossible(null);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scheduling/TestMethodInvokingTask.java b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/TestMethodInvokingTask.java
new file mode 100644
index 00000000000..364610db9e8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/TestMethodInvokingTask.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.scheduling;
+
+/**
+ * @author Juergen Hoeller
+ * @since 09.10.2004
+ */
+public class TestMethodInvokingTask {
+
+ public int counter = 0;
+
+ private Object lock = new Object();
+
+ public void doSomething() {
+ this.counter++;
+ }
+
+ public void doWait() {
+ this.counter++;
+ // wait until stop is called
+ synchronized (this.lock) {
+ try {
+ this.lock.wait();
+ }
+ catch (InterruptedException e) {
+ // fall through
+ }
+ }
+ }
+
+ public void stop() {
+ synchronized(this.lock) {
+ this.lock.notify();
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scheduling/backportconcurrent/ConcurrentTaskExecutorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/backportconcurrent/ConcurrentTaskExecutorTests.java
new file mode 100644
index 00000000000..0d8729dfdf3
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/backportconcurrent/ConcurrentTaskExecutorTests.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.scheduling.backportconcurrent;
+
+import junit.framework.TestCase;
+
+import org.springframework.core.task.NoOpRunnable;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class ConcurrentTaskExecutorTests extends TestCase {
+
+ public void testZeroArgCtorResultsInDefaultTaskExecutorBeingUsed() throws Exception {
+ ConcurrentTaskExecutor executor = new ConcurrentTaskExecutor();
+ // must not throw a NullPointerException
+ executor.execute(new NoOpRunnable());
+ }
+
+ public void testPassingNullExecutorToCtorResultsInDefaultTaskExecutorBeingUsed() throws Exception {
+ ConcurrentTaskExecutor executor = new ConcurrentTaskExecutor(null);
+ // must not throw a NullPointerException
+ executor.execute(new NoOpRunnable());
+ }
+
+ public void testPassingNullExecutorToSetterResultsInDefaultTaskExecutorBeingUsed() throws Exception {
+ ConcurrentTaskExecutor executor = new ConcurrentTaskExecutor();
+ executor.setConcurrentExecutor(null);
+ // must not throw a NullPointerException
+ executor.execute(new NoOpRunnable());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scheduling/backportconcurrent/ScheduledExecutorFactoryBeanTests.java b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/backportconcurrent/ScheduledExecutorFactoryBeanTests.java
new file mode 100644
index 00000000000..b2a440c5117
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/backportconcurrent/ScheduledExecutorFactoryBeanTests.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.scheduling.backportconcurrent;
+
+import edu.emory.mathcs.backport.java.util.concurrent.RejectedExecutionHandler;
+import edu.emory.mathcs.backport.java.util.concurrent.ScheduledExecutorService;
+import edu.emory.mathcs.backport.java.util.concurrent.ThreadFactory;
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.core.task.NoOpRunnable;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class ScheduledExecutorFactoryBeanTests extends TestCase {
+
+ public void testThrowsExceptionIfPoolSizeIsLessThanZero() throws Exception {
+ try {
+ ScheduledExecutorFactoryBean factory = new ScheduledExecutorFactoryBean();
+ factory.setPoolSize(-1);
+ factory.setScheduledExecutorTasks(new ScheduledExecutorTask[]{
+ new NoOpScheduledExecutorTask()
+ });
+ factory.afterPropertiesSet();
+ fail("Pool size less than zero");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testShutdownNowIsPropagatedToTheExecutorOnDestroy() throws Exception {
+ MockControl mockScheduledExecutorService = MockControl.createNiceControl(ScheduledExecutorService.class);
+ final ScheduledExecutorService executor = (ScheduledExecutorService) mockScheduledExecutorService.getMock();
+ executor.shutdownNow();
+ mockScheduledExecutorService.setReturnValue(null);
+ mockScheduledExecutorService.replay();
+
+ ScheduledExecutorFactoryBean factory = new ScheduledExecutorFactoryBean() {
+ protected ScheduledExecutorService createExecutor(int poolSize, ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
+ return executor;
+ }
+ };
+ factory.setScheduledExecutorTasks(new ScheduledExecutorTask[]{
+ new NoOpScheduledExecutorTask()
+ });
+ factory.afterPropertiesSet();
+ factory.destroy();
+
+ mockScheduledExecutorService.verify();
+ }
+
+ public void testShutdownIsPropagatedToTheExecutorOnDestroy() throws Exception {
+ MockControl mockScheduledExecutorService = MockControl.createNiceControl(ScheduledExecutorService.class);
+ final ScheduledExecutorService executor = (ScheduledExecutorService) mockScheduledExecutorService.getMock();
+ executor.shutdown();
+ mockScheduledExecutorService.setVoidCallable();
+ mockScheduledExecutorService.replay();
+
+ ScheduledExecutorFactoryBean factory = new ScheduledExecutorFactoryBean() {
+ protected ScheduledExecutorService createExecutor(int poolSize, ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
+ return executor;
+ }
+ };
+ factory.setScheduledExecutorTasks(new ScheduledExecutorTask[]{
+ new NoOpScheduledExecutorTask()
+ });
+ factory.setWaitForTasksToCompleteOnShutdown(true);
+ factory.afterPropertiesSet();
+ factory.destroy();
+
+ mockScheduledExecutorService.verify();
+ }
+
+ public void testOneTimeExecutionIsSetUpAndFiresCorrectly() throws Exception {
+ MockControl mockRunnable = MockControl.createControl(Runnable.class);
+ Runnable runnable = (Runnable) mockRunnable.getMock();
+ runnable.run();
+ mockRunnable.setVoidCallable();
+ mockRunnable.replay();
+
+ ScheduledExecutorFactoryBean factory = new ScheduledExecutorFactoryBean();
+ factory.setScheduledExecutorTasks(new ScheduledExecutorTask[]{
+ new ScheduledExecutorTask(runnable)
+ });
+ factory.afterPropertiesSet();
+ pauseToLetTaskStart(1);
+ factory.destroy();
+
+ mockRunnable.verify();
+ }
+
+ public void testFixedRepeatedExecutionIsSetUpAndFiresCorrectly() throws Exception {
+ MockControl mockRunnable = MockControl.createControl(Runnable.class);
+ Runnable runnable = (Runnable) mockRunnable.getMock();
+ runnable.run();
+ mockRunnable.setVoidCallable();
+ runnable.run();
+ mockRunnable.setVoidCallable();
+ mockRunnable.replay();
+
+ ScheduledExecutorTask task = new ScheduledExecutorTask(runnable);
+ task.setPeriod(500);
+ task.setFixedRate(true);
+
+ ScheduledExecutorFactoryBean factory = new ScheduledExecutorFactoryBean();
+ factory.setScheduledExecutorTasks(new ScheduledExecutorTask[]{task});
+ factory.afterPropertiesSet();
+ pauseToLetTaskStart(2);
+ factory.destroy();
+
+ mockRunnable.verify();
+ }
+
+ public void testFixedRepeatedExecutionIsSetUpAndFiresCorrectlyAfterException() throws Exception {
+ MockControl mockRunnable = MockControl.createControl(Runnable.class);
+ Runnable runnable = (Runnable) mockRunnable.getMock();
+ runnable.run();
+ mockRunnable.setThrowable(new IllegalStateException());
+ runnable.run();
+ mockRunnable.setThrowable(new IllegalStateException());
+ mockRunnable.replay();
+
+ ScheduledExecutorTask task = new ScheduledExecutorTask(runnable);
+ task.setPeriod(500);
+ task.setFixedRate(true);
+
+ ScheduledExecutorFactoryBean factory = new ScheduledExecutorFactoryBean();
+ factory.setScheduledExecutorTasks(new ScheduledExecutorTask[]{task});
+ factory.setContinueScheduledExecutionAfterException(true);
+ factory.afterPropertiesSet();
+ pauseToLetTaskStart(2);
+ factory.destroy();
+
+ mockRunnable.verify();
+ }
+
+ public void testWithInitialDelayRepeatedExecutionIsSetUpAndFiresCorrectly() throws Exception {
+ MockControl mockRunnable = MockControl.createControl(Runnable.class);
+ Runnable runnable = (Runnable) mockRunnable.getMock();
+ runnable.run();
+ mockRunnable.setVoidCallable();
+ runnable.run();
+ mockRunnable.setVoidCallable();
+ mockRunnable.replay();
+
+ ScheduledExecutorTask task = new ScheduledExecutorTask(runnable);
+ task.setPeriod(500);
+ task.setDelay(3000); // nice long wait...
+
+ ScheduledExecutorFactoryBean factory = new ScheduledExecutorFactoryBean();
+ factory.setScheduledExecutorTasks(new ScheduledExecutorTask[] {task});
+ factory.afterPropertiesSet();
+ pauseToLetTaskStart(1);
+ // invoke destroy before tasks have even been scheduled...
+ factory.destroy();
+
+ try {
+ mockRunnable.verify();
+ fail("Mock must never have been called");
+ }
+ catch (AssertionFailedError expected) {
+ }
+ }
+
+ public void testWithInitialDelayRepeatedExecutionIsSetUpAndFiresCorrectlyAfterException() throws Exception {
+ MockControl mockRunnable = MockControl.createControl(Runnable.class);
+ Runnable runnable = (Runnable) mockRunnable.getMock();
+ runnable.run();
+ mockRunnable.setThrowable(new IllegalStateException());
+ runnable.run();
+ mockRunnable.setThrowable(new IllegalStateException());
+ mockRunnable.replay();
+
+ ScheduledExecutorTask task = new ScheduledExecutorTask(runnable);
+ task.setPeriod(500);
+ task.setDelay(3000); // nice long wait...
+
+ ScheduledExecutorFactoryBean factory = new ScheduledExecutorFactoryBean();
+ factory.setScheduledExecutorTasks(new ScheduledExecutorTask[] {task});
+ factory.setContinueScheduledExecutionAfterException(true);
+ factory.afterPropertiesSet();
+ pauseToLetTaskStart(1);
+ // invoke destroy before tasks have even been scheduled...
+ factory.destroy();
+
+ try {
+ mockRunnable.verify();
+ fail("Mock must never have been called");
+ }
+ catch (AssertionFailedError expected) {
+ }
+ }
+
+ public void testSettingThreadFactoryToNullForcesUseOfDefaultButIsOtherwiseCool() throws Exception {
+ ScheduledExecutorFactoryBean factory = new ScheduledExecutorFactoryBean() {
+ protected ScheduledExecutorService createExecutor(int poolSize, ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
+ assertNotNull("Bah; the setThreadFactory(..) method must use a default ThreadFactory if a null arg is passed in.");
+ return super.createExecutor(poolSize, threadFactory, rejectedExecutionHandler);
+ }
+ };
+ factory.setScheduledExecutorTasks(new ScheduledExecutorTask[]{
+ new NoOpScheduledExecutorTask()
+ });
+ factory.setThreadFactory(null); // the null must not propagate
+ factory.afterPropertiesSet();
+ factory.destroy();
+ }
+
+ public void testSettingRejectedExecutionHandlerToNullForcesUseOfDefaultButIsOtherwiseCool() throws Exception {
+ ScheduledExecutorFactoryBean factory = new ScheduledExecutorFactoryBean() {
+ protected ScheduledExecutorService createExecutor(int poolSize, ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
+ assertNotNull("Bah; the setRejectedExecutionHandler(..) method must use a default RejectedExecutionHandler if a null arg is passed in.");
+ return super.createExecutor(poolSize, threadFactory, rejectedExecutionHandler);
+ }
+ };
+ factory.setScheduledExecutorTasks(new ScheduledExecutorTask[]{
+ new NoOpScheduledExecutorTask()
+ });
+ factory.setRejectedExecutionHandler(null); // the null must not propagate
+ factory.afterPropertiesSet();
+ factory.destroy();
+ }
+
+ public void testObjectTypeReportsCorrectType() throws Exception {
+ ScheduledExecutorFactoryBean factory = new ScheduledExecutorFactoryBean();
+ assertEquals(ScheduledExecutorService.class, factory.getObjectType());
+ }
+
+
+ private static void pauseToLetTaskStart(int seconds) {
+ try {
+ Thread.sleep(seconds * 1000);
+ }
+ catch (InterruptedException ignored) {
+ }
+ }
+
+
+ private static class NoOpScheduledExecutorTask extends ScheduledExecutorTask {
+
+ public NoOpScheduledExecutorTask() {
+ super(new NoOpRunnable());
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scheduling/quartz/QuartzSupportTests.java b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/quartz/QuartzSupportTests.java
new file mode 100644
index 00000000000..e98d0c1482a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/quartz/QuartzSupportTests.java
@@ -0,0 +1,1082 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.scheduling.quartz;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+import org.quartz.CronTrigger;
+import org.quartz.Job;
+import org.quartz.JobDetail;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.quartz.JobListener;
+import org.quartz.ObjectAlreadyExistsException;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerContext;
+import org.quartz.SchedulerException;
+import org.quartz.SchedulerFactory;
+import org.quartz.SchedulerListener;
+import org.quartz.SimpleTrigger;
+import org.quartz.Trigger;
+import org.quartz.TriggerListener;
+import org.quartz.impl.SchedulerRepository;
+import org.quartz.spi.JobFactory;
+
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.support.StaticListableBeanFactory;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.context.support.StaticApplicationContext;
+import org.springframework.core.io.FileSystemResourceLoader;
+import org.springframework.core.task.TaskExecutor;
+import org.springframework.scheduling.TestMethodInvokingTask;
+
+/**
+ * @author Juergen Hoeller
+ * @author Alef Arendsen
+ * @author Rob Harrop
+ * @since 20.02.2004
+ */
+public class QuartzSupportTests extends TestCase {
+
+ public void testSchedulerFactoryBean() throws Exception {
+ doTestSchedulerFactoryBean(false, false);
+ }
+
+ public void testSchedulerFactoryBeanWithExplicitJobDetail() throws Exception {
+ doTestSchedulerFactoryBean(true, false);
+ }
+
+ public void testSchedulerFactoryBeanWithPrototypeJob() throws Exception {
+ doTestSchedulerFactoryBean(false, true);
+ }
+
+ private void doTestSchedulerFactoryBean(boolean explicitJobDetail, boolean prototypeJob) throws Exception {
+ TestBean tb = new TestBean("tb", 99);
+ JobDetailBean jobDetail0 = new JobDetailBean();
+ jobDetail0.setJobClass(Job.class);
+ jobDetail0.setBeanName("myJob0");
+ Map jobData = new HashMap();
+ jobData.put("testBean", tb);
+ jobDetail0.setJobDataAsMap(jobData);
+ jobDetail0.afterPropertiesSet();
+ assertEquals(tb, jobDetail0.getJobDataMap().get("testBean"));
+
+ CronTriggerBean trigger0 = new CronTriggerBean();
+ trigger0.setBeanName("myTrigger0");
+ trigger0.setJobDetail(jobDetail0);
+ trigger0.setCronExpression("0/1 * * * * ?");
+ trigger0.afterPropertiesSet();
+
+ TestMethodInvokingTask task1 = new TestMethodInvokingTask();
+ MethodInvokingJobDetailFactoryBean mijdfb = new MethodInvokingJobDetailFactoryBean();
+ mijdfb.setBeanName("myJob1");
+ if (prototypeJob) {
+ StaticListableBeanFactory beanFactory = new StaticListableBeanFactory();
+ beanFactory.addBean("task", task1);
+ mijdfb.setTargetBeanName("task");
+ mijdfb.setBeanFactory(beanFactory);
+ }
+ else {
+ mijdfb.setTargetObject(task1);
+ }
+ mijdfb.setTargetMethod("doSomething");
+ mijdfb.afterPropertiesSet();
+ JobDetail jobDetail1 = (JobDetail) mijdfb.getObject();
+
+ SimpleTriggerBean trigger1 = new SimpleTriggerBean();
+ trigger1.setBeanName("myTrigger1");
+ trigger1.setJobDetail(jobDetail1);
+ trigger1.setStartDelay(0);
+ trigger1.setRepeatInterval(20);
+ trigger1.afterPropertiesSet();
+
+ MockControl schedulerControl = MockControl.createControl(Scheduler.class);
+ final Scheduler scheduler = (Scheduler) schedulerControl.getMock();
+ scheduler.getContext();
+ schedulerControl.setReturnValue(new SchedulerContext());
+ scheduler.getJobDetail("myJob0", Scheduler.DEFAULT_GROUP);
+ schedulerControl.setReturnValue(null);
+ scheduler.getJobDetail("myJob1", Scheduler.DEFAULT_GROUP);
+ schedulerControl.setReturnValue(null);
+ scheduler.getTrigger("myTrigger0", Scheduler.DEFAULT_GROUP);
+ schedulerControl.setReturnValue(null);
+ scheduler.getTrigger("myTrigger1", Scheduler.DEFAULT_GROUP);
+ schedulerControl.setReturnValue(null);
+ scheduler.addJob(jobDetail0, true);
+ schedulerControl.setVoidCallable();
+ scheduler.scheduleJob(trigger0);
+ schedulerControl.setReturnValue(new Date());
+ scheduler.addJob(jobDetail1, true);
+ schedulerControl.setVoidCallable();
+ scheduler.scheduleJob(trigger1);
+ schedulerControl.setReturnValue(new Date());
+ scheduler.start();
+ schedulerControl.setVoidCallable();
+ scheduler.shutdown(false);
+ schedulerControl.setVoidCallable();
+ schedulerControl.replay();
+
+ SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean() {
+ protected Scheduler createScheduler(SchedulerFactory schedulerFactory, String schedulerName) {
+ return scheduler;
+ }
+ };
+ schedulerFactoryBean.setJobFactory(null);
+ Map schedulerContext = new HashMap();
+ schedulerContext.put("otherTestBean", tb);
+ schedulerFactoryBean.setSchedulerContextAsMap(schedulerContext);
+ if (explicitJobDetail) {
+ schedulerFactoryBean.setJobDetails(new JobDetail[] {jobDetail0});
+ }
+ schedulerFactoryBean.setTriggers(new Trigger[] {trigger0, trigger1});
+ try {
+ schedulerFactoryBean.afterPropertiesSet();
+ }
+ finally {
+ schedulerFactoryBean.destroy();
+ }
+
+ schedulerControl.verify();
+ }
+
+ public void testSchedulerFactoryBeanWithExistingJobs() throws Exception {
+ doTestSchedulerFactoryBeanWithExistingJobs(false);
+ }
+
+ public void testSchedulerFactoryBeanWithOverwriteExistingJobs() throws Exception {
+ doTestSchedulerFactoryBeanWithExistingJobs(true);
+ }
+
+ private void doTestSchedulerFactoryBeanWithExistingJobs(boolean overwrite) throws Exception {
+ TestBean tb = new TestBean("tb", 99);
+ JobDetailBean jobDetail0 = new JobDetailBean();
+ jobDetail0.setJobClass(Job.class);
+ jobDetail0.setBeanName("myJob0");
+ Map jobData = new HashMap();
+ jobData.put("testBean", tb);
+ jobDetail0.setJobDataAsMap(jobData);
+ jobDetail0.afterPropertiesSet();
+ assertEquals(tb, jobDetail0.getJobDataMap().get("testBean"));
+
+ CronTriggerBean trigger0 = new CronTriggerBean();
+ trigger0.setBeanName("myTrigger0");
+ trigger0.setJobDetail(jobDetail0);
+ trigger0.setCronExpression("0/1 * * * * ?");
+ trigger0.afterPropertiesSet();
+
+ TestMethodInvokingTask task1 = new TestMethodInvokingTask();
+ MethodInvokingJobDetailFactoryBean mijdfb = new MethodInvokingJobDetailFactoryBean();
+ mijdfb.setBeanName("myJob1");
+ mijdfb.setTargetObject(task1);
+ mijdfb.setTargetMethod("doSomething");
+ mijdfb.afterPropertiesSet();
+ JobDetail jobDetail1 = (JobDetail) mijdfb.getObject();
+
+ SimpleTriggerBean trigger1 = new SimpleTriggerBean();
+ trigger1.setBeanName("myTrigger1");
+ trigger1.setJobDetail(jobDetail1);
+ trigger1.setStartDelay(0);
+ trigger1.setRepeatInterval(20);
+ trigger1.afterPropertiesSet();
+
+ MockControl schedulerControl = MockControl.createControl(Scheduler.class);
+ final Scheduler scheduler = (Scheduler) schedulerControl.getMock();
+ scheduler.getContext();
+ schedulerControl.setReturnValue(new SchedulerContext());
+ scheduler.getTrigger("myTrigger0", Scheduler.DEFAULT_GROUP);
+ schedulerControl.setReturnValue(null);
+ scheduler.getTrigger("myTrigger1", Scheduler.DEFAULT_GROUP);
+ schedulerControl.setReturnValue(new SimpleTrigger());
+ if (overwrite) {
+ scheduler.addJob(jobDetail1, true);
+ schedulerControl.setVoidCallable();
+ scheduler.rescheduleJob("myTrigger1", Scheduler.DEFAULT_GROUP, trigger1);
+ schedulerControl.setReturnValue(new Date());
+ }
+ else {
+ scheduler.getJobDetail("myJob0", Scheduler.DEFAULT_GROUP);
+ schedulerControl.setReturnValue(null);
+ }
+ scheduler.addJob(jobDetail0, true);
+ schedulerControl.setVoidCallable();
+ scheduler.scheduleJob(trigger0);
+ schedulerControl.setReturnValue(new Date());
+ scheduler.start();
+ schedulerControl.setVoidCallable();
+ scheduler.shutdown(false);
+ schedulerControl.setVoidCallable();
+ schedulerControl.replay();
+
+ SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean() {
+ protected Scheduler createScheduler(SchedulerFactory schedulerFactory, String schedulerName) {
+ return scheduler;
+ }
+ };
+ schedulerFactoryBean.setJobFactory(null);
+ Map schedulerContext = new HashMap();
+ schedulerContext.put("otherTestBean", tb);
+ schedulerFactoryBean.setSchedulerContextAsMap(schedulerContext);
+ schedulerFactoryBean.setTriggers(new Trigger[] {trigger0, trigger1});
+ if (overwrite) {
+ schedulerFactoryBean.setOverwriteExistingJobs(true);
+ }
+ try {
+ schedulerFactoryBean.afterPropertiesSet();
+ }
+ finally {
+ schedulerFactoryBean.destroy();
+ }
+
+ schedulerControl.verify();
+ }
+
+ public void testSchedulerFactoryBeanWithExistingJobsAndRaceCondition() throws Exception {
+ doTestSchedulerFactoryBeanWithExistingJobsAndRaceCondition(false);
+ }
+
+ public void testSchedulerFactoryBeanWithOverwriteExistingJobsAndRaceCondition() throws Exception {
+ doTestSchedulerFactoryBeanWithExistingJobsAndRaceCondition(true);
+ }
+
+ private void doTestSchedulerFactoryBeanWithExistingJobsAndRaceCondition(boolean overwrite) throws Exception {
+ TestBean tb = new TestBean("tb", 99);
+ JobDetailBean jobDetail0 = new JobDetailBean();
+ jobDetail0.setJobClass(Job.class);
+ jobDetail0.setBeanName("myJob0");
+ Map jobData = new HashMap();
+ jobData.put("testBean", tb);
+ jobDetail0.setJobDataAsMap(jobData);
+ jobDetail0.afterPropertiesSet();
+ assertEquals(tb, jobDetail0.getJobDataMap().get("testBean"));
+
+ CronTriggerBean trigger0 = new CronTriggerBean();
+ trigger0.setBeanName("myTrigger0");
+ trigger0.setJobDetail(jobDetail0);
+ trigger0.setCronExpression("0/1 * * * * ?");
+ trigger0.afterPropertiesSet();
+
+ TestMethodInvokingTask task1 = new TestMethodInvokingTask();
+ MethodInvokingJobDetailFactoryBean mijdfb = new MethodInvokingJobDetailFactoryBean();
+ mijdfb.setBeanName("myJob1");
+ mijdfb.setTargetObject(task1);
+ mijdfb.setTargetMethod("doSomething");
+ mijdfb.afterPropertiesSet();
+ JobDetail jobDetail1 = (JobDetail) mijdfb.getObject();
+
+ SimpleTriggerBean trigger1 = new SimpleTriggerBean();
+ trigger1.setBeanName("myTrigger1");
+ trigger1.setJobDetail(jobDetail1);
+ trigger1.setStartDelay(0);
+ trigger1.setRepeatInterval(20);
+ trigger1.afterPropertiesSet();
+
+ MockControl schedulerControl = MockControl.createControl(Scheduler.class);
+ final Scheduler scheduler = (Scheduler) schedulerControl.getMock();
+ scheduler.getContext();
+ schedulerControl.setReturnValue(new SchedulerContext());
+ scheduler.getTrigger("myTrigger0", Scheduler.DEFAULT_GROUP);
+ schedulerControl.setReturnValue(null);
+ scheduler.getTrigger("myTrigger1", Scheduler.DEFAULT_GROUP);
+ schedulerControl.setReturnValue(new SimpleTrigger());
+ if (overwrite) {
+ scheduler.addJob(jobDetail1, true);
+ schedulerControl.setVoidCallable();
+ scheduler.rescheduleJob("myTrigger1", Scheduler.DEFAULT_GROUP, trigger1);
+ schedulerControl.setReturnValue(new Date());
+ }
+ else {
+ scheduler.getJobDetail("myJob0", Scheduler.DEFAULT_GROUP);
+ schedulerControl.setReturnValue(null);
+ }
+ scheduler.addJob(jobDetail0, true);
+ schedulerControl.setVoidCallable();
+ scheduler.scheduleJob(trigger0);
+ schedulerControl.setThrowable(new ObjectAlreadyExistsException(""));
+ if (overwrite) {
+ scheduler.rescheduleJob("myTrigger0", Scheduler.DEFAULT_GROUP, trigger0);
+ schedulerControl.setReturnValue(new Date());
+ }
+ scheduler.start();
+ schedulerControl.setVoidCallable();
+ scheduler.shutdown(false);
+ schedulerControl.setVoidCallable();
+ schedulerControl.replay();
+
+ SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean() {
+ protected Scheduler createScheduler(SchedulerFactory schedulerFactory, String schedulerName) {
+ return scheduler;
+ }
+ };
+ schedulerFactoryBean.setJobFactory(null);
+ Map schedulerContext = new HashMap();
+ schedulerContext.put("otherTestBean", tb);
+ schedulerFactoryBean.setSchedulerContextAsMap(schedulerContext);
+ schedulerFactoryBean.setTriggers(new Trigger[] {trigger0, trigger1});
+ if (overwrite) {
+ schedulerFactoryBean.setOverwriteExistingJobs(true);
+ }
+ try {
+ schedulerFactoryBean.afterPropertiesSet();
+ }
+ finally {
+ schedulerFactoryBean.destroy();
+ }
+
+ schedulerControl.verify();
+ }
+
+ public void testSchedulerFactoryBeanWithListeners() throws Exception {
+ JobFactory jobFactory = new AdaptableJobFactory();
+
+ MockControl schedulerControl = MockControl.createControl(Scheduler.class);
+ final Scheduler scheduler = (Scheduler) schedulerControl.getMock();
+
+ SchedulerListener schedulerListener = new TestSchedulerListener();
+ JobListener globalJobListener = new TestJobListener();
+ JobListener jobListener = new TestJobListener();
+ TriggerListener globalTriggerListener = new TestTriggerListener();
+ TriggerListener triggerListener = new TestTriggerListener();
+
+ scheduler.setJobFactory(jobFactory);
+ schedulerControl.setVoidCallable();
+ scheduler.addSchedulerListener(schedulerListener);
+ schedulerControl.setVoidCallable();
+ scheduler.addGlobalJobListener(globalJobListener);
+ schedulerControl.setVoidCallable();
+ scheduler.addJobListener(jobListener);
+ schedulerControl.setVoidCallable();
+ scheduler.addGlobalTriggerListener(globalTriggerListener);
+ schedulerControl.setVoidCallable();
+ scheduler.addTriggerListener(triggerListener);
+ schedulerControl.setVoidCallable();
+ scheduler.start();
+ schedulerControl.setVoidCallable();
+ scheduler.shutdown(false);
+ schedulerControl.setVoidCallable();
+ schedulerControl.replay();
+
+ SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean() {
+ protected Scheduler createScheduler(SchedulerFactory schedulerFactory, String schedulerName) {
+ return scheduler;
+ }
+ };
+ schedulerFactoryBean.setJobFactory(jobFactory);
+ schedulerFactoryBean.setSchedulerListeners(new SchedulerListener[] {schedulerListener});
+ schedulerFactoryBean.setGlobalJobListeners(new JobListener[] {globalJobListener});
+ schedulerFactoryBean.setJobListeners(new JobListener[] {jobListener});
+ schedulerFactoryBean.setGlobalTriggerListeners(new TriggerListener[] {globalTriggerListener});
+ schedulerFactoryBean.setTriggerListeners(new TriggerListener[] {triggerListener});
+ try {
+ schedulerFactoryBean.afterPropertiesSet();
+ }
+ finally {
+ schedulerFactoryBean.destroy();
+ }
+
+ schedulerControl.verify();
+ }
+
+ /*public void testMethodInvocationWithConcurrency() throws Exception {
+ methodInvokingConcurrency(true);
+ }*/
+
+ // We can't test both since Quartz somehow seems to keep things in memory
+ // enable both and one of them will fail (order doesn't matter).
+ /*public void testMethodInvocationWithoutConcurrency() throws Exception {
+ methodInvokingConcurrency(false);
+ }*/
+
+ private void methodInvokingConcurrency(boolean concurrent) throws Exception {
+ // Test the concurrency flag.
+ // Method invoking job with two triggers.
+ // If the concurrent flag is false, the triggers are NOT allowed
+ // to interfere with each other.
+
+ TestMethodInvokingTask task1 = new TestMethodInvokingTask();
+ MethodInvokingJobDetailFactoryBean mijdfb = new MethodInvokingJobDetailFactoryBean();
+ // set the concurrency flag!
+ mijdfb.setConcurrent(concurrent);
+ mijdfb.setBeanName("myJob1");
+ mijdfb.setTargetObject(task1);
+ mijdfb.setTargetMethod("doWait");
+ mijdfb.afterPropertiesSet();
+ JobDetail jobDetail1 = (JobDetail) mijdfb.getObject();
+
+ SimpleTriggerBean trigger0 = new SimpleTriggerBean();
+ trigger0.setBeanName("myTrigger1");
+ trigger0.setJobDetail(jobDetail1);
+ trigger0.setStartDelay(0);
+ trigger0.setRepeatInterval(1);
+ trigger0.setRepeatCount(1);
+ trigger0.afterPropertiesSet();
+
+ SimpleTriggerBean trigger1 = new SimpleTriggerBean();
+ trigger1.setBeanName("myTrigger1");
+ trigger1.setJobDetail(jobDetail1);
+ trigger1.setStartDelay(1000L);
+ trigger1.setRepeatInterval(1);
+ trigger1.setRepeatCount(1);
+ trigger1.afterPropertiesSet();
+
+ SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
+ schedulerFactoryBean.setJobDetails(new JobDetail[] {jobDetail1});
+ schedulerFactoryBean.setTriggers(new Trigger[] {trigger1, trigger0});
+ schedulerFactoryBean.afterPropertiesSet();
+
+ // ok scheduler is set up... let's wait for like 4 seconds
+ try {
+ Thread.sleep(4000);
+ }
+ catch (InterruptedException ex) {
+ // fall through
+ }
+
+ if (concurrent) {
+ assertEquals(2, task1.counter);
+ task1.stop();
+ // we're done, both jobs have ran, let's call it a day
+ return;
+ }
+ else {
+ assertEquals(1, task1.counter);
+ task1.stop();
+ // we need to check whether or not the test succeed with non-concurrent jobs
+ }
+
+ try {
+ Thread.sleep(4000);
+ }
+ catch (InterruptedException ex) {
+ // fall through
+ }
+
+ task1.stop();
+ assertEquals(2, task1.counter);
+
+ // Although we're destroying the scheduler, it does seem to keep things in memory:
+ // When executing both tests (concurrent and non-concurrent), the second test always
+ // fails.
+ schedulerFactoryBean.destroy();
+ }
+
+ public void testSchedulerFactoryBeanWithPlainQuartzObjects() throws Exception {
+ JobFactory jobFactory = new AdaptableJobFactory();
+
+ TestBean tb = new TestBean("tb", 99);
+ JobDetail jobDetail0 = new JobDetail();
+ jobDetail0.setJobClass(Job.class);
+ jobDetail0.setName("myJob0");
+ jobDetail0.setGroup(Scheduler.DEFAULT_GROUP);
+ jobDetail0.getJobDataMap().put("testBean", tb);
+ assertEquals(tb, jobDetail0.getJobDataMap().get("testBean"));
+
+ CronTrigger trigger0 = new CronTrigger();
+ trigger0.setName("myTrigger0");
+ trigger0.setGroup(Scheduler.DEFAULT_GROUP);
+ trigger0.setJobName("myJob0");
+ trigger0.setJobGroup(Scheduler.DEFAULT_GROUP);
+ trigger0.setStartTime(new Date());
+ trigger0.setCronExpression("0/1 * * * * ?");
+
+ TestMethodInvokingTask task1 = new TestMethodInvokingTask();
+ MethodInvokingJobDetailFactoryBean mijdfb = new MethodInvokingJobDetailFactoryBean();
+ mijdfb.setName("myJob1");
+ mijdfb.setGroup(Scheduler.DEFAULT_GROUP);
+ mijdfb.setTargetObject(task1);
+ mijdfb.setTargetMethod("doSomething");
+ mijdfb.afterPropertiesSet();
+ JobDetail jobDetail1 = (JobDetail) mijdfb.getObject();
+
+ SimpleTrigger trigger1 = new SimpleTrigger();
+ trigger1.setName("myTrigger1");
+ trigger1.setGroup(Scheduler.DEFAULT_GROUP);
+ trigger1.setJobName("myJob1");
+ trigger1.setJobGroup(Scheduler.DEFAULT_GROUP);
+ trigger1.setStartTime(new Date());
+ trigger1.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
+ trigger1.setRepeatInterval(20);
+
+ MockControl schedulerControl = MockControl.createControl(Scheduler.class);
+ final Scheduler scheduler = (Scheduler) schedulerControl.getMock();
+ scheduler.setJobFactory(jobFactory);
+ schedulerControl.setVoidCallable();
+ scheduler.getJobDetail("myJob0", Scheduler.DEFAULT_GROUP);
+ schedulerControl.setReturnValue(null);
+ scheduler.getJobDetail("myJob1", Scheduler.DEFAULT_GROUP);
+ schedulerControl.setReturnValue(null);
+ scheduler.getTrigger("myTrigger0", Scheduler.DEFAULT_GROUP);
+ schedulerControl.setReturnValue(null);
+ scheduler.getTrigger("myTrigger1", Scheduler.DEFAULT_GROUP);
+ schedulerControl.setReturnValue(null);
+ scheduler.addJob(jobDetail0, true);
+ schedulerControl.setVoidCallable();
+ scheduler.addJob(jobDetail1, true);
+ schedulerControl.setVoidCallable();
+ scheduler.scheduleJob(trigger0);
+ schedulerControl.setReturnValue(new Date());
+ scheduler.scheduleJob(trigger1);
+ schedulerControl.setReturnValue(new Date());
+ scheduler.start();
+ schedulerControl.setVoidCallable();
+ scheduler.shutdown(false);
+ schedulerControl.setVoidCallable();
+ schedulerControl.replay();
+
+ SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean() {
+ protected Scheduler createScheduler(SchedulerFactory schedulerFactory, String schedulerName) {
+ return scheduler;
+ }
+ };
+ schedulerFactoryBean.setJobFactory(jobFactory);
+ schedulerFactoryBean.setJobDetails(new JobDetail[] {jobDetail0, jobDetail1});
+ schedulerFactoryBean.setTriggers(new Trigger[] {trigger0, trigger1});
+ try {
+ schedulerFactoryBean.afterPropertiesSet();
+ }
+ finally {
+ schedulerFactoryBean.destroy();
+ }
+
+ schedulerControl.verify();
+ }
+
+ public void testSchedulerFactoryBeanWithApplicationContext() throws Exception {
+ TestBean tb = new TestBean("tb", 99);
+ StaticApplicationContext ac = new StaticApplicationContext();
+
+ MockControl schedulerControl = MockControl.createControl(Scheduler.class);
+ final Scheduler scheduler = (Scheduler) schedulerControl.getMock();
+ SchedulerContext schedulerContext = new SchedulerContext();
+ scheduler.getContext();
+ schedulerControl.setReturnValue(schedulerContext, 4);
+ scheduler.start();
+ schedulerControl.setVoidCallable();
+ scheduler.shutdown(false);
+ schedulerControl.setVoidCallable();
+ schedulerControl.replay();
+
+ SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean() {
+ protected Scheduler createScheduler(SchedulerFactory schedulerFactory, String schedulerName) {
+ return scheduler;
+ }
+ };
+ schedulerFactoryBean.setJobFactory(null);
+ Map schedulerContextMap = new HashMap();
+ schedulerContextMap.put("testBean", tb);
+ schedulerFactoryBean.setSchedulerContextAsMap(schedulerContextMap);
+ schedulerFactoryBean.setApplicationContext(ac);
+ schedulerFactoryBean.setApplicationContextSchedulerContextKey("appCtx");
+ try {
+ schedulerFactoryBean.afterPropertiesSet();
+ Scheduler returnedScheduler = (Scheduler) schedulerFactoryBean.getObject();
+ assertEquals(tb, returnedScheduler.getContext().get("testBean"));
+ assertEquals(ac, returnedScheduler.getContext().get("appCtx"));
+ }
+ finally {
+ schedulerFactoryBean.destroy();
+ }
+
+ schedulerControl.verify();
+ }
+
+ public void testJobDetailBeanWithApplicationContext() throws Exception {
+ TestBean tb = new TestBean("tb", 99);
+ StaticApplicationContext ac = new StaticApplicationContext();
+
+ JobDetailBean jobDetail = new JobDetailBean();
+ jobDetail.setJobClass(Job.class);
+ jobDetail.setBeanName("myJob0");
+ Map jobData = new HashMap();
+ jobData.put("testBean", tb);
+ jobDetail.setJobDataAsMap(jobData);
+ jobDetail.setApplicationContext(ac);
+ jobDetail.setApplicationContextJobDataKey("appCtx");
+ jobDetail.afterPropertiesSet();
+
+ assertEquals(tb, jobDetail.getJobDataMap().get("testBean"));
+ assertEquals(ac, jobDetail.getJobDataMap().get("appCtx"));
+ }
+
+ public void testMethodInvokingJobDetailFactoryBeanWithListenerNames() throws Exception {
+ TestMethodInvokingTask task = new TestMethodInvokingTask();
+ MethodInvokingJobDetailFactoryBean mijdfb = new MethodInvokingJobDetailFactoryBean();
+ String[] names = new String[] {"test1", "test2"};
+ mijdfb.setName("myJob1");
+ mijdfb.setGroup(Scheduler.DEFAULT_GROUP);
+ mijdfb.setTargetObject(task);
+ mijdfb.setTargetMethod("doSomething");
+ mijdfb.setJobListenerNames(names);
+ mijdfb.afterPropertiesSet();
+ JobDetail jobDetail = (JobDetail) mijdfb.getObject();
+ List result = Arrays.asList(jobDetail.getJobListenerNames());
+ assertEquals(Arrays.asList(names), result);
+ }
+
+ public void testJobDetailBeanWithListenerNames() {
+ JobDetailBean jobDetail = new JobDetailBean();
+ String[] names = new String[] {"test1", "test2"};
+ jobDetail.setJobListenerNames(names);
+ List result = Arrays.asList(jobDetail.getJobListenerNames());
+ assertEquals(Arrays.asList(names), result);
+ }
+
+ public void testCronTriggerBeanWithListenerNames() {
+ CronTriggerBean trigger = new CronTriggerBean();
+ String[] names = new String[] {"test1", "test2"};
+ trigger.setTriggerListenerNames(names);
+ List result = Arrays.asList(trigger.getTriggerListenerNames());
+ assertEquals(Arrays.asList(names), result);
+ }
+
+ public void testSimpleTriggerBeanWithListenerNames() {
+ SimpleTriggerBean trigger = new SimpleTriggerBean();
+ String[] names = new String[] {"test1", "test2"};
+ trigger.setTriggerListenerNames(names);
+ List result = Arrays.asList(trigger.getTriggerListenerNames());
+ assertEquals(Arrays.asList(names), result);
+ }
+
+ public void testSchedulerWithTaskExecutor() throws Exception {
+ CountingTaskExecutor taskExecutor = new CountingTaskExecutor();
+ DummyJob.count = 0;
+
+ JobDetail jobDetail = new JobDetail();
+ jobDetail.setJobClass(DummyJob.class);
+ jobDetail.setName("myJob");
+
+ SimpleTriggerBean trigger = new SimpleTriggerBean();
+ trigger.setName("myTrigger");
+ trigger.setJobDetail(jobDetail);
+ trigger.setStartDelay(1);
+ trigger.setRepeatInterval(500);
+ trigger.setRepeatCount(1);
+ trigger.afterPropertiesSet();
+
+ SchedulerFactoryBean bean = new SchedulerFactoryBean();
+ bean.setTaskExecutor(taskExecutor);
+ bean.setTriggers(new Trigger[] {trigger});
+ bean.setJobDetails(new JobDetail[] {jobDetail});
+ bean.afterPropertiesSet();
+
+ Thread.sleep(500);
+ assertTrue(DummyJob.count > 0);
+ assertEquals(DummyJob.count, taskExecutor.count);
+
+ bean.destroy();
+ }
+
+ public void testSchedulerWithRunnable() throws Exception {
+ DummyRunnable.count = 0;
+
+ JobDetail jobDetail = new JobDetailBean();
+ jobDetail.setJobClass(DummyRunnable.class);
+ jobDetail.setName("myJob");
+
+ SimpleTriggerBean trigger = new SimpleTriggerBean();
+ trigger.setName("myTrigger");
+ trigger.setJobDetail(jobDetail);
+ trigger.setStartDelay(1);
+ trigger.setRepeatInterval(500);
+ trigger.setRepeatCount(1);
+ trigger.afterPropertiesSet();
+
+ SchedulerFactoryBean bean = new SchedulerFactoryBean();
+ bean.setTriggers(new Trigger[] {trigger});
+ bean.setJobDetails(new JobDetail[] {jobDetail});
+ bean.afterPropertiesSet();
+
+ Thread.sleep(500);
+ assertTrue(DummyRunnable.count > 0);
+
+ bean.destroy();
+ }
+
+ public void testSchedulerWithQuartzJobBean() throws Exception {
+ DummyJob.param = 0;
+ DummyJob.count = 0;
+
+ JobDetail jobDetail = new JobDetail();
+ jobDetail.setJobClass(DummyJobBean.class);
+ jobDetail.setName("myJob");
+ jobDetail.getJobDataMap().put("param", "10");
+
+ SimpleTriggerBean trigger = new SimpleTriggerBean();
+ trigger.setName("myTrigger");
+ trigger.setJobDetail(jobDetail);
+ trigger.setStartDelay(1);
+ trigger.setRepeatInterval(500);
+ trigger.setRepeatCount(1);
+ trigger.afterPropertiesSet();
+
+ SchedulerFactoryBean bean = new SchedulerFactoryBean();
+ bean.setTriggers(new Trigger[] {trigger});
+ bean.setJobDetails(new JobDetail[] {jobDetail});
+ bean.afterPropertiesSet();
+
+ Thread.sleep(500);
+ assertEquals(10, DummyJobBean.param);
+ assertTrue(DummyJobBean.count > 0);
+
+ bean.destroy();
+ }
+
+ public void testSchedulerWithSpringBeanJobFactory() throws Exception {
+ DummyJob.param = 0;
+ DummyJob.count = 0;
+
+ JobDetail jobDetail = new JobDetail();
+ jobDetail.setJobClass(DummyJob.class);
+ jobDetail.setName("myJob");
+ jobDetail.getJobDataMap().put("param", "10");
+ jobDetail.getJobDataMap().put("ignoredParam", "10");
+
+ SimpleTriggerBean trigger = new SimpleTriggerBean();
+ trigger.setName("myTrigger");
+ trigger.setJobDetail(jobDetail);
+ trigger.setStartDelay(1);
+ trigger.setRepeatInterval(500);
+ trigger.setRepeatCount(1);
+ trigger.afterPropertiesSet();
+
+ SchedulerFactoryBean bean = new SchedulerFactoryBean();
+ bean.setJobFactory(new SpringBeanJobFactory());
+ bean.setTriggers(new Trigger[] {trigger});
+ bean.setJobDetails(new JobDetail[] {jobDetail});
+ bean.afterPropertiesSet();
+
+ Thread.sleep(500);
+ assertEquals(10, DummyJob.param);
+ assertTrue(DummyJob.count > 0);
+
+ bean.destroy();
+ }
+
+ public void testSchedulerWithSpringBeanJobFactoryAndParamMismatchNotIgnored() throws Exception {
+ DummyJob.param = 0;
+ DummyJob.count = 0;
+
+ JobDetail jobDetail = new JobDetail();
+ jobDetail.setJobClass(DummyJob.class);
+ jobDetail.setName("myJob");
+ jobDetail.getJobDataMap().put("para", "10");
+ jobDetail.getJobDataMap().put("ignoredParam", "10");
+
+ SimpleTriggerBean trigger = new SimpleTriggerBean();
+ trigger.setName("myTrigger");
+ trigger.setJobDetail(jobDetail);
+ trigger.setStartDelay(1);
+ trigger.setRepeatInterval(500);
+ trigger.setRepeatCount(1);
+ trigger.afterPropertiesSet();
+
+ SchedulerFactoryBean bean = new SchedulerFactoryBean();
+ SpringBeanJobFactory jobFactory = new SpringBeanJobFactory();
+ jobFactory.setIgnoredUnknownProperties(new String[] {"ignoredParam"});
+ bean.setJobFactory(jobFactory);
+ bean.setTriggers(new Trigger[] {trigger});
+ bean.setJobDetails(new JobDetail[] {jobDetail});
+ bean.afterPropertiesSet();
+
+ Thread.sleep(500);
+ assertEquals(0, DummyJob.param);
+ assertTrue(DummyJob.count == 0);
+
+ bean.destroy();
+ }
+
+ public void testSchedulerWithSpringBeanJobFactoryAndRunnable() throws Exception {
+ DummyRunnable.param = 0;
+ DummyRunnable.count = 0;
+
+ JobDetail jobDetail = new JobDetailBean();
+ jobDetail.setJobClass(DummyRunnable.class);
+ jobDetail.setName("myJob");
+ jobDetail.getJobDataMap().put("param", "10");
+
+ SimpleTriggerBean trigger = new SimpleTriggerBean();
+ trigger.setName("myTrigger");
+ trigger.setJobDetail(jobDetail);
+ trigger.setStartDelay(1);
+ trigger.setRepeatInterval(500);
+ trigger.setRepeatCount(1);
+ trigger.afterPropertiesSet();
+
+ SchedulerFactoryBean bean = new SchedulerFactoryBean();
+ bean.setJobFactory(new SpringBeanJobFactory());
+ bean.setTriggers(new Trigger[] {trigger});
+ bean.setJobDetails(new JobDetail[] {jobDetail});
+ bean.afterPropertiesSet();
+
+ Thread.sleep(500);
+ assertEquals(10, DummyRunnable.param);
+ assertTrue(DummyRunnable.count > 0);
+
+ bean.destroy();
+ }
+
+ public void testSchedulerWithSpringBeanJobFactoryAndQuartzJobBean() throws Exception {
+ DummyJobBean.param = 0;
+ DummyJobBean.count = 0;
+
+ JobDetail jobDetail = new JobDetail();
+ jobDetail.setJobClass(DummyJobBean.class);
+ jobDetail.setName("myJob");
+ jobDetail.getJobDataMap().put("param", "10");
+
+ SimpleTriggerBean trigger = new SimpleTriggerBean();
+ trigger.setName("myTrigger");
+ trigger.setJobDetail(jobDetail);
+ trigger.setStartDelay(1);
+ trigger.setRepeatInterval(500);
+ trigger.setRepeatCount(1);
+ trigger.afterPropertiesSet();
+
+ SchedulerFactoryBean bean = new SchedulerFactoryBean();
+ bean.setJobFactory(new SpringBeanJobFactory());
+ bean.setTriggers(new Trigger[] {trigger});
+ bean.setJobDetails(new JobDetail[] {jobDetail});
+ bean.afterPropertiesSet();
+
+ Thread.sleep(500);
+ assertEquals(10, DummyJobBean.param);
+ assertTrue(DummyJobBean.count > 0);
+
+ bean.destroy();
+ }
+
+ public void testSchedulerWithSpringBeanJobFactoryAndJobSchedulingData() throws Exception {
+ DummyJob.param = 0;
+ DummyJob.count = 0;
+
+ SchedulerFactoryBean bean = new SchedulerFactoryBean();
+ bean.setJobFactory(new SpringBeanJobFactory());
+ bean.setJobSchedulingDataLocation("org/springframework/scheduling/quartz/job-scheduling-data.xml");
+ bean.setResourceLoader(new FileSystemResourceLoader());
+ bean.afterPropertiesSet();
+
+ Thread.sleep(500);
+ assertEquals(10, DummyJob.param);
+ assertTrue(DummyJob.count > 0);
+
+ bean.destroy();
+ }
+
+ /**
+ * Tests the creation of multiple schedulers (SPR-772)
+ */
+ public void testMultipleSchedulers() throws Exception {
+ ClassPathXmlApplicationContext ctx =
+ new ClassPathXmlApplicationContext("/org/springframework/scheduling/quartz/multipleSchedulers.xml");
+ try {
+ Scheduler scheduler1 = (Scheduler) ctx.getBean("scheduler1");
+ Scheduler scheduler2 = (Scheduler) ctx.getBean("scheduler2");
+ assertNotSame(scheduler1, scheduler2);
+ assertEquals("quartz1", scheduler1.getSchedulerName());
+ assertEquals("quartz2", scheduler2.getSchedulerName());
+ }
+ finally {
+ ctx.close();
+ }
+ }
+
+ public void testWithTwoAnonymousMethodInvokingJobDetailFactoryBeans() throws InterruptedException {
+ ClassPathXmlApplicationContext ctx =
+ new ClassPathXmlApplicationContext("/org/springframework/scheduling/quartz/multipleAnonymousMethodInvokingJobDetailFB.xml");
+ Thread.sleep(3000);
+ try {
+ QuartzTestBean exportService = (QuartzTestBean) ctx.getBean("exportService");
+ QuartzTestBean importService = (QuartzTestBean) ctx.getBean("importService");
+
+ assertEquals("doImport called exportService", 0, exportService.getImportCount());
+ assertEquals("doExport not called on exportService", 2, exportService.getExportCount());
+ assertEquals("doImport not called on importService", 2, importService.getImportCount());
+ assertEquals("doExport called on importService", 0, importService.getExportCount());
+ }
+ finally {
+ ctx.close();
+ }
+ }
+
+ public void testSchedulerAccessorBean() throws InterruptedException {
+ ClassPathXmlApplicationContext ctx =
+ new ClassPathXmlApplicationContext("/org/springframework/scheduling/quartz/schedulerAccessorBean.xml");
+ Thread.sleep(3000);
+ try {
+ QuartzTestBean exportService = (QuartzTestBean) ctx.getBean("exportService");
+ QuartzTestBean importService = (QuartzTestBean) ctx.getBean("importService");
+
+ assertEquals("doImport called exportService", 0, exportService.getImportCount());
+ assertEquals("doExport not called on exportService", 2, exportService.getExportCount());
+ assertEquals("doImport not called on importService", 2, importService.getImportCount());
+ assertEquals("doExport called on importService", 0, importService.getExportCount());
+ }
+ finally {
+ ctx.close();
+ }
+ }
+
+ public void testSchedulerRepositoryExposure() throws InterruptedException {
+ ClassPathXmlApplicationContext ctx =
+ new ClassPathXmlApplicationContext("/org/springframework/scheduling/quartz/schedulerRepositoryExposure.xml");
+ assertSame(SchedulerRepository.getInstance().lookup("myScheduler"), ctx.getBean("scheduler"));
+ ctx.close();
+ }
+
+
+ private static class TestSchedulerListener implements SchedulerListener {
+
+ public void jobScheduled(Trigger trigger) {
+ }
+
+ public void jobUnscheduled(String triggerName, String triggerGroup) {
+ }
+
+ public void triggerFinalized(Trigger trigger) {
+ }
+
+ public void triggersPaused(String triggerName, String triggerGroup) {
+ }
+
+ public void triggersResumed(String triggerName, String triggerGroup) {
+ }
+
+ public void jobsPaused(String jobName, String jobGroup) {
+ }
+
+ public void jobsResumed(String jobName, String jobGroup) {
+ }
+
+ public void schedulerError(String msg, SchedulerException cause) {
+ }
+
+ public void schedulerShutdown() {
+ }
+ }
+
+
+ private static class TestJobListener implements JobListener {
+
+ public String getName() {
+ return null;
+ }
+
+ public void jobToBeExecuted(JobExecutionContext context) {
+ }
+
+ public void jobExecutionVetoed(JobExecutionContext context) {
+ }
+
+ public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
+ }
+ }
+
+
+ private static class TestTriggerListener implements TriggerListener {
+
+ public String getName() {
+ return null;
+ }
+
+ public void triggerFired(Trigger trigger, JobExecutionContext context) {
+ }
+
+ public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {
+ return false;
+ }
+
+ public void triggerMisfired(Trigger trigger) {
+ }
+
+ public void triggerComplete(Trigger trigger, JobExecutionContext context, int triggerInstructionCode) {
+ }
+ }
+
+
+ public static class CountingTaskExecutor implements TaskExecutor {
+
+ private int count;
+
+ public void execute(Runnable task) {
+ this.count++;
+ task.run();
+ }
+ }
+
+
+ public static class DummyJob implements Job {
+
+ private static int param;
+
+ private static int count;
+
+ public void setParam(int value) {
+ if (param > 0) {
+ throw new IllegalStateException("Param already set");
+ }
+ param = value;
+ }
+
+ public synchronized void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
+ count++;
+ }
+ }
+
+
+ public static class DummyJobBean extends QuartzJobBean {
+
+ private static int param;
+
+ private static int count;
+
+ public void setParam(int value) {
+ if (param > 0) {
+ throw new IllegalStateException("Param already set");
+ }
+ param = value;
+ }
+
+ protected synchronized void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
+ count++;
+ }
+ }
+
+
+ public static class DummyRunnable implements Runnable {
+
+ private static int param;
+
+ private static int count;
+
+ public void setParam(int value) {
+ if (param > 0) {
+ throw new IllegalStateException("Param already set");
+ }
+ param = value;
+ }
+
+ public void run() {
+ count++;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scheduling/quartz/QuartzTestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/quartz/QuartzTestBean.java
new file mode 100644
index 00000000000..8890e39ed08
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/quartz/QuartzTestBean.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.scheduling.quartz;
+
+/**
+ * @author Rob Harrop
+ */
+public class QuartzTestBean {
+
+ private int importCount;
+
+ private int exportCount;
+
+
+ public void doImport() {
+ ++importCount;
+ }
+
+ public void doExport() {
+ ++exportCount;
+ }
+
+ public int getImportCount() {
+ return importCount;
+ }
+
+ public int getExportCount() {
+ return exportCount;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scheduling/quartz/job-scheduling-data.xml b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/quartz/job-scheduling-data.xml
new file mode 100644
index 00000000000..d9200432831
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/quartz/job-scheduling-data.xml
@@ -0,0 +1,29 @@
+
+
+
+
+ myJob
+ myGroup
+ org.springframework.scheduling.quartz.QuartzSupportTests$DummyJob
+
+
+ param
+ 10
+
+
+
+
+
+ myTrigger
+ myGroup
+ 1
+ 500
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scheduling/quartz/multipleAnonymousMethodInvokingJobDetailFB.xml b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/quartz/multipleAnonymousMethodInvokingJobDetailFB.xml
new file mode 100644
index 00000000000..40f5a8d7626
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/quartz/multipleAnonymousMethodInvokingJobDetailFB.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scheduling/quartz/multipleSchedulers.xml b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/quartz/multipleSchedulers.xml
new file mode 100644
index 00000000000..02d8f3668b6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/quartz/multipleSchedulers.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scheduling/quartz/schedulerAccessorBean.xml b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/quartz/schedulerAccessorBean.xml
new file mode 100644
index 00000000000..0c4c9578b2d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/quartz/schedulerAccessorBean.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scheduling/quartz/schedulerRepositoryExposure.xml b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/quartz/schedulerRepositoryExposure.xml
new file mode 100644
index 00000000000..46410a7cd31
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/quartz/schedulerRepositoryExposure.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scheduling/timer/TimerSupportTests.java b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/timer/TimerSupportTests.java
new file mode 100644
index 00000000000..620c737c860
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/timer/TimerSupportTests.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.scheduling.timer;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import junit.framework.TestCase;
+
+import org.springframework.scheduling.TestMethodInvokingTask;
+
+/**
+ * @author Juergen Hoeller
+ * @since 20.02.2004
+ */
+public class TimerSupportTests extends TestCase {
+
+ public void testTimerFactoryBean() throws Exception {
+ final TestTimerTask timerTask0 = new TestTimerTask();
+
+ TestMethodInvokingTask task1 = new TestMethodInvokingTask();
+ MethodInvokingTimerTaskFactoryBean mittfb = new MethodInvokingTimerTaskFactoryBean();
+ mittfb.setTargetObject(task1);
+ mittfb.setTargetMethod("doSomething");
+ mittfb.afterPropertiesSet();
+ final TimerTask timerTask1 = (TimerTask) mittfb.getObject();
+
+ final TestRunnable timerTask2 = new TestRunnable();
+
+ ScheduledTimerTask[] tasks = new ScheduledTimerTask[3];
+ tasks[0] = new ScheduledTimerTask(timerTask0, 0, 10, false);
+ tasks[1] = new ScheduledTimerTask(timerTask1, 10, 20, true);
+ tasks[2] = new ScheduledTimerTask(timerTask2, 20);
+
+ final List success = new ArrayList(3);
+ final Timer timer = new Timer(true) {
+ public void schedule(TimerTask task, long delay, long period) {
+ if (task == timerTask0 && delay == 0 && period == 10) {
+ success.add(Boolean.TRUE);
+ }
+ }
+ public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
+ if (task == timerTask1 && delay == 10 && period == 20) {
+ success.add(Boolean.TRUE);
+ }
+ }
+ public void schedule(TimerTask task, long delay) {
+ if (task instanceof DelegatingTimerTask && delay == 20) {
+ success.add(Boolean.TRUE);
+ }
+ }
+ public void cancel() {
+ success.add(Boolean.TRUE);
+ }
+ };
+
+ TimerFactoryBean timerFactoryBean = new TimerFactoryBean() {
+ protected Timer createTimer(String name, boolean daemon) {
+ return timer;
+ }
+ };
+ try {
+ timerFactoryBean.setScheduledTimerTasks(tasks);
+ timerFactoryBean.afterPropertiesSet();
+ assertTrue(timerFactoryBean.getObject() instanceof Timer);
+ timerTask0.run();
+ timerTask1.run();
+ timerTask2.run();
+ }
+ finally {
+ timerFactoryBean.destroy();
+ }
+
+ assertTrue("Correct Timer invocations", success.size() == 4);
+ assertTrue("TimerTask0 works", timerTask0.counter == 1);
+ assertTrue("TimerTask1 works", task1.counter == 1);
+ assertTrue("TimerTask2 works", timerTask2.counter == 1);
+ }
+
+ public void testPlainTimerFactoryBean() {
+ TimerFactoryBean tfb = new TimerFactoryBean();
+ tfb.afterPropertiesSet();
+ tfb.destroy();
+ }
+
+
+ private static class TestTimerTask extends TimerTask {
+
+ private int counter = 0;
+
+ public void run() {
+ counter++;
+ }
+ }
+
+
+ private static class TestRunnable implements Runnable {
+
+ private int counter = 0;
+
+ public void run() {
+ counter++;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scheduling/timer/TimerTaskExecutorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/timer/TimerTaskExecutorTests.java
new file mode 100644
index 00000000000..db011ede1f7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scheduling/timer/TimerTaskExecutorTests.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.scheduling.timer;
+
+import junit.framework.TestCase;
+import org.springframework.test.AssertThrows;
+
+import java.util.Timer;
+
+/**
+ * Unit tests for the {@link TimerTaskExecutor} class.
+ *
+ * @author Rick Evans
+ */
+public final class TimerTaskExecutorTests extends TestCase {
+
+ public void testExecuteChokesWithNullTimer() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ TimerTaskExecutor executor = new TimerTaskExecutor();
+ executor.execute(new NoOpRunnable());
+ }
+ }.runTest();
+ }
+
+ public void testExecuteChokesWithNullTask() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ TimerTaskExecutor executor = new TimerTaskExecutor(new Timer());
+ executor.execute(null);
+ }
+ }.runTest();
+ }
+
+ public void testExecuteChokesWithNegativeDelay() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ TimerTaskExecutor executor = new TimerTaskExecutor(new Timer());
+ executor.setDelay(-10);
+ executor.execute(new NoOpRunnable());
+ }
+ }.runTest();
+ }
+
+ public void testExecuteReallyDoesScheduleTheSuppliedTask() throws Exception {
+ final Object monitor = new Object();
+
+ RunAwareRunnable task = new RunAwareRunnable(monitor);
+
+ TimerTaskExecutor executor = new TimerTaskExecutor(new Timer());
+ executor.execute(task);
+
+ synchronized (monitor) {
+ monitor.wait(5000);
+ }
+
+ assertTrue("Supplied task (a Runnable) is not being invoked.", task.isRunWasCalled());
+ }
+
+ public void testCtorWithNullTimer() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new TimerTaskExecutor(null);
+ }
+ }.runTest();
+ }
+
+ public void testCreateTimerMethodIsCalledIfNoTimerIsExplicitlySupplied() throws Exception {
+ CreationAwareTimerTaskExecutor executor = new CreationAwareTimerTaskExecutor();
+ executor.afterPropertiesSet();
+ assertTrue("If no Timer is set explicitly, then the protected createTimer() " +
+ "method must be called to create the Timer (it obviously isn't being called).",
+ executor.isCreateTimerWasCalled());
+ }
+
+ public void testCreateTimerMethodIsNotCalledIfTimerIsExplicitlySupplied() throws Exception {
+ CreationAwareTimerTaskExecutor executor = new CreationAwareTimerTaskExecutor();
+ executor.setTimer(new Timer());
+ executor.afterPropertiesSet();
+ assertFalse("If a Timer is set explicitly, then the protected createTimer() " +
+ "method must not be called to create the Timer (it obviously is being called, in error).",
+ executor.isCreateTimerWasCalled());
+ }
+
+ public void testThatTheDestroyCallbackCancelsTheTimerIfNoTimerIsExplicitlySupplied() throws Exception {
+
+ final CancelAwareTimer timer = new CancelAwareTimer();
+
+ TimerTaskExecutor executor = new TimerTaskExecutor() {
+
+ protected Timer createTimer() {
+ return timer;
+ }
+ };
+ executor.afterPropertiesSet();
+ executor.destroy();
+ assertTrue("When the Timer used is created by the TimerTaskExecutor because " +
+ "no Timer was set explicitly, then the destroy() callback must cancel() said Timer (it obviously isn't doing this).",
+ timer.isCancelWasCalled());
+ }
+
+ public void testThatTheDestroyCallbackDoesNotCancelTheTimerIfTheTimerWasSuppliedExplictly() throws Exception {
+ TimerTaskExecutor executor = new TimerTaskExecutor();
+ CancelAwareTimer timer = new CancelAwareTimer();
+ executor.setTimer(timer);
+ executor.afterPropertiesSet();
+ executor.destroy();
+ assertFalse("When the Timer used is not created by the TimerTaskExecutor because " +
+ "it Timer was set explicitly, then the destroy() callback must NOT cancel() said Timer (it obviously is, in error).",
+ timer.isCancelWasCalled());
+ }
+
+
+ private final static class CreationAwareTimerTaskExecutor extends TimerTaskExecutor {
+
+ private boolean createTimerWasCalled = false;
+
+
+ public boolean isCreateTimerWasCalled() {
+ return this.createTimerWasCalled;
+ }
+
+ protected Timer createTimer() {
+ this.createTimerWasCalled = true;
+ return super.createTimer();
+ }
+
+ }
+
+ private static class CancelAwareTimer extends Timer {
+
+ private boolean cancelWasCalled;
+
+
+ public boolean isCancelWasCalled() {
+ return this.cancelWasCalled;
+ }
+
+
+ public void cancel() {
+ this.cancelWasCalled = true;
+ super.cancel();
+ }
+ }
+
+ private static class RunAwareRunnable implements Runnable {
+ private boolean runWasCalled;
+ private final Object monitor;
+
+ public RunAwareRunnable(Object monitor) {
+ this.monitor = monitor;
+ }
+
+
+ public boolean isRunWasCalled() {
+ return this.runWasCalled;
+ }
+
+
+ public void run() {
+ this.runWasCalled = true;
+ synchronized (monitor) {
+ monitor.notifyAll();
+ }
+ }
+ }
+
+ private static final class NoOpRunnable implements Runnable {
+
+ public void run() {
+ // explicit no-op
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/Calculator.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/Calculator.java
new file mode 100644
index 00000000000..a2923db8214
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/Calculator.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.scripting;
+
+/**
+ * @author Rob Harrop
+ */
+public interface Calculator {
+
+ int add(int x, int y);
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/CallCounter.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/CallCounter.java
new file mode 100644
index 00000000000..ee21c8c2e78
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/CallCounter.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.scripting;
+
+/**
+ * @author Juergen Hoeller
+ */
+public interface CallCounter {
+
+ void before();
+
+ int getCalls();
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/ConfigurableMessenger.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/ConfigurableMessenger.java
new file mode 100644
index 00000000000..bf7b4656455
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/ConfigurableMessenger.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.scripting;
+
+/**
+ * @author Juergen Hoeller
+ */
+public interface ConfigurableMessenger extends Messenger {
+
+ void setMessage(String message);
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/ContextScriptBean.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/ContextScriptBean.java
new file mode 100644
index 00000000000..052209d92f8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/ContextScriptBean.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.scripting;
+
+import org.springframework.beans.TestBean;
+import org.springframework.context.ApplicationContext;
+
+/**
+ * @author Juergen Hoeller
+ * @since 08.08.2006
+ */
+public interface ContextScriptBean extends ScriptBean {
+
+ TestBean getTestBean();
+
+ ApplicationContext getApplicationContext();
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/Messenger.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/Messenger.java
new file mode 100644
index 00000000000..7e1f3aff64a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/Messenger.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.scripting;
+
+/**
+ * @author Rob Harrop
+ */
+public interface Messenger {
+
+ String getMessage();
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/MessengerScrambler.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/MessengerScrambler.java
new file mode 100644
index 00000000000..cf8253f91b3
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/MessengerScrambler.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.scripting;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+
+/**
+ * Twee advice that 'scrambles' the return value
+ * of a {@link Messenger} invocation.
+ *
+ * @author Rick Evans
+ */
+public final class MessengerScrambler {
+
+ public String scramble(ProceedingJoinPoint pjp) throws Throwable {
+ String message = (String) pjp.proceed();
+ return new StringBuffer(message).reverse().toString();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/ScriptBean.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/ScriptBean.java
new file mode 100644
index 00000000000..2630e5b3a9c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/ScriptBean.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.scripting;
+
+/**
+ * Simple interface used in testing the scripted beans support.
+ *
+ * @author Rick Evans
+ */
+public interface ScriptBean {
+
+ String getName();
+
+ void setName(String name);
+
+ int getAge();
+
+ void setAge(int age);
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/TestBeanAwareMessenger.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/TestBeanAwareMessenger.java
new file mode 100644
index 00000000000..ddc139475cc
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/TestBeanAwareMessenger.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.scripting;
+
+import org.springframework.beans.TestBean;
+
+/**
+ * @author Juergen Hoeller
+ */
+public interface TestBeanAwareMessenger extends ConfigurableMessenger {
+
+ TestBean getTestBean();
+
+ void setTestBean(TestBean testBean);
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/Broken.bsh b/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/Broken.bsh
new file mode 100644
index 00000000000..5b1af163a47
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/Broken.bsh
@@ -0,0 +1 @@
+one sure is the loneliest number... that i'll ever know
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/BshScriptFactoryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/BshScriptFactoryTests.java
new file mode 100644
index 00000000000..090ef9fde41
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/BshScriptFactoryTests.java
@@ -0,0 +1,306 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.scripting.bsh;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.aop.support.AopUtils;
+import org.springframework.aop.target.dynamic.Refreshable;
+import org.springframework.beans.TestBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.core.NestedRuntimeException;
+import org.springframework.scripting.Calculator;
+import org.springframework.scripting.ConfigurableMessenger;
+import org.springframework.scripting.Messenger;
+import org.springframework.scripting.ScriptCompilationException;
+import org.springframework.scripting.ScriptSource;
+import org.springframework.scripting.TestBeanAwareMessenger;
+import org.springframework.scripting.support.ScriptFactoryPostProcessor;
+
+/**
+ * @author Rob Harrop
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class BshScriptFactoryTests extends TestCase {
+
+ public void testStaticScript() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("bshContext.xml", getClass());
+
+ assertTrue(Arrays.asList(ctx.getBeanNamesForType(Calculator.class)).contains("calculator"));
+ assertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.class)).contains("messenger"));
+
+ Calculator calc = (Calculator) ctx.getBean("calculator");
+ Messenger messenger = (Messenger) ctx.getBean("messenger");
+
+ assertFalse("Scripted object should not be instance of Refreshable", calc instanceof Refreshable);
+ assertFalse("Scripted object should not be instance of Refreshable", messenger instanceof Refreshable);
+
+ assertEquals(calc, calc);
+ assertEquals(messenger, messenger);
+ assertTrue(!messenger.equals(calc));
+ assertTrue(messenger.hashCode() != calc.hashCode());
+ assertTrue(!messenger.toString().equals(calc.toString()));
+
+ assertEquals(5, calc.add(2, 3));
+
+ String desiredMessage = "Hello World!";
+ assertEquals("Message is incorrect", desiredMessage, messenger.getMessage());
+
+ assertTrue(ctx.getBeansOfType(Calculator.class).values().contains(calc));
+ assertTrue(ctx.getBeansOfType(Messenger.class).values().contains(messenger));
+ }
+
+ public void testStaticScriptWithNullReturnValue() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("bshContext.xml", getClass());
+ assertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.class)).contains("messengerWithConfig"));
+
+ ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerWithConfig");
+ messenger.setMessage(null);
+ assertNull(messenger.getMessage());
+ assertTrue(ctx.getBeansOfType(Messenger.class).values().contains(messenger));
+ }
+
+ public void testStaticScriptWithTwoInterfacesSpecified() throws Exception {
+ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("bshContext.xml", getClass());
+ assertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.class)).contains("messengerWithConfigExtra"));
+
+ ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerWithConfigExtra");
+ messenger.setMessage(null);
+ assertNull(messenger.getMessage());
+ assertTrue(ctx.getBeansOfType(Messenger.class).values().contains(messenger));
+
+ ctx.close();
+ assertNull(messenger.getMessage());
+ }
+
+ public void testStaticWithScriptReturningInstance() throws Exception {
+ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("bshContext.xml", getClass());
+ assertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.class)).contains("messengerInstance"));
+
+ Messenger messenger = (Messenger) ctx.getBean("messengerInstance");
+ String desiredMessage = "Hello World!";
+ assertEquals("Message is incorrect", desiredMessage, messenger.getMessage());
+ assertTrue(ctx.getBeansOfType(Messenger.class).values().contains(messenger));
+
+ ctx.close();
+ assertNull(messenger.getMessage());
+ }
+
+ public void testStaticScriptImplementingInterface() throws Exception {
+ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("bshContext.xml", getClass());
+ assertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.class)).contains("messengerImpl"));
+
+ Messenger messenger = (Messenger) ctx.getBean("messengerImpl");
+ String desiredMessage = "Hello World!";
+ assertEquals("Message is incorrect", desiredMessage, messenger.getMessage());
+ assertTrue(ctx.getBeansOfType(Messenger.class).values().contains(messenger));
+
+ ctx.close();
+ assertNull(messenger.getMessage());
+ }
+
+ public void testStaticPrototypeScript() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("bshContext.xml", getClass());
+ ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
+ ConfigurableMessenger messenger2 = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
+
+ assertFalse("Shouldn't get proxy when refresh is disabled", AopUtils.isAopProxy(messenger));
+ assertFalse("Scripted object should not be instance of Refreshable", messenger instanceof Refreshable);
+
+ assertNotSame(messenger, messenger2);
+ assertSame(messenger.getClass(), messenger2.getClass());
+ assertEquals("Hello World!", messenger.getMessage());
+ assertEquals("Hello World!", messenger2.getMessage());
+ messenger.setMessage("Bye World!");
+ messenger2.setMessage("Byebye World!");
+ assertEquals("Bye World!", messenger.getMessage());
+ assertEquals("Byebye World!", messenger2.getMessage());
+ }
+
+ public void testNonStaticScript() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("bshRefreshableContext.xml", getClass());
+ Messenger messenger = (Messenger) ctx.getBean("messenger");
+
+ assertTrue("Should be a proxy for refreshable scripts", AopUtils.isAopProxy(messenger));
+ assertTrue("Should be an instance of Refreshable", messenger instanceof Refreshable);
+
+ String desiredMessage = "Hello World!";
+ assertEquals("Message is incorrect", desiredMessage, messenger.getMessage());
+
+ Refreshable refreshable = (Refreshable) messenger;
+ refreshable.refresh();
+
+ assertEquals("Message is incorrect after refresh", desiredMessage, messenger.getMessage());
+ assertEquals("Incorrect refresh count", 2, refreshable.getRefreshCount());
+ }
+
+ public void testNonStaticPrototypeScript() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("bshRefreshableContext.xml", getClass());
+ ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
+ ConfigurableMessenger messenger2 = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
+
+ assertTrue("Should be a proxy for refreshable scripts", AopUtils.isAopProxy(messenger));
+ assertTrue("Should be an instance of Refreshable", messenger instanceof Refreshable);
+
+ assertEquals("Hello World!", messenger.getMessage());
+ assertEquals("Hello World!", messenger2.getMessage());
+ messenger.setMessage("Bye World!");
+ messenger2.setMessage("Byebye World!");
+ assertEquals("Bye World!", messenger.getMessage());
+ assertEquals("Byebye World!", messenger2.getMessage());
+
+ Refreshable refreshable = (Refreshable) messenger;
+ refreshable.refresh();
+
+ assertEquals("Hello World!", messenger.getMessage());
+ assertEquals("Byebye World!", messenger2.getMessage());
+ assertEquals("Incorrect refresh count", 2, refreshable.getRefreshCount());
+ }
+
+ public void testScriptCompilationException() throws Exception {
+ try {
+ new ClassPathXmlApplicationContext("org/springframework/scripting/bsh/bshBrokenContext.xml");
+ fail("Must throw exception for broken script file");
+ }
+ catch (NestedRuntimeException ex) {
+ assertTrue(ex.contains(ScriptCompilationException.class));
+ }
+ }
+
+ public void testScriptThatCompilesButIsJustPlainBad() throws Exception {
+ MockControl mock = MockControl.createControl(ScriptSource.class);
+ ScriptSource script = (ScriptSource) mock.getMock();
+ script.getScriptAsString();
+ final String badScript = "String getMessage() { throw new IllegalArgumentException(); }";
+ mock.setReturnValue(badScript);
+ script.isModified();
+ mock.setReturnValue(true);
+ mock.replay();
+ BshScriptFactory factory = new BshScriptFactory(
+ ScriptFactoryPostProcessor.INLINE_SCRIPT_PREFIX + badScript,
+ new Class[] {Messenger.class});
+ try {
+ Messenger messenger = (Messenger) factory.getScriptedObject(script, new Class[]{Messenger.class});
+ messenger.getMessage();
+ fail("Must have thrown a BshScriptUtils.BshExecutionException.");
+ }
+ catch (BshScriptUtils.BshExecutionException expected) {
+ }
+ mock.verify();
+ }
+
+ public void testCtorWithNullScriptSourceLocator() throws Exception {
+ try {
+ new BshScriptFactory(null, new Class[] {Messenger.class});
+ fail("Must have thrown exception by this point.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testCtorWithEmptyScriptSourceLocator() throws Exception {
+ try {
+ new BshScriptFactory("", new Class[] {Messenger.class});
+ fail("Must have thrown exception by this point.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testCtorWithWhitespacedScriptSourceLocator() throws Exception {
+ try {
+ new BshScriptFactory("\n ", new Class[] {Messenger.class});
+ fail("Must have thrown exception by this point.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testResourceScriptFromTag() throws Exception {
+ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("bsh-with-xsd.xml", getClass());
+ TestBean testBean = (TestBean) ctx.getBean("testBean");
+
+ Collection beanNames = Arrays.asList(ctx.getBeanNamesForType(Messenger.class));
+ assertTrue(beanNames.contains("messenger"));
+ assertTrue(beanNames.contains("messengerImpl"));
+ assertTrue(beanNames.contains("messengerInstance"));
+
+ Messenger messenger = (Messenger) ctx.getBean("messenger");
+ assertEquals("Hello World!", messenger.getMessage());
+ assertFalse(messenger instanceof Refreshable);
+
+ Messenger messengerImpl = (Messenger) ctx.getBean("messengerImpl");
+ assertEquals("Hello World!", messengerImpl.getMessage());
+
+ Messenger messengerInstance = (Messenger) ctx.getBean("messengerInstance");
+ assertEquals("Hello World!", messengerInstance.getMessage());
+
+ TestBeanAwareMessenger messengerByType = (TestBeanAwareMessenger) ctx.getBean("messengerByType");
+ assertEquals(testBean, messengerByType.getTestBean());
+
+ TestBeanAwareMessenger messengerByName = (TestBeanAwareMessenger) ctx.getBean("messengerByName");
+ assertEquals(testBean, messengerByName.getTestBean());
+
+ Collection beans = ctx.getBeansOfType(Messenger.class).values();
+ assertTrue(beans.contains(messenger));
+ assertTrue(beans.contains(messengerImpl));
+ assertTrue(beans.contains(messengerInstance));
+ assertTrue(beans.contains(messengerByType));
+ assertTrue(beans.contains(messengerByName));
+
+ ctx.close();
+ assertNull(messenger.getMessage());
+ assertNull(messengerImpl.getMessage());
+ assertNull(messengerInstance.getMessage());
+ }
+
+ public void testPrototypeScriptFromTag() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("bsh-with-xsd.xml", getClass());
+ ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
+ ConfigurableMessenger messenger2 = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
+
+ assertNotSame(messenger, messenger2);
+ assertSame(messenger.getClass(), messenger2.getClass());
+ assertEquals("Hello World!", messenger.getMessage());
+ assertEquals("Hello World!", messenger2.getMessage());
+ messenger.setMessage("Bye World!");
+ messenger2.setMessage("Byebye World!");
+ assertEquals("Bye World!", messenger.getMessage());
+ assertEquals("Byebye World!", messenger2.getMessage());
+ }
+
+ public void testInlineScriptFromTag() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("bsh-with-xsd.xml", getClass());
+ Calculator calculator = (Calculator) ctx.getBean("calculator");
+ assertNotNull(calculator);
+ assertFalse(calculator instanceof Refreshable);
+ }
+
+ public void testRefreshableFromTag() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("bsh-with-xsd.xml", getClass());
+ Messenger messenger = (Messenger) ctx.getBean("refreshableMessenger");
+ assertEquals("Hello World!", messenger.getMessage());
+ assertTrue("Messenger should be Refreshable", messenger instanceof Refreshable);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/Calculator.bsh b/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/Calculator.bsh
new file mode 100644
index 00000000000..cc88f798123
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/Calculator.bsh
@@ -0,0 +1,3 @@
+int add(int x, int y) {
+ return x + y;
+}
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/Messenger.bsh b/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/Messenger.bsh
new file mode 100644
index 00000000000..b15af62a160
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/Messenger.bsh
@@ -0,0 +1,21 @@
+String message;
+
+boolean active;
+
+void init() {
+ active = true;
+}
+
+String getMessage() {
+ if (!active && message != null) throw new java.lang.IllegalStateException();
+ return message;
+}
+
+void setMessage(String aMessage) {
+ message = aMessage;
+}
+
+void destroy() {
+ message = null;
+ active = false;
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/MessengerImpl.bsh b/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/MessengerImpl.bsh
new file mode 100644
index 00000000000..62bfe8b7bf3
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/MessengerImpl.bsh
@@ -0,0 +1,38 @@
+import org.springframework.beans.TestBean;
+import org.springframework.scripting.TestBeanAwareMessenger;
+
+public class MyMessenger implements TestBeanAwareMessenger {
+
+ private String message;
+
+ private TestBean testBean;
+
+ private boolean active;
+
+ public void init() {
+ active = true;
+ }
+
+ public String getMessage() {
+ if (!active && message != null) throw new java.lang.IllegalStateException();
+ return message;
+ }
+
+ public void setMessage(String aMessage) {
+ message = aMessage;
+ }
+
+ public TestBean getTestBean() {
+ return testBean;
+ }
+
+ public void setTestBean(TestBean tb) {
+ testBean = tb;
+ }
+
+ public void destroy() {
+ message = null;
+ active = false;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/MessengerInstance.bsh b/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/MessengerInstance.bsh
new file mode 100644
index 00000000000..e211b1b3f6c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/MessengerInstance.bsh
@@ -0,0 +1,28 @@
+import org.springframework.scripting.Messenger;
+
+public class MyMessenger implements Messenger {
+
+ private String message;
+
+ private boolean active;
+
+ public void init() {
+ active = true;
+ }
+
+ public String getMessage() {
+ if (!active && message != null) throw new java.lang.IllegalStateException();
+ return message;
+ }
+
+ public void setMessage(String aMessage) {
+ message = aMessage;
+ }
+
+ public void destroy() {
+ message = null;
+ active = false;
+ }
+}
+
+return new MyMessenger() ;
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/bsh-with-xsd.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/bsh-with-xsd.xml
new file mode 100644
index 00000000000..09453b3c0da
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/bsh-with-xsd.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ int add(int x, int y) {
+ return x + y;
+ }
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/bshBrokenContext.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/bshBrokenContext.xml
new file mode 100644
index 00000000000..ffa602cfdda
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/bshBrokenContext.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/bshContext.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/bshContext.xml
new file mode 100644
index 00000000000..27f6378f981
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/bshContext.xml
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+ inline:
+int add(int x, int y) {
+ return x + y;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/bshRefreshableContext.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/bshRefreshableContext.xml
new file mode 100644
index 00000000000..a5365960226
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/bsh/bshRefreshableContext.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/config/ITestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/config/ITestBean.java
new file mode 100644
index 00000000000..30ad6626a30
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/config/ITestBean.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.scripting.config;
+
+/**
+ * @author Mark Fisher
+ */
+public interface ITestBean {
+
+ boolean isInitialized();
+
+ boolean isDestroyed();
+
+ ITestBean getOtherBean();
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/config/OtherTestBean.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/config/OtherTestBean.java
new file mode 100644
index 00000000000..4a542c0c6e4
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/config/OtherTestBean.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.scripting.config;
+
+/**
+ * @author Mark Fisher
+ */
+public class OtherTestBean implements ITestBean {
+
+ public ITestBean getOtherBean() {
+ return null;
+ }
+
+ public boolean isInitialized() {
+ return false;
+ }
+
+ public boolean isDestroyed() {
+ return false;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/config/ScriptingDefaultsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/config/ScriptingDefaultsTests.java
new file mode 100644
index 00000000000..28d88820585
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/config/ScriptingDefaultsTests.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.scripting.config;
+
+import java.lang.reflect.Field;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.framework.Advised;
+import org.springframework.aop.target.dynamic.AbstractRefreshableTargetSource;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * @author Mark Fisher
+ */
+public class ScriptingDefaultsTests extends TestCase {
+
+ private static final String CONFIG =
+ "org/springframework/scripting/config/scriptingDefaultsTests.xml";
+
+
+ public void testDefaultRefreshCheckDelay() throws Exception {
+ ApplicationContext context = new ClassPathXmlApplicationContext(CONFIG);
+ Advised advised = (Advised) context.getBean("testBean");
+ AbstractRefreshableTargetSource targetSource =
+ ((AbstractRefreshableTargetSource) advised.getTargetSource());
+ Field field = AbstractRefreshableTargetSource.class.getDeclaredField("refreshCheckDelay");
+ field.setAccessible(true);
+ long delay = ((Long) field.get(targetSource)).longValue();
+ assertEquals(5000L, delay);
+ }
+
+ public void testDefaultInitMethod() {
+ ApplicationContext context = new ClassPathXmlApplicationContext(CONFIG);
+ ITestBean testBean = (ITestBean) context.getBean("testBean");
+ assertTrue(testBean.isInitialized());
+ }
+
+ public void testDefaultDestroyMethod() {
+ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(CONFIG);
+ ITestBean testBean = (ITestBean) context.getBean("nonRefreshableTestBean");
+ assertFalse(testBean.isDestroyed());
+ context.close();
+ assertTrue(testBean.isDestroyed());
+ }
+
+ public void testDefaultAutowire() {
+ ApplicationContext context = new ClassPathXmlApplicationContext(CONFIG);
+ ITestBean testBean = (ITestBean) context.getBean("testBean");
+ ITestBean otherBean = (ITestBean) context.getBean("otherBean");
+ assertEquals(otherBean, testBean.getOtherBean());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/config/TestBean.groovy b/org.springframework.testsuite/src/test/java/org/springframework/scripting/config/TestBean.groovy
new file mode 100644
index 00000000000..74188adfb55
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/config/TestBean.groovy
@@ -0,0 +1,19 @@
+package org.springframework.scripting.config
+
+class TestBean implements ITestBean {
+
+ ITestBean otherBean
+
+ boolean initialized
+
+ boolean destroyed
+
+ void setOtherBean(ITestBean otherBean) {
+ this.otherBean = otherBean;
+ }
+
+ void startup() { this.initialized = true }
+
+ void shutdown() { this.destroyed = true }
+
+}
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/config/scriptingDefaultsTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/config/scriptingDefaultsTests.xml
new file mode 100644
index 00000000000..50ccdf95853
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/config/scriptingDefaultsTests.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/Broken.groovyb b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/Broken.groovyb
new file mode 100644
index 00000000000..b9e6515230c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/Broken.groovyb
@@ -0,0 +1,14 @@
+I have eaten
+the plums
+that were in
+the icebox
+
+and which
+you were probably
+saving
+for breakfast
+
+Forgive me
+they were delicious
+so sweet
+and so cold
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/Calculator.groovy b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/Calculator.groovy
new file mode 100644
index 00000000000..9be3036fd5d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/Calculator.groovy
@@ -0,0 +1,10 @@
+package org.springframework.scripting.groovy;
+
+import org.springframework.scripting.Calculator
+
+class GroovyCalculator implements Calculator {
+
+ int add(int x, int y) {
+ return x + y;
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/CallCounter.groovy b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/CallCounter.groovy
new file mode 100644
index 00000000000..fd2303782d8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/CallCounter.groovy
@@ -0,0 +1,24 @@
+package org.springframework.scripting.groovy;
+
+import org.springframework.scripting.CallCounter;
+
+class GroovyCallCounter implements CallCounter {
+
+ int count = -100;
+
+ void init() {
+ count = 0;
+ }
+
+ void before() {
+ count++;
+ }
+
+ int getCalls() {
+ return count;
+ }
+
+ void destroy() {
+ count = -200;
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/DelegatingCalculator.groovy b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/DelegatingCalculator.groovy
new file mode 100644
index 00000000000..e60fb52734c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/DelegatingCalculator.groovy
@@ -0,0 +1,19 @@
+package org.springframework.scripting.groovy;
+
+import org.springframework.scripting.Calculator
+
+class DelegatingCalculator implements Calculator {
+
+ def Calculator delegate;
+
+ int add(int x, int y) {
+ //println "hello"
+ //println this.metaClass.getClass()
+ //println delegate.metaClass.getClass()
+ //delegate.metaClass.invokeMethod("add", [x,y])
+
+ delegate.callMissingMethod()
+
+ return delegate.add(x,y)
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/GroovyClassLoadingTests.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/GroovyClassLoadingTests.java
new file mode 100644
index 00000000000..530559a6b47
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/GroovyClassLoadingTests.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.scripting.groovy;
+
+import java.lang.reflect.Method;
+
+import groovy.lang.GroovyClassLoader;
+import junit.framework.TestCase;
+
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.context.support.StaticApplicationContext;
+import org.springframework.util.ReflectionUtils;
+
+/**
+ * @author Mark Fisher
+ */
+public class GroovyClassLoadingTests extends TestCase {
+
+ public void testClassLoading() throws Exception {
+ StaticApplicationContext context = new StaticApplicationContext();
+
+ GroovyClassLoader gcl = new GroovyClassLoader();
+ Class class1 = gcl.parseClass("class TestBean { def myMethod() { \"foo\" } }");
+ Class class2 = gcl.parseClass("class TestBean { def myMethod() { \"bar\" } }");
+
+ context.registerBeanDefinition("testBean", new RootBeanDefinition(class1));
+ Object testBean1 = context.getBean("testBean");
+ Method method1 = class1.getDeclaredMethod("myMethod", new Class[0]);
+ Object result1 = ReflectionUtils.invokeMethod(method1, testBean1);
+ assertEquals("foo", (String) result1);
+
+ // ### uncommenting the next line causes the test to pass for Spring > 2.0.2 ###
+ //context.removeBeanDefinition("testBean");
+
+ context.registerBeanDefinition("testBean", new RootBeanDefinition(class2));
+ Object testBean2 = context.getBean("testBean");
+ Method method2 = class2.getDeclaredMethod("myMethod", new Class[0]);
+ Object result2 = ReflectionUtils.invokeMethod(method2, testBean2);
+ assertEquals("bar", (String) result2);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/GroovyScriptFactoryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/GroovyScriptFactoryTests.java
new file mode 100644
index 00000000000..a8641a688ba
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/GroovyScriptFactoryTests.java
@@ -0,0 +1,447 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.scripting.groovy;
+
+import java.io.FileNotFoundException;
+import java.util.Arrays;
+import java.util.Map;
+
+import groovy.lang.DelegatingMetaClass;
+import groovy.lang.GroovyObject;
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.aop.support.AopUtils;
+import org.springframework.aop.target.dynamic.Refreshable;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.UnsatisfiedDependencyException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.core.NestedRuntimeException;
+import org.springframework.scripting.Calculator;
+import org.springframework.scripting.CallCounter;
+import org.springframework.scripting.ConfigurableMessenger;
+import org.springframework.scripting.ContextScriptBean;
+import org.springframework.scripting.Messenger;
+import org.springframework.scripting.ScriptCompilationException;
+import org.springframework.scripting.ScriptSource;
+import org.springframework.scripting.support.ScriptFactoryPostProcessor;
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Rob Harrop
+ * @author Rick Evans
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @author Mark Fisher
+ */
+public class GroovyScriptFactoryTests extends TestCase {
+
+ public void testStaticScript() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("groovyContext.xml", getClass());
+
+ assertTrue(Arrays.asList(ctx.getBeanNamesForType(Calculator.class)).contains("calculator"));
+ assertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.class)).contains("messenger"));
+
+ Calculator calc = (Calculator) ctx.getBean("calculator");
+ Messenger messenger = (Messenger) ctx.getBean("messenger");
+
+ assertFalse("Shouldn't get proxy when refresh is disabled", AopUtils.isAopProxy(calc));
+ assertFalse("Shouldn't get proxy when refresh is disabled", AopUtils.isAopProxy(messenger));
+
+ assertFalse("Scripted object should not be instance of Refreshable", calc instanceof Refreshable);
+ assertFalse("Scripted object should not be instance of Refreshable", messenger instanceof Refreshable);
+
+ assertEquals(calc, calc);
+ assertEquals(messenger, messenger);
+ assertTrue(!messenger.equals(calc));
+ assertTrue(messenger.hashCode() != calc.hashCode());
+ assertTrue(!messenger.toString().equals(calc.toString()));
+
+ String desiredMessage = "Hello World!";
+ assertEquals("Message is incorrect", desiredMessage, messenger.getMessage());
+
+ assertTrue(ctx.getBeansOfType(Calculator.class).values().contains(calc));
+ assertTrue(ctx.getBeansOfType(Messenger.class).values().contains(messenger));
+ }
+
+ public void testStaticPrototypeScript() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("groovyContext.xml", getClass());
+ ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
+ ConfigurableMessenger messenger2 = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
+
+ assertFalse("Shouldn't get proxy when refresh is disabled", AopUtils.isAopProxy(messenger));
+ assertFalse("Scripted object should not be instance of Refreshable", messenger instanceof Refreshable);
+
+ assertNotSame(messenger, messenger2);
+ assertSame(messenger.getClass(), messenger2.getClass());
+ assertEquals("Hello World!", messenger.getMessage());
+ assertEquals("Hello World!", messenger2.getMessage());
+ messenger.setMessage("Bye World!");
+ messenger2.setMessage("Byebye World!");
+ assertEquals("Bye World!", messenger.getMessage());
+ assertEquals("Byebye World!", messenger2.getMessage());
+ }
+
+ public void testStaticScriptWithInstance() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("groovyContext.xml", getClass());
+ assertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.class)).contains("messengerInstance"));
+ Messenger messenger = (Messenger) ctx.getBean("messengerInstance");
+
+ assertFalse("Shouldn't get proxy when refresh is disabled", AopUtils.isAopProxy(messenger));
+ assertFalse("Scripted object should not be instance of Refreshable", messenger instanceof Refreshable);
+
+ String desiredMessage = "Hello World!";
+ assertEquals("Message is incorrect", desiredMessage, messenger.getMessage());
+ assertTrue(ctx.getBeansOfType(Messenger.class).values().contains(messenger));
+ }
+
+ public void testStaticScriptWithInlineDefinedInstance() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("groovyContext.xml", getClass());
+ assertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.class)).contains("messengerInstanceInline"));
+ Messenger messenger = (Messenger) ctx.getBean("messengerInstanceInline");
+
+ assertFalse("Shouldn't get proxy when refresh is disabled", AopUtils.isAopProxy(messenger));
+ assertFalse("Scripted object should not be instance of Refreshable", messenger instanceof Refreshable);
+
+ String desiredMessage = "Hello World!";
+ assertEquals("Message is incorrect", desiredMessage, messenger.getMessage());
+ assertTrue(ctx.getBeansOfType(Messenger.class).values().contains(messenger));
+ }
+
+ public void testNonStaticScript() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("groovyRefreshableContext.xml", getClass());
+ Messenger messenger = (Messenger) ctx.getBean("messenger");
+
+ assertTrue("Should be a proxy for refreshable scripts", AopUtils.isAopProxy(messenger));
+ assertTrue("Should be an instance of Refreshable", messenger instanceof Refreshable);
+
+ String desiredMessage = "Hello World!";
+ assertEquals("Message is incorrect", desiredMessage, messenger.getMessage());
+
+ Refreshable refreshable = (Refreshable) messenger;
+ refreshable.refresh();
+
+ assertEquals("Message is incorrect after refresh.", desiredMessage, messenger.getMessage());
+ assertEquals("Incorrect refresh count", 2, refreshable.getRefreshCount());
+ }
+
+ public void testNonStaticPrototypeScript() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("groovyRefreshableContext.xml", getClass());
+ ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
+ ConfigurableMessenger messenger2 = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
+
+ assertTrue("Should be a proxy for refreshable scripts", AopUtils.isAopProxy(messenger));
+ assertTrue("Should be an instance of Refreshable", messenger instanceof Refreshable);
+
+ assertEquals("Hello World!", messenger.getMessage());
+ assertEquals("Hello World!", messenger2.getMessage());
+ messenger.setMessage("Bye World!");
+ messenger2.setMessage("Byebye World!");
+ assertEquals("Bye World!", messenger.getMessage());
+ assertEquals("Byebye World!", messenger2.getMessage());
+
+ Refreshable refreshable = (Refreshable) messenger;
+ refreshable.refresh();
+
+ assertEquals("Hello World!", messenger.getMessage());
+ assertEquals("Byebye World!", messenger2.getMessage());
+ assertEquals("Incorrect refresh count", 2, refreshable.getRefreshCount());
+ }
+
+ public void testScriptCompilationException() throws Exception {
+ try {
+ new ClassPathXmlApplicationContext("org/springframework/scripting/groovy/groovyBrokenContext.xml");
+ fail("Should throw exception for broken script file");
+ }
+ catch (NestedRuntimeException ex) {
+ assertTrue("Wrong root cause: " + ex, ex.contains(ScriptCompilationException.class));
+ }
+ }
+
+ public void testScriptedClassThatDoesNotHaveANoArgCtor() throws Exception {
+ MockControl mock = MockControl.createControl(ScriptSource.class);
+ ScriptSource script = (ScriptSource) mock.getMock();
+ script.getScriptAsString();
+ final String badScript = "class Foo { public Foo(String foo) {}}";
+ mock.setReturnValue(badScript);
+ script.suggestedClassName();
+ mock.setReturnValue("someName");
+ mock.replay();
+ GroovyScriptFactory factory = new GroovyScriptFactory(ScriptFactoryPostProcessor.INLINE_SCRIPT_PREFIX + badScript);
+ try {
+ factory.getScriptedObject(script, new Class[]{});
+ fail("Must have thrown a ScriptCompilationException (no public no-arg ctor in scripted class).");
+ }
+ catch (ScriptCompilationException expected) {
+ assertTrue(expected.contains(InstantiationException.class));
+ }
+ mock.verify();
+ }
+
+ public void testScriptedClassThatHasNoPublicNoArgCtor() throws Exception {
+ MockControl mock = MockControl.createControl(ScriptSource.class);
+ ScriptSource script = (ScriptSource) mock.getMock();
+ script.getScriptAsString();
+ final String badScript = "class Foo { protected Foo() {}}";
+ mock.setReturnValue(badScript);
+ script.suggestedClassName();
+ mock.setReturnValue("someName");
+ mock.replay();
+ GroovyScriptFactory factory = new GroovyScriptFactory(ScriptFactoryPostProcessor.INLINE_SCRIPT_PREFIX + badScript);
+ try {
+ factory.getScriptedObject(script, new Class[]{});
+ fail("Must have thrown a ScriptCompilationException (no oublic no-arg ctor in scripted class).");
+ }
+ catch (ScriptCompilationException expected) {
+ assertTrue(expected.contains(IllegalAccessException.class));
+ }
+ mock.verify();
+ }
+
+ public void testWithTwoClassesDefinedInTheOneGroovyFile_CorrectClassFirst() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("twoClassesCorrectOneFirst.xml", getClass());
+ Messenger messenger = (Messenger) ctx.getBean("messenger");
+ assertNotNull(messenger);
+ assertEquals("Hello World!", messenger.getMessage());
+
+ // Check can cast to GroovyObject
+ GroovyObject goo = (GroovyObject) messenger;
+ }
+
+ public void testWithTwoClassesDefinedInTheOneGroovyFile_WrongClassFirst() throws Exception {
+ try {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("twoClassesWrongOneFirst.xml", getClass());
+ ctx.getBean("messenger", Messenger.class);
+ fail("Must have failed: two classes defined in GroovyScriptFactory source, non-Messenger class defined first.");
+ }
+ // just testing for failure here, hence catching Exception...
+ catch (Exception expected) {
+ }
+ }
+
+ public void testCtorWithNullScriptSourceLocator() throws Exception {
+ try {
+ new GroovyScriptFactory(null);
+ fail("Must have thrown exception by this point.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testCtorWithEmptyScriptSourceLocator() throws Exception {
+ try {
+ new GroovyScriptFactory("");
+ fail("Must have thrown exception by this point.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testCtorWithWhitespacedScriptSourceLocator() throws Exception {
+ try {
+ new GroovyScriptFactory("\n ");
+ fail("Must have thrown exception by this point.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testWithInlineScriptWithLeadingWhitespace() throws Exception {
+ try {
+ new ClassPathXmlApplicationContext("lwspBadGroovyContext.xml", getClass());
+ fail("Must have thrown a BeanCreationException ('inline:' prefix was preceded by whitespace");
+ }
+ catch (BeanCreationException expected) {
+ assertTrue(expected.contains(FileNotFoundException.class));
+ }
+ }
+
+ public void testGetScriptedObjectDoesNotChokeOnNullInterfacesBeingPassedIn() throws Exception {
+ MockControl mock = MockControl.createControl(ScriptSource.class);
+ ScriptSource scriptSource = (ScriptSource) mock.getMock();
+ scriptSource.getScriptAsString();
+ mock.setReturnValue("class Bar {}");
+ scriptSource.suggestedClassName();
+ mock.setReturnValue("someName");
+ mock.replay();
+
+ GroovyScriptFactory factory = new GroovyScriptFactory("a script source locator (doesn't matter here)");
+ Object scriptedObject = factory.getScriptedObject(scriptSource, null);
+ assertNotNull(scriptedObject);
+ mock.verify();
+ }
+
+ public void testGetScriptedObjectDoesChokeOnNullScriptSourceBeingPassedIn() throws Exception {
+ GroovyScriptFactory factory = new GroovyScriptFactory("a script source locator (doesn't matter here)");
+ try {
+ factory.getScriptedObject(null, null);
+ fail("Must have thrown a NullPointerException as per contract ('null' ScriptSource supplied");
+ }
+ catch (NullPointerException expected) {
+ }
+ }
+
+ public void testResourceScriptFromTag() throws Exception {
+ ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("groovy-with-xsd.xml", getClass());
+ Messenger messenger = (Messenger) ctx.getBean("messenger");
+ CallCounter countingAspect = (CallCounter) ctx.getBean("getMessageAspect");
+
+ assertTrue(AopUtils.isAopProxy(messenger));
+ assertFalse(messenger instanceof Refreshable);
+ assertEquals(0, countingAspect.getCalls());
+ assertEquals("Hello World!", messenger.getMessage());
+ assertEquals(1, countingAspect.getCalls());
+
+ ctx.close();
+ assertEquals(-200, countingAspect.getCalls());
+ }
+
+ public void testPrototypeScriptFromTag() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("groovy-with-xsd.xml", getClass());
+ ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
+ ConfigurableMessenger messenger2 = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
+
+ assertNotSame(messenger, messenger2);
+ assertSame(messenger.getClass(), messenger2.getClass());
+ assertEquals("Hello World!", messenger.getMessage());
+ assertEquals("Hello World!", messenger2.getMessage());
+ messenger.setMessage("Bye World!");
+ messenger2.setMessage("Byebye World!");
+ assertEquals("Bye World!", messenger.getMessage());
+ assertEquals("Byebye World!", messenger2.getMessage());
+ }
+
+ public void testInlineScriptFromTag() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("groovy-with-xsd.xml", getClass());
+ Calculator calculator = (Calculator) ctx.getBean("calculator");
+ assertNotNull(calculator);
+ assertFalse(calculator instanceof Refreshable);
+ }
+
+ public void testRefreshableFromTag() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("groovy-with-xsd.xml", getClass());
+ assertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.class)).contains("refreshableMessenger"));
+
+ Messenger messenger = (Messenger) ctx.getBean("refreshableMessenger");
+ CallCounter countingAspect = (CallCounter) ctx.getBean("getMessageAspect");
+
+ assertTrue(AopUtils.isAopProxy(messenger));
+ assertTrue(messenger instanceof Refreshable);
+ assertEquals(0, countingAspect.getCalls());
+ assertEquals("Hello World!", messenger.getMessage());
+ assertEquals(1, countingAspect.getCalls());
+
+ assertTrue(ctx.getBeansOfType(Messenger.class).values().contains(messenger));
+ }
+
+ public void testAnonymousScriptDetected() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("groovy-with-xsd.xml", getClass());
+ Map beans = ctx.getBeansOfType(Messenger.class);
+ assertEquals(4, beans.size());
+ }
+
+ /**
+ * Tests the SPR-2098 bug whereby no more than 1 property element could be
+ * passed to a scripted bean :(
+ */
+ public void testCanPassInMoreThanOneProperty() {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("groovy-multiple-properties.xml", getClass());
+ TestBean tb = (TestBean) ctx.getBean("testBean");
+
+ ContextScriptBean bean = (ContextScriptBean) ctx.getBean("bean");
+ assertEquals("The first property ain't bein' injected.", "Sophie Marceau", bean.getName());
+ assertEquals("The second property ain't bein' injected.", 31, bean.getAge());
+ assertEquals(tb, bean.getTestBean());
+ assertEquals(ctx, bean.getApplicationContext());
+
+ ContextScriptBean bean2 = (ContextScriptBean) ctx.getBean("bean2");
+ assertEquals(tb, bean2.getTestBean());
+ assertEquals(ctx, bean2.getApplicationContext());
+
+ try {
+ ctx.getBean("bean3");
+ fail("Should have thrown BeanCreationException");
+ }
+ catch (BeanCreationException ex) {
+ // expected
+ assertTrue(ex.contains(UnsatisfiedDependencyException.class));
+ }
+ }
+
+ public void testMetaClassWithBeans() {
+ testMetaClass("org/springframework/scripting/groovy/calculators.xml");
+ }
+
+ public void testMetaClassWithXsd() {
+ testMetaClass("org/springframework/scripting/groovy/calculators-with-xsd.xml");
+ }
+
+ private void testMetaClass(final String xmlFile) {
+ // expect the exception we threw in the custom metaclass to show it got invoked
+ AssertThrows at = new AssertThrows(IllegalStateException.class) {
+ public void test() throws Exception {
+ ApplicationContext ctx =
+ new ClassPathXmlApplicationContext(xmlFile);
+ Calculator calc = (Calculator) ctx.getBean("delegatingCalculator");
+ calc.add(1, 2);
+ }
+ };
+ at.runTest();
+ assertEquals("Gotcha", at.getActualException().getMessage());
+ }
+
+ public void testFactoryBean() {
+ ApplicationContext context = new ClassPathXmlApplicationContext("groovyContext.xml", getClass());
+ Object factory = context.getBean("&factory");
+ assertTrue(factory instanceof FactoryBean);
+ Object result = context.getBean("factory");
+ assertTrue(result instanceof String);
+ assertEquals("test", result);
+ }
+
+ public void testRefreshableFactoryBean() {
+ ApplicationContext context = new ClassPathXmlApplicationContext("groovyContext.xml", getClass());
+ Object factory = context.getBean("&refreshableFactory");
+ assertTrue(factory instanceof FactoryBean);
+ Object result = context.getBean("refreshableFactory");
+ assertTrue(result instanceof String);
+ assertEquals("test", result);
+ }
+
+
+ public static class TestCustomizer implements GroovyObjectCustomizer {
+
+ public void customize(GroovyObject goo) {
+ DelegatingMetaClass dmc = new DelegatingMetaClass(goo.getMetaClass()) {
+ public Object invokeMethod(Object arg0, String mName, Object[] arg2) {
+ if (mName.indexOf("Missing") != -1) {
+ throw new IllegalStateException("Gotcha");
+ }
+ else {
+ return super.invokeMethod(arg0, mName, arg2);
+ }
+ }
+ };
+ dmc.initialize();
+ goo.setMetaClass(dmc);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/Messenger.groovy b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/Messenger.groovy
new file mode 100644
index 00000000000..6f411a695c5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/Messenger.groovy
@@ -0,0 +1,8 @@
+package org.springframework.scripting.groovy;
+
+import org.springframework.scripting.ConfigurableMessenger
+
+class GroovyMessenger implements ConfigurableMessenger {
+
+ def String message;
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/MessengerInstance.groovy b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/MessengerInstance.groovy
new file mode 100644
index 00000000000..8f0a864329c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/MessengerInstance.groovy
@@ -0,0 +1,14 @@
+package org.springframework.scripting.groovy;
+
+import org.springframework.scripting.Messenger
+
+class GroovyMessenger implements Messenger {
+
+ GroovyMessenger() {
+ println "GroovyMessenger"
+ }
+
+ def String message;
+}
+
+return new GroovyMessenger();
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/ScriptBean.groovy b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/ScriptBean.groovy
new file mode 100644
index 00000000000..d1b82bfece9
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/ScriptBean.groovy
@@ -0,0 +1,23 @@
+import org.springframework.beans.TestBean
+import org.springframework.context.ApplicationContext
+import org.springframework.context.ApplicationContextAware
+import org.springframework.scripting.ContextScriptBean
+
+class GroovyScriptBean implements ContextScriptBean, ApplicationContextAware {
+
+ private int age
+
+ int getAge() {
+ return this.age
+ }
+
+ void setAge(int age) {
+ this.age = age
+ }
+
+ def String name
+
+ def TestBean testBean;
+
+ def ApplicationContext applicationContext
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/TestFactoryBean.groovy b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/TestFactoryBean.groovy
new file mode 100644
index 00000000000..e86c13a6efb
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/TestFactoryBean.groovy
@@ -0,0 +1,17 @@
+import org.springframework.beans.factory.FactoryBean
+
+class TestFactoryBean implements FactoryBean {
+
+ public boolean isSingleton() {
+ true
+ }
+
+ public Class getObjectType() {
+ String.class
+ }
+
+ public Object getObject() {
+ "test"
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/calculators-with-xsd.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/calculators-with-xsd.xml
new file mode 100644
index 00000000000..8c90f9b2673
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/calculators-with-xsd.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/calculators.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/calculators.xml
new file mode 100644
index 00000000000..b936acc96e9
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/calculators.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/groovy-multiple-properties.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/groovy-multiple-properties.xml
new file mode 100644
index 00000000000..58ce5e022aa
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/groovy-multiple-properties.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/groovy-with-xsd.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/groovy-with-xsd.xml
new file mode 100644
index 00000000000..1887788bd97
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/groovy-with-xsd.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ package org.springframework.scripting.groovy;
+import org.springframework.scripting.Calculator
+class GroovyCalculator implements Calculator {
+ int add(int x, int y) {
+ return x + y;
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/groovyBrokenContext.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/groovyBrokenContext.xml
new file mode 100644
index 00000000000..e8e17e1b29d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/groovyBrokenContext.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/groovyContext.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/groovyContext.xml
new file mode 100644
index 00000000000..a159b1791e7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/groovyContext.xml
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+ inline:
+package org.springframework.scripting.groovy;
+import org.springframework.scripting.Calculator
+class GroovyCalculator implements Calculator {
+ int add(int x, int y) {
+ return x + y;
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ inline:
+package org.springframework.scripting.groovy;
+import org.springframework.scripting.Messenger
+class GroovyMessenger implements Messenger {
+ def String message;
+}
+return new GroovyMessenger();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/groovyRefreshableContext.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/groovyRefreshableContext.xml
new file mode 100644
index 00000000000..34c8b401d1a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/groovyRefreshableContext.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/lwspBadGroovyContext.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/lwspBadGroovyContext.xml
new file mode 100644
index 00000000000..2d5692534de
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/lwspBadGroovyContext.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+ inline:
+
+ class Bingo {
+
+ @Property String message;
+ }
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/twoClassesCorrectOneFirst.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/twoClassesCorrectOneFirst.xml
new file mode 100644
index 00000000000..b32cc8294f7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/twoClassesCorrectOneFirst.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+ inline:
+ package org.springframework.scripting.groovy;
+
+ import org.springframework.scripting.Messenger;
+
+ class GroovyMessenger implements Messenger {
+
+ def String message;
+ }
+
+ class Bingo {
+
+ def String message;
+ }
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/twoClassesWrongOneFirst.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/twoClassesWrongOneFirst.xml
new file mode 100644
index 00000000000..c3b4e80f166
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/groovy/twoClassesWrongOneFirst.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+ inline:
+ package org.springframework.scripting.groovy;
+
+ import org.springframework.scripting.Messenger;
+
+ class Bingo {
+
+ @Property String message;
+ }
+
+ class GroovyMessenger implements Messenger {
+
+ @Property String message;
+ }
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/AdvisedJRubyScriptFactoryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/AdvisedJRubyScriptFactoryTests.java
new file mode 100644
index 00000000000..d2ad09952dc
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/AdvisedJRubyScriptFactoryTests.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.scripting.jruby;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.framework.Advised;
+import org.springframework.aop.framework.CountingBeforeAdvice;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.scripting.Messenger;
+
+/**
+ * @author Rob Harrop
+ */
+public class AdvisedJRubyScriptFactoryTests extends TestCase {
+
+ public void testAdviseWithProxyFactoryBean() throws Exception {
+ ApplicationContext context =
+ new ClassPathXmlApplicationContext("advisedByProxyFactoryBean.xml", getClass());
+
+ Messenger bean = (Messenger) context.getBean("messenger");
+ assertTrue("Bean is not a proxy", AopUtils.isAopProxy(bean));
+ assertTrue("Bean is not an Advised object", bean instanceof Advised);
+
+ CountingBeforeAdvice advice = (CountingBeforeAdvice) context.getBean("advice");
+ assertEquals(0, advice.getCalls());
+ bean.getMessage();
+ assertEquals(1, advice.getCalls());
+ }
+
+ public void testAdviseWithBeanNameAutoProxyCreator() throws Exception {
+ ApplicationContext context =
+ new ClassPathXmlApplicationContext("advisedByBeanNameAutoProxyCreator.xml", getClass());
+
+ Messenger bean = (Messenger) context.getBean("messenger");
+ assertTrue("Bean is not a proxy", AopUtils.isAopProxy(bean));
+ assertTrue("Bean is not an Advised object", bean instanceof Advised);
+
+ CountingBeforeAdvice advice = (CountingBeforeAdvice) context.getBean("advice");
+ assertEquals(0, advice.getCalls());
+ bean.getMessage();
+ assertEquals(1, advice.getCalls());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/Broken.rb b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/Broken.rb
new file mode 100644
index 00000000000..0e16bb77584
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/Broken.rb
@@ -0,0 +1,4 @@
+In A Station Of The Metro
+
+the apparition of these faces in the crowd
+petals on a wet black bough
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/Calculator.rb b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/Calculator.rb
new file mode 100644
index 00000000000..d3785e03f74
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/Calculator.rb
@@ -0,0 +1,9 @@
+require 'java'
+
+class RubyCalculator
+ include org.springframework.scripting.Calculator
+
+ def add(x, y)
+ x + y
+ end
+end
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/JRubyScriptFactoryTests.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/JRubyScriptFactoryTests.java
new file mode 100644
index 00000000000..08bf6b6cc57
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/JRubyScriptFactoryTests.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.scripting.jruby;
+
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.support.AopUtils;
+import org.springframework.aop.target.dynamic.Refreshable;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.scripting.Calculator;
+import org.springframework.scripting.ConfigurableMessenger;
+import org.springframework.scripting.Messenger;
+import org.springframework.scripting.ScriptCompilationException;
+import org.springframework.scripting.TestBeanAwareMessenger;
+
+/**
+ * @author Rob Harrop
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class JRubyScriptFactoryTests extends TestCase {
+
+ private static final String RUBY_SCRIPT_SOURCE_LOCATOR =
+ "inline:require 'java'\n" +
+ "class RubyBar\n" +
+ "end\n" +
+ "RubyBar.new";
+
+
+ public void testStaticScript() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("jrubyContext.xml", getClass());
+ Calculator calc = (Calculator) ctx.getBean("calculator");
+ Messenger messenger = (Messenger) ctx.getBean("messenger");
+
+ assertFalse("Scripted object should not be instance of Refreshable", calc instanceof Refreshable);
+ assertFalse("Scripted object should not be instance of Refreshable", messenger instanceof Refreshable);
+
+ assertEquals(calc, calc);
+ assertEquals(messenger, messenger);
+ assertTrue(!messenger.equals(calc));
+ assertTrue(messenger.hashCode() != calc.hashCode());
+ assertTrue(!messenger.toString().equals(calc.toString()));
+
+ String desiredMessage = "Hello World!";
+ assertEquals("Message is incorrect", desiredMessage, messenger.getMessage());
+ }
+
+ public void testNonStaticScript() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("jrubyRefreshableContext.xml", getClass());
+ Messenger messenger = (Messenger) ctx.getBean("messenger");
+
+ assertTrue("Should be a proxy for refreshable scripts", AopUtils.isAopProxy(messenger));
+ assertTrue("Should be an instance of Refreshable", messenger instanceof Refreshable);
+
+ String desiredMessage = "Hello World!";
+ assertEquals("Message is incorrect.", desiredMessage, messenger.getMessage());
+
+ Refreshable refreshable = (Refreshable) messenger;
+ refreshable.refresh();
+
+ assertEquals("Message is incorrect after refresh.", desiredMessage, messenger.getMessage());
+ assertEquals("Incorrect refresh count", 2, refreshable.getRefreshCount());
+ }
+
+ public void testScriptCompilationException() throws Exception {
+ try {
+ new ClassPathXmlApplicationContext("jrubyBrokenContext.xml", getClass());
+ fail("Should throw exception for broken script file");
+ }
+ catch (BeanCreationException ex) {
+ assertTrue(ex.contains(ScriptCompilationException.class));
+ }
+ }
+
+ public void testCtorWithNullScriptSourceLocator() throws Exception {
+ try {
+ new JRubyScriptFactory(null, new Class[]{Messenger.class});
+ fail("Must have thrown exception by this point.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testCtorWithEmptyScriptSourceLocator() throws Exception {
+ try {
+ new JRubyScriptFactory("", new Class[]{Messenger.class});
+ fail("Must have thrown exception by this point.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testCtorWithWhitespacedScriptSourceLocator() throws Exception {
+ try {
+ new JRubyScriptFactory("\n ", new Class[]{Messenger.class});
+ fail("Must have thrown exception by this point.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testCtorWithNullScriptInterfacesArray() throws Exception {
+ try {
+ new JRubyScriptFactory(RUBY_SCRIPT_SOURCE_LOCATOR, null);
+ fail("Must have thrown exception by this point.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testCtorWithEmptyScriptInterfacesArray() throws Exception {
+ try {
+ new JRubyScriptFactory(RUBY_SCRIPT_SOURCE_LOCATOR, new Class[]{});
+ fail("Must have thrown exception by this point.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testResourceScriptFromTag() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("jruby-with-xsd.xml", getClass());
+ TestBean testBean = (TestBean) ctx.getBean("testBean");
+
+ Messenger messenger = (Messenger) ctx.getBean("messenger");
+ assertEquals("Hello World!", messenger.getMessage());
+ assertFalse(messenger instanceof Refreshable);
+
+ TestBeanAwareMessenger messengerByType = (TestBeanAwareMessenger) ctx.getBean("messengerByType");
+ assertEquals(testBean, messengerByType.getTestBean());
+
+ TestBeanAwareMessenger messengerByName = (TestBeanAwareMessenger) ctx.getBean("messengerByName");
+ assertEquals(testBean, messengerByName.getTestBean());
+ }
+
+ public void testPrototypeScriptFromTag() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("jruby-with-xsd.xml", getClass());
+ ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
+ ConfigurableMessenger messenger2 = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
+
+ assertNotSame(messenger, messenger2);
+ assertSame(messenger.getClass(), messenger2.getClass());
+ assertEquals("Hello World!", messenger.getMessage());
+ assertEquals("Hello World!", messenger2.getMessage());
+ messenger.setMessage("Bye World!");
+ messenger2.setMessage("Byebye World!");
+ assertEquals("Bye World!", messenger.getMessage());
+ assertEquals("Byebye World!", messenger2.getMessage());
+ }
+
+ public void testInlineScriptFromTag() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("jruby-with-xsd.xml", getClass());
+ Calculator calculator = (Calculator) ctx.getBean("calculator");
+ assertNotNull(calculator);
+ assertFalse(calculator instanceof Refreshable);
+ }
+
+ public void testRefreshableFromTag() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("jruby-with-xsd.xml", getClass());
+ Messenger messenger = (Messenger) ctx.getBean("refreshableMessenger");
+ assertEquals("Hello World!", messenger.getMessage());
+ assertTrue("Messenger should be Refreshable", messenger instanceof Refreshable);
+ }
+
+ public void testThatMultipleScriptInterfacesAreSupported() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("jruby-with-xsd.xml", getClass());
+ Messenger messenger = (Messenger) ctx.getBean("calculatingMessenger");
+ assertEquals("Hello World!", messenger.getMessage());
+
+ // cool, now check that the Calculator interface is also exposed
+ Calculator calc = (Calculator) messenger;
+ assertEquals(0, calc.add(2, -2));
+ }
+
+ public void testWithComplexArg() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("jrubyContext.xml", getClass());
+ Printer printer = (Printer) ctx.getBean("printer");
+ CountingPrintable printable = new CountingPrintable();
+ printer.print(printable);
+ assertEquals(1, printable.count);
+ }
+
+ public void testWithPrimitiveArgsInReturnTypeAndParameters() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("jrubyContextForPrimitives.xml", getClass());
+ PrimitiveAdder adder = (PrimitiveAdder) ctx.getBean("adder");
+ assertEquals(2, adder.addInts(1, 1));
+ assertEquals(4, adder.addShorts((short) 1, (short) 3));
+ assertEquals(5, adder.addLongs(2L, 3L));
+ assertEquals(5, new Float(adder.addFloats(2.0F, 3.1F)).intValue());
+ assertEquals(5, new Double(adder.addDoubles(2.0, 3.1)).intValue());
+ assertFalse(adder.resultIsPositive(-200, 1));
+ assertEquals("ri", adder.concatenate('r', 'i'));
+ assertEquals('c', adder.echo('c'));
+ }
+
+ public void testWithWrapperArgsInReturnTypeAndParameters() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("jrubyContextForWrappers.xml", getClass());
+ WrapperAdder adder = (WrapperAdder) ctx.getBean("adder");
+
+ assertEquals(new Integer(2), adder.addInts(new Integer(1), new Integer(1)));
+ assertEquals(Integer.class, adder.addInts(new Integer(1), new Integer(1)).getClass());
+ assertEquals(new Short((short) 4), adder.addShorts(new Short((short) 1), new Short((short) 3)));
+ assertEquals(Short.class, adder.addShorts(new Short((short) 1), new Short((short) 3)).getClass());
+ assertEquals(new Long(5L), adder.addLongs(new Long(2L), new Long(3L)));
+ assertEquals(Long.class, adder.addLongs(new Long(2L), new Long(3L)).getClass());
+ assertEquals(5, adder.addFloats(new Float(2.0F), new Float(3.1F)).intValue());
+ assertEquals(Float.class, adder.addFloats(new Float(2.0F), new Float(3.1F)).getClass());
+ assertEquals(5, new Double(adder.addDoubles(new Double(2.0), new Double(3.1)).intValue()).intValue());
+ assertEquals(Double.class, adder.addDoubles(new Double(2.0), new Double(3.1)).getClass());
+ assertFalse(adder.resultIsPositive(new Integer(-200), new Integer(1)).booleanValue());
+ assertEquals(Boolean.class, adder.resultIsPositive(new Integer(-200), new Integer(1)).getClass());
+ assertEquals("ri", adder.concatenate(new Character('r'), new Character('i')));
+ assertEquals(String.class, adder.concatenate(new Character('r'), new Character('i')).getClass());
+ assertEquals(new Character('c'), adder.echo(new Character('c')));
+ assertEquals(Character.class, adder.echo(new Character('c')).getClass());
+ Integer[] numbers = new Integer[]{new Integer(1), new Integer(2), new Integer(3), new Integer(4), new Integer(5)};
+ assertEquals("12345", adder.concatArrayOfIntegerWrappers(numbers));
+ assertEquals(String.class, adder.concatArrayOfIntegerWrappers(numbers).getClass());
+
+ Short[] shorts = adder.populate(new Short((short) 1), new Short((short) 2));
+ assertEquals(2, shorts.length);
+ assertNotNull(shorts[0]);
+ assertEquals(new Short((short) 1), shorts[0]);
+ assertNotNull(shorts[1]);
+ assertEquals(new Short((short) 2), shorts[1]);
+
+ String[][] lol = adder.createListOfLists("1", "2", "3");
+ assertNotNull(lol);
+ assertEquals(3, lol.length);
+ assertEquals("1", lol[0][0]);
+ assertEquals("2", lol[1][0]);
+ assertEquals("3", lol[2][0]);
+
+ Map singleValueMap = adder.toMap("key", "value");
+ assertNotNull(singleValueMap);
+ assertEquals(1, singleValueMap.size());
+ assertEquals("key", singleValueMap.keySet().iterator().next());
+ assertEquals("value", singleValueMap.values().iterator().next());
+
+ String[] expectedStrings = new String[]{"1", "2", "3"};
+ Map map = adder.toMap("key", expectedStrings);
+ assertNotNull(map);
+ assertEquals(1, map.size());
+ assertEquals("key", map.keySet().iterator().next());
+ String[] strings = (String[]) map.values().iterator().next();
+ for (int i = 0; i < expectedStrings.length; ++i) {
+ assertEquals(expectedStrings[i], strings[i]);
+ }
+ }
+
+ public void testAOP() throws Exception {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("jruby-aop.xml", getClass());
+ Messenger messenger = (Messenger) ctx.getBean("messenger");
+ assertEquals(new StringBuffer("Hello World!").reverse().toString(), messenger.getMessage());
+ }
+
+
+ private static final class CountingPrintable implements Printable {
+
+ public int count;
+
+ public String getContent() {
+ this.count++;
+ return "Hello World!";
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/Messenger.rb b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/Messenger.rb
new file mode 100644
index 00000000000..73268f03825
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/Messenger.rb
@@ -0,0 +1,21 @@
+require 'java'
+
+class RubyMessenger
+ include org.springframework.scripting.Messenger
+
+ def setMessage(message)
+ @@message = message
+ end
+
+ def getMessage
+ @@message
+ end
+
+ def setTestBean(testBean)
+ @@testBean = testBean
+ end
+
+ def getTestBean
+ @@testBean
+ end
+end
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/PrimitiveAdder.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/PrimitiveAdder.java
new file mode 100644
index 00000000000..1110206e149
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/PrimitiveAdder.java
@@ -0,0 +1,25 @@
+package org.springframework.scripting.jruby;
+
+/**
+ * http://opensource.atlassian.com/projects/spring/browse/SPR-3026
+ *
+ * @author Rick Evans
+ */
+public interface PrimitiveAdder {
+
+ int addInts(int x, int y);
+
+ short addShorts(short x, short y);
+
+ long addLongs(long x, long y);
+
+ float addFloats(float x, float y);
+
+ double addDoubles(double x, double y);
+
+ boolean resultIsPositive(int x, int y);
+
+ String concatenate(char c, char d);
+
+ char echo(char c);
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/Printable.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/Printable.java
new file mode 100644
index 00000000000..6fb529871cd
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/Printable.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.scripting.jruby;
+
+/**
+ * @author Rob Harrop
+ * @since 2.0.2
+ */
+public interface Printable {
+
+ String getContent();
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/Printer.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/Printer.java
new file mode 100644
index 00000000000..d4fb494bbbf
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/Printer.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.scripting.jruby;
+
+/**
+ * @author Rob Harrop
+ * @since 2.0.2
+ */
+public interface Printer {
+
+ void print(Printable arg);
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/Printer.rb b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/Printer.rb
new file mode 100644
index 00000000000..7f622462615
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/Printer.rb
@@ -0,0 +1,9 @@
+require 'java'
+
+class RubyPrinter
+ include org.springframework.scripting.jruby.Printer
+
+ def print(obj)
+ puts obj.getContent
+ end
+end
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/WrapperAdder.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/WrapperAdder.java
new file mode 100644
index 00000000000..2656c8a60e2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/WrapperAdder.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.scripting.jruby;
+
+import java.util.Map;
+
+/**
+ * http://opensource.atlassian.com/projects/spring/browse/SPR-3038
+ *
+ * @author Rick Evans
+ */
+public interface WrapperAdder {
+
+ Integer addInts(Integer x, Integer y);
+
+ Short addShorts(Short x, Short y);
+
+ Long addLongs(Long x, Long y);
+
+ Float addFloats(Float x, Float y);
+
+ Double addDoubles(Double x, Double y);
+
+ Boolean resultIsPositive(Integer x, Integer y);
+
+ String concatenate(Character c, Character d);
+
+ Character echo(Character c);
+
+ String concatArrayOfIntegerWrappers(Integer[] numbers);
+
+ Short[] populate(Short one, Short two);
+
+ String[][] createListOfLists(String one, String second, String third);
+
+ Map toMap(String key, Object value);
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/advisedByBeanNameAutoProxyCreator.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/advisedByBeanNameAutoProxyCreator.xml
new file mode 100644
index 00000000000..39aab62b466
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/advisedByBeanNameAutoProxyCreator.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/advisedByProxyFactoryBean.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/advisedByProxyFactoryBean.xml
new file mode 100644
index 00000000000..fffce34d77f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/advisedByProxyFactoryBean.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/jruby-aop.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/jruby-aop.xml
new file mode 100644
index 00000000000..6fa5b5b64f5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/jruby-aop.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/jruby-with-xsd.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/jruby-with-xsd.xml
new file mode 100644
index 00000000000..13f5d3c9aa0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/jruby-with-xsd.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+require 'java'
+
+class RubyCalculator
+ include org.springframework.scripting.Calculator
+
+ def add(x, y)
+ x + y
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/jrubyBrokenContext.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/jrubyBrokenContext.xml
new file mode 100644
index 00000000000..947cf0d8215
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/jrubyBrokenContext.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/jrubyContext.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/jrubyContext.xml
new file mode 100644
index 00000000000..11f4fb56f0a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/jrubyContext.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+ inline:
+require 'java'
+
+class RubyCalculator
+ include org.springframework.scripting.Calculator
+
+ def add(x, y)
+ x + y
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/jrubyContextForPrimitives.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/jrubyContextForPrimitives.xml
new file mode 100644
index 00000000000..06b4e73ab58
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/jrubyContextForPrimitives.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+ 0
+ end
+
+ def concatenate(c, d)
+ return ("" << c) << d;
+ end
+
+ def echo(c)
+ c
+ end
+
+end
+ ]]>
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/jrubyContextForWrappers.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/jrubyContextForWrappers.xml
new file mode 100644
index 00000000000..f4ed0d736da
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/jrubyContextForWrappers.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+ 0
+ end
+
+ def concatenate(c, d)
+ return ("" << c) << d;
+ end
+
+ def echo(c)
+ c
+ end
+
+ def concatArrayOfIntegerWrappers(numbers)
+ buffer = ""
+ numbers.each do |number|
+ buffer << number.to_s
+ end
+ return buffer
+ end
+
+ def populate(x, y)
+ [x, y]
+ end
+
+ def createListOfLists(x, y, z)
+ [[x], [y], [z]]
+ end
+
+ def toMap(key, value)
+ {key => value}
+ end
+
+end
+ ]]>
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/jrubyRefreshableContext.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/jrubyRefreshableContext.xml
new file mode 100644
index 00000000000..2b9c694a383
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/jruby/jrubyRefreshableContext.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/support/RefreshableScriptTargetSourceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/support/RefreshableScriptTargetSourceTests.java
new file mode 100644
index 00000000000..dd39e655765
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/support/RefreshableScriptTargetSourceTests.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.scripting.support;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.beans.factory.BeanFactory;
+
+/**
+ * @author Rick Evans
+ */
+public class RefreshableScriptTargetSourceTests extends TestCase {
+
+ public void testCreateWithNullScriptSource() throws Exception {
+ MockControl mockFactory = MockControl.createNiceControl(BeanFactory.class);
+ mockFactory.replay();
+ try {
+ new RefreshableScriptTargetSource((BeanFactory) mockFactory.getMock(), "a.bean", null, null, false);
+ fail("Must have failed when passed a null ScriptSource.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ mockFactory.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/support/ResourceScriptSourceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/support/ResourceScriptSourceTests.java
new file mode 100644
index 00000000000..94e8c606e8f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/support/ResourceScriptSourceTests.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.scripting.support;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.core.io.Resource;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class ResourceScriptSourceTests extends TestCase {
+
+ public void testCtorWithNullResource() throws Exception {
+ try {
+ new ResourceScriptSource(null);
+ fail("Must have thrown exception by this point.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testDoesNotPropagateFatalExceptionOnResourceThatCannotBeResolvedToAFile() throws Exception {
+ MockControl mock = MockControl.createControl(Resource.class);
+ Resource resource = (Resource) mock.getMock();
+ resource.lastModified();
+ mock.setThrowable(new IOException());
+ mock.replay();
+
+ ResourceScriptSource scriptSource = new ResourceScriptSource(resource);
+ long lastModified = scriptSource.retrieveLastModifiedTime();
+ assertEquals(0, lastModified);
+ mock.verify();
+ }
+
+ public void testBeginsInModifiedState() throws Exception {
+ MockControl mock = MockControl.createControl(Resource.class);
+ Resource resource = (Resource) mock.getMock();
+ mock.replay();
+
+ ResourceScriptSource scriptSource = new ResourceScriptSource(resource);
+ assertTrue(scriptSource.isModified());
+ mock.verify();
+ }
+
+ public void testLastModifiedWorksWithResourceThatDoesNotSupportFileBasedReading() throws Exception {
+ MockControl mock = MockControl.createControl(Resource.class);
+ Resource resource = (Resource) mock.getMock();
+ // underlying File is asked for so that the last modified time can be checked...
+ resource.lastModified();
+ mock.setReturnValue(100, 2);
+ // does not support File-based reading; delegates to InputStream-style reading...
+ resource.getFile();
+ mock.setThrowable(new FileNotFoundException());
+ resource.getInputStream();
+ mock.setReturnValue(new ByteArrayInputStream(new byte[0]));
+ // And then mock the file changing; i.e. the File says it has been modified
+ resource.lastModified();
+ mock.setReturnValue(200);
+ mock.replay();
+
+ ResourceScriptSource scriptSource = new ResourceScriptSource(resource);
+ assertTrue("ResourceScriptSource must start off in the 'isModified' state (it obviously isn't).", scriptSource.isModified());
+ scriptSource.getScriptAsString();
+ assertFalse("ResourceScriptSource must not report back as being modified if the underlying File resource is not reporting a changed lastModified time.", scriptSource.isModified());
+ // Must now report back as having been modified
+ assertTrue("ResourceScriptSource must report back as being modified if the underlying File resource is reporting a changed lastModified time.", scriptSource.isModified());
+ mock.verify();
+ }
+
+ public void testLastModifiedWorksWithResourceThatDoesNotSupportFileBasedAccessAtAll() throws Exception {
+ Resource resource = new ByteArrayResource(new byte[0]);
+ ResourceScriptSource scriptSource = new ResourceScriptSource(resource);
+ assertTrue("ResourceScriptSource must start off in the 'isModified' state (it obviously isn't).", scriptSource.isModified());
+ scriptSource.getScriptAsString();
+ assertFalse("ResourceScriptSource must not report back as being modified if the underlying File resource is not reporting a changed lastModified time.", scriptSource.isModified());
+ // Must now continue to report back as not having been modified 'cos the Resource does not support access as a File (and so the lastModified date cannot be determined).
+ assertFalse("ResourceScriptSource must not report back as being modified if the underlying File resource is not reporting a changed lastModified time.", scriptSource.isModified());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/support/ScriptFactoryPostProcessorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/support/ScriptFactoryPostProcessorTests.java
new file mode 100644
index 00000000000..8aebff6f7b7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/support/ScriptFactoryPostProcessorTests.java
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.scripting.support;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.beans.FatalBeanException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.context.support.GenericApplicationContext;
+import org.springframework.scripting.Messenger;
+import org.springframework.scripting.ScriptCompilationException;
+import org.springframework.scripting.groovy.GroovyScriptFactory;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class ScriptFactoryPostProcessorTests extends TestCase {
+
+ private static final String MESSAGE_TEXT = "Bingo";
+
+ private static final String MESSENGER_BEAN_NAME = "messenger";
+
+ private static final String PROCESSOR_BEAN_NAME = "processor";
+
+ private static final String CHANGED_SCRIPT = "package org.springframework.scripting.groovy\n" +
+ "import org.springframework.scripting.Messenger\n" +
+ "class GroovyMessenger implements Messenger {\n" +
+ " private String message = \"Bingo\"\n" +
+ " public String getMessage() {\n" +
+ // quote the returned message (this is the change)...
+ " return \"'\" + this.message + \"'\"\n" +
+ " }\n" +
+ " public void setMessage(String message) {\n" +
+ " this.message = message\n" +
+ " }\n" +
+ "}";
+
+ private static final String EXPECTED_CHANGED_MESSAGE_TEXT = "'" + MESSAGE_TEXT + "'";
+
+ private static final int DEFAULT_SECONDS_TO_PAUSE = 1;
+
+ private static final String DELEGATING_SCRIPT = "inline:package org.springframework.scripting;\n" +
+ "class DelegatingMessenger implements Messenger {\n" +
+ " private Messenger wrappedMessenger;\n" +
+ " public String getMessage() {\n" +
+ " return this.wrappedMessenger.getMessage()\n" +
+ " }\n" +
+ " public void setMessenger(Messenger wrappedMessenger) {\n" +
+ " this.wrappedMessenger = wrappedMessenger\n" +
+ " }\n" +
+ "}";
+
+
+ public void testDoesNothingWhenPostProcessingNonScriptFactoryTypeBeforeInstantiation() throws Exception {
+ assertNull(new ScriptFactoryPostProcessor().postProcessBeforeInstantiation(getClass(), "a.bean"));
+ }
+
+ public void testThrowsExceptionIfGivenNonAbstractBeanFactoryImplementation() throws Exception {
+ MockControl mock = MockControl.createControl(BeanFactory.class);
+ mock.replay();
+ try {
+ new ScriptFactoryPostProcessor().setBeanFactory((BeanFactory) mock.getMock());
+ fail("Must have thrown exception by this point.");
+ }
+ catch (IllegalStateException expected) {
+ }
+ mock.verify();
+ }
+
+ public void testChangeScriptWithRefreshableBeanFunctionality() throws Exception {
+ BeanDefinition processorBeanDefinition = createScriptFactoryPostProcessor(true);
+ BeanDefinition scriptedBeanDefinition = createScriptedGroovyBean();
+
+ GenericApplicationContext ctx = new GenericApplicationContext();
+ ctx.registerBeanDefinition(PROCESSOR_BEAN_NAME, processorBeanDefinition);
+ ctx.registerBeanDefinition(MESSENGER_BEAN_NAME, scriptedBeanDefinition);
+ ctx.refresh();
+
+ Messenger messenger = (Messenger) ctx.getBean(MESSENGER_BEAN_NAME);
+ assertEquals(MESSAGE_TEXT, messenger.getMessage());
+ // cool; now let's change the script and check the refresh behaviour...
+ pauseToLetRefreshDelayKickIn(DEFAULT_SECONDS_TO_PAUSE);
+ StaticScriptSource source = getScriptSource(ctx);
+ source.setScript(CHANGED_SCRIPT);
+ Messenger refreshedMessenger = (Messenger) ctx.getBean(MESSENGER_BEAN_NAME);
+ // the updated script surrounds the message in quotes before returning...
+ assertEquals(EXPECTED_CHANGED_MESSAGE_TEXT, refreshedMessenger.getMessage());
+ }
+
+ public void testChangeScriptWithNoRefreshableBeanFunctionality() throws Exception {
+ BeanDefinition processorBeanDefinition = createScriptFactoryPostProcessor(false);
+ BeanDefinition scriptedBeanDefinition = createScriptedGroovyBean();
+
+ GenericApplicationContext ctx = new GenericApplicationContext();
+ ctx.registerBeanDefinition(PROCESSOR_BEAN_NAME, processorBeanDefinition);
+ ctx.registerBeanDefinition(MESSENGER_BEAN_NAME, scriptedBeanDefinition);
+ ctx.refresh();
+
+ Messenger messenger = (Messenger) ctx.getBean(MESSENGER_BEAN_NAME);
+ assertEquals(MESSAGE_TEXT, messenger.getMessage());
+ // cool; now let's change the script and check the refresh behaviour...
+ pauseToLetRefreshDelayKickIn(DEFAULT_SECONDS_TO_PAUSE);
+ StaticScriptSource source = getScriptSource(ctx);
+ source.setScript(CHANGED_SCRIPT);
+ Messenger refreshedMessenger = (Messenger) ctx.getBean(MESSENGER_BEAN_NAME);
+ assertEquals("Script seems to have been refreshed (must not be as no refreshCheckDelay set on ScriptFactoryPostProcessor)",
+ MESSAGE_TEXT, refreshedMessenger.getMessage());
+ }
+
+ public void testRefreshedScriptReferencePropagatesToCollaborators() throws Exception {
+ BeanDefinition processorBeanDefinition = createScriptFactoryPostProcessor(true);
+ BeanDefinition scriptedBeanDefinition = createScriptedGroovyBean();
+ BeanDefinitionBuilder collaboratorBuilder = BeanDefinitionBuilder.rootBeanDefinition(DefaultMessengerService.class);
+ collaboratorBuilder.addPropertyReference(MESSENGER_BEAN_NAME, MESSENGER_BEAN_NAME);
+
+ GenericApplicationContext ctx = new GenericApplicationContext();
+ ctx.registerBeanDefinition(PROCESSOR_BEAN_NAME, processorBeanDefinition);
+ ctx.registerBeanDefinition(MESSENGER_BEAN_NAME, scriptedBeanDefinition);
+ final String collaboratorBeanName = "collaborator";
+ ctx.registerBeanDefinition(collaboratorBeanName, collaboratorBuilder.getBeanDefinition());
+ ctx.refresh();
+
+ Messenger messenger = (Messenger) ctx.getBean(MESSENGER_BEAN_NAME);
+ assertEquals(MESSAGE_TEXT, messenger.getMessage());
+ // cool; now let's change the script and check the refresh behaviour...
+ pauseToLetRefreshDelayKickIn(DEFAULT_SECONDS_TO_PAUSE);
+ StaticScriptSource source = getScriptSource(ctx);
+ source.setScript(CHANGED_SCRIPT);
+ Messenger refreshedMessenger = (Messenger) ctx.getBean(MESSENGER_BEAN_NAME);
+ // the updated script surrounds the message in quotes before returning...
+ assertEquals(EXPECTED_CHANGED_MESSAGE_TEXT, refreshedMessenger.getMessage());
+ // ok, is this change reflected in the reference that the collaborator has?
+ DefaultMessengerService collaborator = (DefaultMessengerService) ctx.getBean(collaboratorBeanName);
+ assertEquals(EXPECTED_CHANGED_MESSAGE_TEXT, collaborator.getMessage());
+ }
+
+ public void testReferencesAcrossAContainerHierarchy() throws Exception {
+ GenericApplicationContext businessContext = new GenericApplicationContext();
+ businessContext.registerBeanDefinition("messenger", BeanDefinitionBuilder.rootBeanDefinition(StubMessenger.class).getBeanDefinition());
+ businessContext.refresh();
+
+ BeanDefinitionBuilder scriptedBeanBuilder = BeanDefinitionBuilder.rootBeanDefinition(GroovyScriptFactory.class);
+ scriptedBeanBuilder.addConstructorArgValue(DELEGATING_SCRIPT);
+ scriptedBeanBuilder.addPropertyReference("messenger", "messenger");
+
+ GenericApplicationContext presentationCtx = new GenericApplicationContext(businessContext);
+ presentationCtx.registerBeanDefinition("needsMessenger", scriptedBeanBuilder.getBeanDefinition());
+ presentationCtx.registerBeanDefinition("scriptProcessor", createScriptFactoryPostProcessor(true));
+ presentationCtx.refresh();
+ }
+
+ public void testScriptHavingAReferenceToAnotherBean() throws Exception {
+ // just tests that the (singleton) script-backed bean is able to be instantiated with references to its collaborators
+ new ClassPathXmlApplicationContext("org/springframework/scripting/support/groovyReferences.xml");
+ }
+
+ public void testForRefreshedScriptHavingErrorPickedUpOnFirstCall() throws Exception {
+ BeanDefinition processorBeanDefinition = createScriptFactoryPostProcessor(true);
+ BeanDefinition scriptedBeanDefinition = createScriptedGroovyBean();
+ BeanDefinitionBuilder collaboratorBuilder = BeanDefinitionBuilder.rootBeanDefinition(DefaultMessengerService.class);
+ collaboratorBuilder.addPropertyReference(MESSENGER_BEAN_NAME, MESSENGER_BEAN_NAME);
+
+ GenericApplicationContext ctx = new GenericApplicationContext();
+ ctx.registerBeanDefinition(PROCESSOR_BEAN_NAME, processorBeanDefinition);
+ ctx.registerBeanDefinition(MESSENGER_BEAN_NAME, scriptedBeanDefinition);
+ final String collaboratorBeanName = "collaborator";
+ ctx.registerBeanDefinition(collaboratorBeanName, collaboratorBuilder.getBeanDefinition());
+ ctx.refresh();
+
+ Messenger messenger = (Messenger) ctx.getBean(MESSENGER_BEAN_NAME);
+ assertEquals(MESSAGE_TEXT, messenger.getMessage());
+ // cool; now let's change the script and check the refresh behaviour...
+ pauseToLetRefreshDelayKickIn(DEFAULT_SECONDS_TO_PAUSE);
+ StaticScriptSource source = getScriptSource(ctx);
+ // needs The Sundays compiler; must NOT throw any exception here...
+ source.setScript("I keep hoping you are the same as me, and I'll send you letters and come to your house for tea");
+ Messenger refreshedMessenger = (Messenger) ctx.getBean(MESSENGER_BEAN_NAME);
+ try {
+ refreshedMessenger.getMessage();
+ fail("Must have thrown an Exception (invalid script)");
+ }
+ catch (FatalBeanException expected) {
+ assertTrue(expected.contains(ScriptCompilationException.class));
+ }
+ }
+
+ public void testPrototypeScriptedBean() throws Exception {
+ GenericApplicationContext ctx = new GenericApplicationContext();
+ ctx.registerBeanDefinition("messenger", BeanDefinitionBuilder.rootBeanDefinition(StubMessenger.class).getBeanDefinition());
+
+ BeanDefinitionBuilder scriptedBeanBuilder = BeanDefinitionBuilder.rootBeanDefinition(GroovyScriptFactory.class);
+ scriptedBeanBuilder.setSingleton(false);
+ scriptedBeanBuilder.addConstructorArgValue(DELEGATING_SCRIPT);
+ scriptedBeanBuilder.addPropertyReference("messenger", "messenger");
+
+ final String BEAN_WITH_DEPENDENCY_NAME = "needsMessenger";
+ ctx.registerBeanDefinition(BEAN_WITH_DEPENDENCY_NAME, scriptedBeanBuilder.getBeanDefinition());
+ ctx.registerBeanDefinition("scriptProcessor", createScriptFactoryPostProcessor(true));
+ ctx.refresh();
+
+ Messenger messenger1 = (Messenger) ctx.getBean(BEAN_WITH_DEPENDENCY_NAME);
+ Messenger messenger2 = (Messenger) ctx.getBean(BEAN_WITH_DEPENDENCY_NAME);
+ assertNotSame(messenger1, messenger2);
+ }
+
+ private static StaticScriptSource getScriptSource(GenericApplicationContext ctx) throws Exception {
+ ScriptFactoryPostProcessor processor = (ScriptFactoryPostProcessor) ctx.getBean(PROCESSOR_BEAN_NAME);
+ BeanDefinition bd = processor.scriptBeanFactory.getBeanDefinition("scriptedObject.messenger");
+ return (StaticScriptSource) bd.getConstructorArgumentValues().getIndexedArgumentValue(0, StaticScriptSource.class).getValue();
+ }
+
+ private static BeanDefinition createScriptFactoryPostProcessor(boolean isRefreshable) {
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ScriptFactoryPostProcessor.class);
+ if (isRefreshable) {
+ builder.addPropertyValue("defaultRefreshCheckDelay", new Long(1));
+ }
+ return builder.getBeanDefinition();
+ }
+
+ private static BeanDefinition createScriptedGroovyBean() {
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(GroovyScriptFactory.class);
+ builder.addConstructorArgValue("inline:package org.springframework.scripting;\n" +
+ "class GroovyMessenger implements Messenger {\n" +
+ " private String message = \"Bingo\"\n" +
+ " public String getMessage() {\n" +
+ " return this.message\n" +
+ " }\n" +
+ " public void setMessage(String message) {\n" +
+ " this.message = message\n" +
+ " }\n" +
+ "}");
+ builder.addPropertyValue("message", MESSAGE_TEXT);
+ return builder.getBeanDefinition();
+ }
+
+ private static void pauseToLetRefreshDelayKickIn(int secondsToPause) {
+ try {
+ Thread.sleep(secondsToPause * 1000);
+ }
+ catch (InterruptedException ignored) {
+ }
+ }
+
+
+ public static class DefaultMessengerService {
+
+ private Messenger messenger;
+
+ public void setMessenger(Messenger messenger) {
+ this.messenger = messenger;
+ }
+
+ public String getMessage() {
+ return this.messenger.getMessage();
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/support/StaticScriptSourceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/support/StaticScriptSourceTests.java
new file mode 100644
index 00000000000..c9e6babddc6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/support/StaticScriptSourceTests.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.scripting.support;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for the StaticScriptSource class.
+ *
+ * @author Rick Evans
+ */
+public final class StaticScriptSourceTests extends TestCase {
+
+ private static final String SCRIPT_TEXT = "print($hello) if $true;";
+
+
+ public void testCreateWithNullScript() throws Exception {
+ try {
+ new StaticScriptSource(null);
+ fail("Must have failed when passed a null script string.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testCreateWithEmptyScript() throws Exception {
+ try {
+ new StaticScriptSource("");
+ fail("Must have failed when passed an empty script string.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testCreateWithWhitespaceOnlyScript() throws Exception {
+ try {
+ new StaticScriptSource(" \n\n\t \t\n");
+ fail("Must have failed when passed a whitespace-only script string.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testIsModifiedIsTrueByDefault() throws Exception {
+ StaticScriptSource source = new StaticScriptSource(SCRIPT_TEXT);
+ assertTrue("Script must be flagged as 'modified' when first created.", source.isModified());
+ }
+
+ public void testGettingScriptTogglesIsModified() throws Exception {
+ StaticScriptSource source = new StaticScriptSource(SCRIPT_TEXT);
+ source.getScriptAsString();
+ assertFalse("Script must be flagged as 'not modified' after script is read.", source.isModified());
+ }
+
+ public void testGettingScriptViaToStringDoesNotToggleIsModified() throws Exception {
+ StaticScriptSource source = new StaticScriptSource(SCRIPT_TEXT);
+ boolean isModifiedState = source.isModified();
+ source.toString();
+ assertEquals("Script's 'modified' flag must not change after script is read via toString().", isModifiedState, source.isModified());
+ }
+
+ public void testIsModifiedToggledWhenDifferentScriptIsSet() throws Exception {
+ StaticScriptSource source = new StaticScriptSource(SCRIPT_TEXT);
+ source.setScript("use warnings;");
+ assertTrue("Script must be flagged as 'modified' when different script is passed in.", source.isModified());
+ }
+
+ public void testIsModifiedNotToggledWhenSameScriptIsSet() throws Exception {
+ StaticScriptSource source = new StaticScriptSource(SCRIPT_TEXT);
+ source.setScript(SCRIPT_TEXT);
+ assertFalse("Script must not be flagged as 'modified' when same script is passed in.", source.isModified());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/support/StubMessenger.java b/org.springframework.testsuite/src/test/java/org/springframework/scripting/support/StubMessenger.java
new file mode 100644
index 00000000000..3a4ffb70436
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/support/StubMessenger.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.scripting.support;
+
+import org.springframework.scripting.ConfigurableMessenger;
+
+/**
+ * @author Rick Evans
+ */
+public final class StubMessenger implements ConfigurableMessenger {
+
+ private String message = "I used to be smart... now I'm just stupid.";
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/scripting/support/groovyReferences.xml b/org.springframework.testsuite/src/test/java/org/springframework/scripting/support/groovyReferences.xml
new file mode 100644
index 00000000000..20bc7ee8c9b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/scripting/support/groovyReferences.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+ inline:package org.springframework.scripting;
+
+import org.springframework.scripting.Messenger
+
+class DelegatingMessenger implements Messenger {
+
+ private Messenger wrappedMessenger;
+
+ public String getMessage() {
+ this.wrappedMessenger.getMessage();
+ }
+
+ public void setMessenger(Messenger wrappedMessenger) {
+ this.wrappedMessenger = wrappedMessenger;
+ }
+}
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/test/AbstractSpr3350SingleSpringContextTests.java b/org.springframework.testsuite/src/test/java/org/springframework/test/AbstractSpr3350SingleSpringContextTests.java
new file mode 100644
index 00000000000..1bc157cba60
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/test/AbstractSpr3350SingleSpringContextTests.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2007 the original author or authors.
+ *
+ * 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.springframework.test;
+
+import org.springframework.beans.Pet;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.context.ApplicationContext;
+
+/**
+ * Abstract JUnit 3.8 based unit test which verifies new functionality requested
+ * in SPR-3350.
+ *
+ * @author Sam Brannen
+ * @since 2.5
+ */
+public abstract class AbstractSpr3350SingleSpringContextTests extends AbstractDependencyInjectionSpringContextTests {
+
+ private Pet cat;
+
+
+ public AbstractSpr3350SingleSpringContextTests() {
+ super();
+ }
+
+ public AbstractSpr3350SingleSpringContextTests(String name) {
+ super(name);
+ }
+
+ public final void setCat(final Pet cat) {
+ this.cat = cat;
+ }
+
+ /**
+ * Forcing concrete subclasses to provide a config path appropriate to the
+ * configured
+ * {@link #createBeanDefinitionReader(org.springframework.context.support.GenericApplicationContext) BeanDefinitionReader}.
+ *
+ * @see org.springframework.test.AbstractSingleSpringContextTests#getConfigPath()
+ */
+ protected abstract String getConfigPath();
+
+ /**
+ *
+ * Test which addresses the following issue raised in SPR-3350:
+ *
+ *
+ * {@link AbstractSingleSpringContextTests} always uses an
+ * {@link XmlBeanDefinitionReader} internally when creating the
+ * {@link ApplicationContext} inside
+ * {@link #createApplicationContext(String[])}. It would be nice to have
+ * the bean definition reader creation in a separate method so that
+ * subclasses can choose that individually without having to copy-n-paste
+ * code from createApplicationContext() to do the context creation and
+ * refresh. Consider JavaConfig where an Annotation based reader can be
+ * plugged in.
+ *
+ */
+ public final void testApplicationContextNotAutoCreated() {
+ assertNotNull("The cat field should have been autowired.", this.cat);
+ assertEquals("Garfield", this.cat.getName());
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/test/PropertiesBasedSpr3350SingleSpringContextTests-context.properties b/org.springframework.testsuite/src/test/java/org/springframework/test/PropertiesBasedSpr3350SingleSpringContextTests-context.properties
new file mode 100644
index 00000000000..307a4e93df2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/test/PropertiesBasedSpr3350SingleSpringContextTests-context.properties
@@ -0,0 +1,2 @@
+cat.(class)=org.springframework.beans.Pet
+cat.$0=Garfield
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/test/PropertiesBasedSpr3350SingleSpringContextTests.java b/org.springframework.testsuite/src/test/java/org/springframework/test/PropertiesBasedSpr3350SingleSpringContextTests.java
new file mode 100644
index 00000000000..d0da3c8e5ad
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/test/PropertiesBasedSpr3350SingleSpringContextTests.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2007 the original author or authors.
+ *
+ * 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.springframework.test;
+
+import org.springframework.beans.factory.support.BeanDefinitionReader;
+import org.springframework.beans.factory.support.PropertiesBeanDefinitionReader;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.context.support.GenericApplicationContext;
+
+/**
+ * Concrete implementation of {@link AbstractSpr3350SingleSpringContextTests}
+ * which configures a {@link PropertiesBeanDefinitionReader} instead of the
+ * default {@link XmlBeanDefinitionReader}.
+ *
+ * @author Sam Brannen
+ * @since 2.5
+ */
+public class PropertiesBasedSpr3350SingleSpringContextTests extends AbstractSpr3350SingleSpringContextTests {
+
+ public PropertiesBasedSpr3350SingleSpringContextTests() {
+ super();
+ }
+
+ public PropertiesBasedSpr3350SingleSpringContextTests(String name) {
+ super(name);
+ }
+
+ /**
+ * Creates a new {@link PropertiesBeanDefinitionReader}.
+ *
+ * @see org.springframework.test.AbstractSingleSpringContextTests#createBeanDefinitionReader(org.springframework.context.support.GenericApplicationContext)
+ */
+ protected final BeanDefinitionReader createBeanDefinitionReader(GenericApplicationContext context) {
+ return new PropertiesBeanDefinitionReader(context);
+ }
+
+ /**
+ * Returns
+ * "PropertiesBasedSpr3350SingleSpringContextTests-context.properties".
+ */
+ protected final String getConfigPath() {
+ return "PropertiesBasedSpr3350SingleSpringContextTests-context.properties";
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/test/Spr3264DependencyInjectionSpringContextTests.java b/org.springframework.testsuite/src/test/java/org/springframework/test/Spr3264DependencyInjectionSpringContextTests.java
new file mode 100644
index 00000000000..7cf3e27b328
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/test/Spr3264DependencyInjectionSpringContextTests.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2007 the original author or authors.
+ *
+ * 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.springframework.test;
+
+/**
+ * JUnit 3.8 based unit test which verifies new functionality requested in SPR-3264.
+ *
+ * @author Sam Brannen
+ * @since 2.5
+ * @see Spr3264SingleSpringContextTests
+ */
+public class Spr3264DependencyInjectionSpringContextTests extends AbstractDependencyInjectionSpringContextTests {
+
+ public Spr3264DependencyInjectionSpringContextTests() {
+ super();
+ }
+
+ public Spr3264DependencyInjectionSpringContextTests(String name) {
+ super(name);
+ }
+
+ /**
+ *
+ * Test which addresses the following issue raised in SPR-3264:
+ *
+ *
+ * AbstractDependencyInjectionSpringContextTests will try to apply
+ * auto-injection; this can be disabled but it has to be done manually
+ * inside the onSetUp...
+ *
+ */
+ public void testInjectDependenciesThrowsIllegalStateException() {
+
+ // Re-assert issues covered by Spr3264SingleSpringContextTests as a
+ // safety net.
+ assertNull("The ApplicationContext should NOT be automatically created if no 'locations' are defined.",
+ this.applicationContext);
+ assertEquals("Verifying the ApplicationContext load count.", 0, super.getLoadCount());
+
+ // Assert changes to AbstractDependencyInjectionSpringContextTests:
+ new AssertThrows(IllegalStateException.class) {
+
+ public void test() throws Exception {
+ Spr3264DependencyInjectionSpringContextTests.super.injectDependencies();
+ }
+ }.runTest();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/test/Spr3264SingleSpringContextTests.java b/org.springframework.testsuite/src/test/java/org/springframework/test/Spr3264SingleSpringContextTests.java
new file mode 100644
index 00000000000..d6286ecd1cb
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/test/Spr3264SingleSpringContextTests.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2007 the original author or authors.
+ *
+ * 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.springframework.test;
+
+/**
+ * JUnit 3.8 based unit test which verifies new functionality requested in SPR-3264.
+ *
+ * @author Sam Brannen
+ * @since 2.5
+ * @see Spr3264DependencyInjectionSpringContextTests
+ */
+public class Spr3264SingleSpringContextTests extends AbstractSingleSpringContextTests {
+
+ public Spr3264SingleSpringContextTests() {
+ super();
+ }
+
+ public Spr3264SingleSpringContextTests(String name) {
+ super(name);
+ }
+
+ /**
+ *
+ * Test which addresses the following issue raised in SPR-3264:
+ *
+ *
+ * AbstractSingleSpringContextTests always expects an application context to
+ * be created even if no files/locations are specified which can lead to NPE
+ * problems or force an appCtx to be instantiated even if not needed.
+ *
+ */
+ public void testApplicationContextNotAutoCreated() {
+ assertNull("The ApplicationContext should NOT be automatically created if no 'locations' are defined.",
+ super.applicationContext);
+ assertEquals("Verifying the ApplicationContext load count.", 0, super.getLoadCount());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/test/XmlBasedSpr3350SingleSpringContextTests-context.xml b/org.springframework.testsuite/src/test/java/org/springframework/test/XmlBasedSpr3350SingleSpringContextTests-context.xml
new file mode 100644
index 00000000000..72360454848
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/test/XmlBasedSpr3350SingleSpringContextTests-context.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/test/XmlBasedSpr3350SingleSpringContextTests.java b/org.springframework.testsuite/src/test/java/org/springframework/test/XmlBasedSpr3350SingleSpringContextTests.java
new file mode 100644
index 00000000000..8143c775115
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/test/XmlBasedSpr3350SingleSpringContextTests.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2007 the original author or authors.
+ *
+ * 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.springframework.test;
+
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+
+/**
+ * Concrete implementation of {@link AbstractSpr3350SingleSpringContextTests}
+ * which is based on the default {@link XmlBeanDefinitionReader}.
+ *
+ * @author Sam Brannen
+ * @since 2.5
+ */
+public class XmlBasedSpr3350SingleSpringContextTests extends AbstractSpr3350SingleSpringContextTests {
+
+ public XmlBasedSpr3350SingleSpringContextTests() {
+ super();
+ }
+
+ public XmlBasedSpr3350SingleSpringContextTests(String name) {
+ super(name);
+ }
+
+ /**
+ * Returns "XmlBasedSpr3350SingleSpringContextTests-context.xml".
+ */
+ protected final String getConfigPath() {
+ return "XmlBasedSpr3350SingleSpringContextTests-context.xml";
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/test/jdbc/JdbcTestUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/test/jdbc/JdbcTestUtilsTests.java
new file mode 100644
index 00000000000..35346bc253e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/test/jdbc/JdbcTestUtilsTests.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.test.jdbc;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Unit tests for {@link JdbcTestUtils}.
+ *
+ * @author Thomas Risberg
+ * @since 2.5.4
+ */
+public class JdbcTestUtilsTests extends TestCase {
+
+ public void testContainsDelimiters() {
+ assertTrue("test with ';' is wrong", !JdbcTestUtils.containsSqlScriptDelimiters("select 1\n select ';'", ';'));
+ assertTrue("test with delimiter ; is wrong", JdbcTestUtils.containsSqlScriptDelimiters("select 1; select 2", ';'));
+ assertTrue("test with '\\n' is wrong", !JdbcTestUtils.containsSqlScriptDelimiters("select 1; select '\\n\n';", '\n'));
+ assertTrue("test with delimiter \\n is wrong", JdbcTestUtils.containsSqlScriptDelimiters("select 1\n select 2", '\n'));
+ }
+
+ public void testSplitSqlScriptDelimitedWithSemicolon() {
+ String statement1 = "insert into customer (id, name) \n" +
+ "values (1, 'Rod ; Johnson'), (2, 'Adrian \n Collier')";
+ String statement2 = "insert into orders(id, order_date, customer_id) \n" +
+ "values (1, '2008-01-02', 2)";
+ String statement3 = "insert into orders(id, order_date, customer_id) " +
+ "values (1, '2008-01-02', 2)";
+ char delim = ';';
+ String script = statement1 + delim + statement2 + delim + statement3;
+ List statements = new ArrayList();
+ JdbcTestUtils.splitSqlScript(script, delim, statements);
+ assertEquals("wrong number of statements", 3, statements.size());
+ assertEquals("statement 1 not split correctly", statement1, statements.get(0));
+ assertEquals("statement 2 not split correctly", statement2, statements.get(1));
+ assertEquals("statement 3 not split correctly", statement3, statements.get(2));
+
+ }
+
+ public void testSplitSqlScriptDelimitedWithNewLine() {
+ String statement1 = "insert into customer (id, name) " +
+ "values (1, 'Rod ; Johnson'), (2, 'Adrian ; Collier')";
+ String statement2 = "insert into orders(id, order_date, customer_id) " +
+ "values (1, '2008-01-02', 2)";
+ String statement3 = "insert into orders(id, order_date, customer_id) " +
+ "values (1, '2008-01-02', 2)";
+ char delim = '\n';
+ String script = statement1 + delim + statement2 + delim + statement3;
+ List statements = new ArrayList();
+ JdbcTestUtils.splitSqlScript(script, delim, statements);
+ assertEquals("wrong number of statements", 3, statements.size());
+ assertEquals("statement 1 not split correctly", statement1, statements.get(0));
+ assertEquals("statement 2 not split correctly", statement2, statements.get(1));
+ assertEquals("statement 3 not split correctly", statement3, statements.get(2));
+
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/test/transaction/TransactionTestUtils.java b/org.springframework.testsuite/src/test/java/org/springframework/test/transaction/TransactionTestUtils.java
new file mode 100644
index 00000000000..fb7bd3bd626
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/test/transaction/TransactionTestUtils.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.test.transaction;
+
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+
+/**
+ * Collection of JDK 1.4+ utilities for tests involving transactions. Intended
+ * for internal use within the Spring testing suite.
+ *
+ *
All assert*() methods throw {@link AssertionError}s.
+ *
+ * @author Sam Brannen
+ * @since 2.5
+ */
+public abstract class TransactionTestUtils {
+
+ /**
+ * Convenience method for determining if a transaction is active for the
+ * current {@link Thread}.
+ * @return true if a transaction is currently active
+ */
+ public static boolean inTransaction() {
+ return TransactionSynchronizationManager.isActualTransactionActive();
+ }
+
+ /**
+ * Asserts whether or not a transaction is active for the current
+ * {@link Thread}.
+ * @param transactionExpected whether or not a transaction is expected
+ * @throws AssertionError if the supplied assertion fails
+ * @see #inTransaction()
+ */
+ public static void assertInTransaction(boolean transactionExpected) {
+ if (transactionExpected) {
+ assertCondition(inTransaction(), "The current thread should be associated with a transaction.");
+ }
+ else {
+ assertCondition(!inTransaction(), "The current thread should not be associated with a transaction");
+ }
+ }
+
+ /**
+ * Fails by throwing an AssertionError with the supplied
+ * message.
+ * @param message the exception message to use
+ * @see #assertCondition(boolean,String)
+ */
+ private static void fail(String message) throws AssertionError {
+ throw new AssertionError(message);
+ }
+
+ /**
+ * Assert the provided boolean condition, throwing
+ * AssertionError with the supplied message if
+ * the test result is false.
+ * @param condition a boolean expression
+ * @param message the exception message to use if the assertion fails
+ * @throws AssertionError if condition is false
+ * @see #fail(String)
+ */
+ private static void assertCondition(boolean condition, String message) throws AssertionError {
+ if (!condition) {
+ fail(message);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/test/util/ReflectionTestUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/test/util/ReflectionTestUtilsTests.java
new file mode 100644
index 00000000000..41b98ce8df7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/test/util/ReflectionTestUtilsTests.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.test.util;
+
+import junit.framework.TestCase;
+
+import org.springframework.test.AssertThrows;
+import org.springframework.test.util.subpackage.Person;
+
+/**
+ * JUnit 3.8 based unit tests for {@link ReflectionTestUtils}.
+ *
+ * @author Sam Brannen
+ * @author Juergen Hoeller
+ */
+public class ReflectionTestUtilsTests extends TestCase {
+
+ protected static final Float PI = new Float((float) 22 / 7);
+
+
+ public void testSetField() throws Exception {
+ final Person person = new Person();
+
+ // Standard
+
+ ReflectionTestUtils.setField(person, "id", new Long(99), long.class);
+ ReflectionTestUtils.setField(person, "name", "Tom");
+ ReflectionTestUtils.setField(person, "age", new Integer(42));
+ ReflectionTestUtils.setField(person, "eyeColor", "blue", String.class);
+ ReflectionTestUtils.setField(person, "likesPets", Boolean.TRUE);
+ ReflectionTestUtils.setField(person, "favoriteNumber", PI, Number.class);
+
+ assertEquals("Verifying that the person's ID (private field in a superclass) was set.", 99, person.getId());
+ assertEquals("Verifying that the person's name (protected field) was set.", "Tom", person.getName());
+ assertEquals("Verifying that the person's age (private field) was set.", 42, person.getAge());
+ assertEquals("Verifying that the person's eye color (package private field) was set.", "blue",
+ person.getEyeColor());
+ assertEquals("Verifying that the person's 'likes pets' flag (package private boolean field) was set.", true,
+ person.likesPets());
+ assertEquals("Verifying that the person's 'favorite number' (package field) was set.", PI,
+ person.getFavoriteNumber());
+
+ assertEquals(new Long(99), ReflectionTestUtils.getField(person, "id"));
+ assertEquals("Tom", ReflectionTestUtils.getField(person, "name"));
+ assertEquals(new Integer(42), ReflectionTestUtils.getField(person, "age"));
+ assertEquals("blue", ReflectionTestUtils.getField(person, "eyeColor"));
+ assertEquals(Boolean.TRUE, ReflectionTestUtils.getField(person, "likesPets"));
+ assertEquals(PI, ReflectionTestUtils.getField(person, "favoriteNumber"));
+
+ // Null - non-primitives
+
+ ReflectionTestUtils.setField(person, "name", null, String.class);
+ ReflectionTestUtils.setField(person, "eyeColor", null, String.class);
+ ReflectionTestUtils.setField(person, "favoriteNumber", null, Number.class);
+
+ assertNull("Verifying that the person's name (protected field) was set.", person.getName());
+ assertNull("Verifying that the person's eye color (package private field) was set.", person.getEyeColor());
+ assertNull("Verifying that the person's 'favorite number' (package field) was set.", person.getFavoriteNumber());
+
+ // Null - primitives
+
+ new AssertThrows(IllegalArgumentException.class,
+ "Calling setField() with NULL for a primitive type should throw an IllegalArgumentException.") {
+
+ public void test() throws Exception {
+ ReflectionTestUtils.setField(person, "id", null, long.class);
+ }
+ }.runTest();
+
+ new AssertThrows(IllegalArgumentException.class,
+ "Calling setField() with NULL for a primitive type should throw an IllegalArgumentException.") {
+
+ public void test() throws Exception {
+ ReflectionTestUtils.setField(person, "age", null, int.class);
+ }
+ }.runTest();
+
+ new AssertThrows(IllegalArgumentException.class,
+ "Calling setField() with NULL for a primitive type should throw an IllegalArgumentException.") {
+
+ public void test() throws Exception {
+ ReflectionTestUtils.setField(person, "likesPets", null, boolean.class);
+ }
+ }.runTest();
+ }
+
+ public void testInvokeSetterMethod() throws Exception {
+ final Person person = new Person();
+
+ // Standard - properties
+
+ ReflectionTestUtils.invokeSetterMethod(person, "id", new Long(99), long.class);
+ ReflectionTestUtils.invokeSetterMethod(person, "name", "Tom");
+ ReflectionTestUtils.invokeSetterMethod(person, "age", new Integer(42));
+ ReflectionTestUtils.invokeSetterMethod(person, "eyeColor", "blue", String.class);
+ ReflectionTestUtils.invokeSetterMethod(person, "likesPets", Boolean.TRUE);
+ ReflectionTestUtils.invokeSetterMethod(person, "favoriteNumber", PI, Number.class);
+
+ assertEquals("Verifying that the person's ID (protected method in a superclass) was set.", 99, person.getId());
+ assertEquals("Verifying that the person's name (private method) was set.", "Tom", person.getName());
+ assertEquals("Verifying that the person's age (protected method) was set.", 42, person.getAge());
+ assertEquals("Verifying that the person's eye color (package private method) was set.", "blue",
+ person.getEyeColor());
+ assertEquals("Verifying that the person's 'likes pets' flag (protected method for a boolean) was set.", true,
+ person.likesPets());
+ assertEquals("Verifying that the person's 'favorite number' (protected method for a Number) was set.", PI,
+ person.getFavoriteNumber());
+
+ assertEquals(new Long(99), ReflectionTestUtils.invokeGetterMethod(person, "id"));
+ assertEquals("Tom", ReflectionTestUtils.invokeGetterMethod(person, "name"));
+ assertEquals(new Integer(42), ReflectionTestUtils.invokeGetterMethod(person, "age"));
+ assertEquals("blue", ReflectionTestUtils.invokeGetterMethod(person, "eyeColor"));
+ assertEquals(Boolean.TRUE, ReflectionTestUtils.invokeGetterMethod(person, "likesPets"));
+ assertEquals(PI, ReflectionTestUtils.invokeGetterMethod(person, "favoriteNumber"));
+
+ // Standard - setter methods
+
+ ReflectionTestUtils.invokeSetterMethod(person, "setId", new Long(1), long.class);
+ ReflectionTestUtils.invokeSetterMethod(person, "setName", "Jerry", String.class);
+ ReflectionTestUtils.invokeSetterMethod(person, "setAge", new Integer(33), int.class);
+ ReflectionTestUtils.invokeSetterMethod(person, "setEyeColor", "green", String.class);
+ ReflectionTestUtils.invokeSetterMethod(person, "setLikesPets", Boolean.FALSE, boolean.class);
+ ReflectionTestUtils.invokeSetterMethod(person, "setFavoriteNumber", new Integer(42), Number.class);
+
+ assertEquals("Verifying that the person's ID (protected method in a superclass) was set.", 1, person.getId());
+ assertEquals("Verifying that the person's name (private method) was set.", "Jerry", person.getName());
+ assertEquals("Verifying that the person's age (protected method) was set.", 33, person.getAge());
+ assertEquals("Verifying that the person's eye color (package private method) was set.", "green",
+ person.getEyeColor());
+ assertEquals("Verifying that the person's 'likes pets' flag (protected method for a boolean) was set.", false,
+ person.likesPets());
+ assertEquals("Verifying that the person's 'favorite number' (protected method for a Number) was set.",
+ new Integer(42), person.getFavoriteNumber());
+
+ assertEquals(new Long(1), ReflectionTestUtils.invokeGetterMethod(person, "getId"));
+ assertEquals("Jerry", ReflectionTestUtils.invokeGetterMethod(person, "getName"));
+ assertEquals(new Integer(33), ReflectionTestUtils.invokeGetterMethod(person, "getAge"));
+ assertEquals("green", ReflectionTestUtils.invokeGetterMethod(person, "getEyeColor"));
+ assertEquals(Boolean.FALSE, ReflectionTestUtils.invokeGetterMethod(person, "likesPets"));
+ assertEquals(new Integer(42), ReflectionTestUtils.invokeGetterMethod(person, "getFavoriteNumber"));
+
+ // Null - non-primitives
+
+ ReflectionTestUtils.invokeSetterMethod(person, "name", null, String.class);
+ ReflectionTestUtils.invokeSetterMethod(person, "eyeColor", null, String.class);
+ ReflectionTestUtils.invokeSetterMethod(person, "favoriteNumber", null, Number.class);
+
+ assertNull("Verifying that the person's name (private method) was set.", person.getName());
+ assertNull("Verifying that the person's eye color (package private method) was set.", person.getEyeColor());
+ assertNull("Verifying that the person's 'favorite number' (protected method for a Number) was set.",
+ person.getFavoriteNumber());
+
+ // Null - primitives
+
+ new AssertThrows(RuntimeException.class,
+ "Calling invokeSetterMethod() with NULL for a primitive type should throw an IllegalArgumentException.") {
+
+ public void test() throws Exception {
+ ReflectionTestUtils.invokeSetterMethod(person, "id", null, long.class);
+ }
+ }.runTest();
+
+ new AssertThrows(RuntimeException.class,
+ "Calling invokeSetterMethod() with NULL for a primitive type should throw an IllegalArgumentException.") {
+
+ public void test() throws Exception {
+ ReflectionTestUtils.invokeSetterMethod(person, "age", null, int.class);
+ }
+ }.runTest();
+
+ new AssertThrows(RuntimeException.class,
+ "Calling invokeSetterMethod() with NULL for a primitive type should throw an IllegalArgumentException.") {
+
+ public void test() throws Exception {
+ ReflectionTestUtils.invokeSetterMethod(person, "likesPets", null, boolean.class);
+ }
+ }.runTest();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/test/util/subpackage/PersistentEntity.java b/org.springframework.testsuite/src/test/java/org/springframework/test/util/subpackage/PersistentEntity.java
new file mode 100644
index 00000000000..7831653bf3e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/test/util/subpackage/PersistentEntity.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2007 the original author or authors.
+ *
+ * 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.springframework.test.util.subpackage;
+
+/**
+ * Abstract base class for persistent entities; intended for use in
+ * unit tests.
+ *
+ * @author Sam Brannen
+ * @since 2.5
+ */
+public abstract class PersistentEntity {
+
+ private long id;
+
+
+ public final long getId() {
+ return this.id;
+ }
+
+ protected final void setId(long id) {
+ this.id = id;
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/test/util/subpackage/Person.java b/org.springframework.testsuite/src/test/java/org/springframework/test/util/subpackage/Person.java
new file mode 100644
index 00000000000..0fec1a026ea
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/test/util/subpackage/Person.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2007 the original author or authors.
+ *
+ * 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.springframework.test.util.subpackage;
+
+import org.springframework.core.style.ToStringCreator;
+
+/**
+ * Concrete subclass of {@link PersistentEntity} representing a person
+ * entity; intended for use in unit tests.
+ *
+ * @author Sam Brannen
+ * @since 2.5
+ */
+public class Person extends PersistentEntity {
+
+ protected String name;
+
+ private int age;
+
+ String eyeColor;
+
+ boolean likesPets = false;
+
+ private Number favoriteNumber;
+
+
+ public final String getName() {
+ return this.name;
+ }
+
+ private final void setName(final String name) {
+ this.name = name;
+ }
+
+ public final int getAge() {
+ return this.age;
+ }
+
+ protected final void setAge(final int age) {
+ this.age = age;
+ }
+
+ public final String getEyeColor() {
+ return this.eyeColor;
+ }
+
+ final void setEyeColor(final String eyeColor) {
+ this.eyeColor = eyeColor;
+ }
+
+ public final boolean likesPets() {
+ return this.likesPets;
+ }
+
+ protected final void setLikesPets(final boolean likesPets) {
+ this.likesPets = likesPets;
+ }
+
+ public final Number getFavoriteNumber() {
+ return this.favoriteNumber;
+ }
+
+ protected final void setFavoriteNumber(Number favoriteNumber) {
+ this.favoriteNumber = favoriteNumber;
+ }
+
+ public String toString() {
+ return new ToStringCreator(this)
+
+ .append("id", this.getId())
+
+ .append("name", this.name)
+
+ .append("age", this.age)
+
+ .append("eyeColor", this.eyeColor)
+
+ .append("likesPets", this.likesPets)
+
+ .append("favoriteNumber", this.favoriteNumber)
+
+ .toString();
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/CallCountingTransactionManager.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/CallCountingTransactionManager.java
new file mode 100644
index 00000000000..d5c2531fbde
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/CallCountingTransactionManager.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.transaction;
+
+import org.springframework.transaction.support.AbstractPlatformTransactionManager;
+import org.springframework.transaction.support.DefaultTransactionStatus;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public class CallCountingTransactionManager extends AbstractPlatformTransactionManager {
+
+ public TransactionDefinition lastDefinition;
+ public int begun;
+ public int commits;
+ public int rollbacks;
+ public int inflight;
+
+ protected Object doGetTransaction() {
+ return new Object();
+ }
+
+ protected void doBegin(Object transaction, TransactionDefinition definition) {
+ this.lastDefinition = definition;
+ ++begun;
+ ++inflight;
+ }
+
+ protected void doCommit(DefaultTransactionStatus status) {
+ ++commits;
+ --inflight;
+ }
+
+ protected void doRollback(DefaultTransactionStatus status) {
+ ++rollbacks;
+ --inflight;
+ }
+
+ public void clear() {
+ begun = commits = rollbacks = inflight = 0;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/JndiJtaTransactionManagerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/JndiJtaTransactionManagerTests.java
new file mode 100644
index 00000000000..c78fdcf43cb
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/JndiJtaTransactionManagerTests.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.transaction;
+
+import javax.transaction.Status;
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.mock.jndi.ExpectedLookupTemplate;
+import org.springframework.transaction.jta.JtaTransactionManager;
+import org.springframework.transaction.jta.UserTransactionAdapter;
+import org.springframework.transaction.support.TransactionCallbackWithoutResult;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+import org.springframework.transaction.support.TransactionTemplate;
+
+/**
+ * @author Juergen Hoeller
+ * @since 05.08.2005
+ */
+public class JndiJtaTransactionManagerTests extends TestCase {
+
+ public void testJtaTransactionManagerWithDefaultJndiLookups1() throws Exception {
+ doTestJtaTransactionManagerWithDefaultJndiLookups("java:comp/TransactionManager", true, true);
+ }
+
+ public void testJtaTransactionManagerWithDefaultJndiLookups2() throws Exception {
+ doTestJtaTransactionManagerWithDefaultJndiLookups("java:/TransactionManager", true, true);
+ }
+
+ public void testJtaTransactionManagerWithDefaultJndiLookupsAndNoTmFound() throws Exception {
+ doTestJtaTransactionManagerWithDefaultJndiLookups("java:/tm", false, true);
+ }
+
+ public void testJtaTransactionManagerWithDefaultJndiLookupsAndNoUtFound() throws Exception {
+ doTestJtaTransactionManagerWithDefaultJndiLookups("java:/TransactionManager", true, false);
+ }
+
+ private void doTestJtaTransactionManagerWithDefaultJndiLookups(String tmName, boolean tmFound, boolean defaultUt)
+ throws Exception {
+
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ if (defaultUt) {
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.commit();
+ utControl.setVoidCallable(1);
+ }
+ utControl.replay();
+
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ if (!defaultUt) {
+ tm.getStatus();
+ tmControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ tm.getStatus();
+ tmControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ tm.begin();
+ tmControl.setVoidCallable(1);
+ tm.commit();
+ tmControl.setVoidCallable(1);
+ }
+ tmControl.replay();
+
+ JtaTransactionManager ptm = new JtaTransactionManager();
+ ExpectedLookupTemplate jndiTemplate = new ExpectedLookupTemplate();
+ if (defaultUt) {
+ jndiTemplate.addObject("java:comp/UserTransaction", ut);
+ }
+ jndiTemplate.addObject(tmName, tm);
+ ptm.setJndiTemplate(jndiTemplate);
+ ptm.afterPropertiesSet();
+
+ if (tmFound) {
+ assertEquals(tm, ptm.getTransactionManager());
+ }
+ else {
+ assertNull(ptm.getTransactionManager());
+ }
+
+ if (defaultUt) {
+ assertEquals(ut, ptm.getUserTransaction());
+ }
+ else {
+ assertTrue(ptm.getUserTransaction() instanceof UserTransactionAdapter);
+ UserTransactionAdapter uta = (UserTransactionAdapter) ptm.getUserTransaction();
+ assertEquals(tm, uta.getTransactionManager());
+ }
+
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ assertTrue(!TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ }
+ });
+ assertTrue(!TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ utControl.verify();
+ tmControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithCustomJndiLookups() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.commit();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+
+ JtaTransactionManager ptm = new JtaTransactionManager();
+ ptm.setUserTransactionName("jndi-ut");
+ ptm.setTransactionManagerName("jndi-tm");
+ ExpectedLookupTemplate jndiTemplate = new ExpectedLookupTemplate();
+ jndiTemplate.addObject("jndi-ut", ut);
+ jndiTemplate.addObject("jndi-tm", tm);
+ ptm.setJndiTemplate(jndiTemplate);
+ ptm.afterPropertiesSet();
+
+ assertEquals(ut, ptm.getUserTransaction());
+ assertEquals(tm, ptm.getTransactionManager());
+
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ assertTrue(!TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ }
+ });
+ assertTrue(!TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithNotCacheUserTransaction() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.commit();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ MockControl ut2Control = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut2 = (UserTransaction) ut2Control.getMock();
+ ut2.getStatus();
+ ut2Control.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut2.getStatus();
+ ut2Control.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut2.begin();
+ ut2Control.setVoidCallable(1);
+ ut2.commit();
+ ut2Control.setVoidCallable(1);
+ ut2Control.replay();
+
+ JtaTransactionManager ptm = new JtaTransactionManager();
+ ptm.setJndiTemplate(new ExpectedLookupTemplate("java:comp/UserTransaction", ut));
+ ptm.setCacheUserTransaction(false);
+ ptm.afterPropertiesSet();
+
+ assertEquals(ut, ptm.getUserTransaction());
+
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ assertEquals(JtaTransactionManager.SYNCHRONIZATION_ALWAYS, ptm.getTransactionSynchronization());
+ assertTrue(!TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ }
+ });
+
+ ptm.setJndiTemplate(new ExpectedLookupTemplate("java:comp/UserTransaction", ut2));
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ }
+ });
+ assertTrue(!TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ utControl.verify();
+ ut2Control.verify();
+ }
+
+ /**
+ * Prevent any side-effects due to this test modifying ThreadLocals that might
+ * affect subsequent tests when all tests are run in the same JVM, as with Eclipse.
+ */
+ protected void tearDown() {
+ assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertNull(TransactionSynchronizationManager.getCurrentTransactionName());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/JtaTransactionManagerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/JtaTransactionManagerTests.java
new file mode 100644
index 00000000000..6d23128081e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/JtaTransactionManagerTests.java
@@ -0,0 +1,1574 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.transaction;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.dao.OptimisticLockingFailureException;
+import org.springframework.transaction.jta.JtaTransactionManager;
+import org.springframework.transaction.support.DefaultTransactionDefinition;
+import org.springframework.transaction.support.TransactionCallbackWithoutResult;
+import org.springframework.transaction.support.TransactionSynchronization;
+import org.springframework.transaction.support.TransactionSynchronizationAdapter;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+import org.springframework.transaction.support.TransactionTemplate;
+
+/**
+ * @author Juergen Hoeller
+ * @since 12.05.2003
+ */
+public class JtaTransactionManagerTests extends TestCase {
+
+ public void testJtaTransactionManagerWithCommit() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.commit();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ MockControl synchControl = MockControl.createControl(TransactionSynchronization.class);
+ final TransactionSynchronization synch = (TransactionSynchronization) synchControl.getMock();
+ synch.beforeCommit(false);
+ synchControl.setVoidCallable(1);
+ synch.beforeCompletion();
+ synchControl.setVoidCallable(1);
+ synch.afterCommit();
+ synchControl.setVoidCallable(1);
+ synch.afterCompletion(TransactionSynchronization.STATUS_COMMITTED);
+ synchControl.setVoidCallable(1);
+ synchControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setName("txName");
+
+ assertEquals(JtaTransactionManager.SYNCHRONIZATION_ALWAYS, ptm.getTransactionSynchronization());
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertNull(TransactionSynchronizationManager.getCurrentTransactionName());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ TransactionSynchronizationManager.registerSynchronization(synch);
+ assertEquals("txName", TransactionSynchronizationManager.getCurrentTransactionName());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertNull(TransactionSynchronizationManager.getCurrentTransactionName());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ utControl.verify();
+ synchControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithCommitAndSynchronizationOnActual() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.commit();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ MockControl synchControl = MockControl.createControl(TransactionSynchronization.class);
+ final TransactionSynchronization synch = (TransactionSynchronization) synchControl.getMock();
+ synch.beforeCommit(false);
+ synchControl.setVoidCallable(1);
+ synch.beforeCompletion();
+ synchControl.setVoidCallable(1);
+ synch.afterCommit();
+ synchControl.setVoidCallable(1);
+ synch.afterCompletion(TransactionSynchronization.STATUS_COMMITTED);
+ synchControl.setVoidCallable(1);
+ synchControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ ptm.setTransactionSynchronization(JtaTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ TransactionSynchronizationManager.registerSynchronization(synch);
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ synchControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithCommitAndSynchronizationNever() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.commit();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ ptm.setTransactionSynchronization(JtaTransactionManager.SYNCHRONIZATION_NEVER);
+ ptm.afterPropertiesSet();
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithRollback() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.setTransactionTimeout(10);
+ utControl.setVoidCallable(1);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ ut.rollback();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ MockControl synchControl = MockControl.createControl(TransactionSynchronization.class);
+ final TransactionSynchronization synch = (TransactionSynchronization) synchControl.getMock();
+ synch.beforeCompletion();
+ synchControl.setVoidCallable(1);
+ synch.afterCompletion(TransactionSynchronization.STATUS_ROLLED_BACK);
+ synchControl.setVoidCallable(1);
+ synchControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setTimeout(10);
+ tt.setName("txName");
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertNull(TransactionSynchronizationManager.getCurrentTransactionName());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ TransactionSynchronizationManager.registerSynchronization(synch);
+ assertEquals("txName", TransactionSynchronizationManager.getCurrentTransactionName());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ status.setRollbackOnly();
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertNull(TransactionSynchronizationManager.getCurrentTransactionName());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ utControl.verify();
+ synchControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithRollbackAndSynchronizationOnActual() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.setTransactionTimeout(10);
+ utControl.setVoidCallable(1);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ ut.rollback();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ MockControl synchControl = MockControl.createControl(TransactionSynchronization.class);
+ final TransactionSynchronization synch = (TransactionSynchronization) synchControl.getMock();
+ synch.beforeCompletion();
+ synchControl.setVoidCallable(1);
+ synch.afterCompletion(TransactionSynchronization.STATUS_ROLLED_BACK);
+ synchControl.setVoidCallable(1);
+ synchControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ ptm.setTransactionSynchronization(JtaTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
+ tt.setTimeout(10);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ TransactionSynchronizationManager.registerSynchronization(synch);
+ status.setRollbackOnly();
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ synchControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithRollbackAndSynchronizationNever() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.setTransactionTimeout(10);
+ utControl.setVoidCallable(1);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ ut.rollback();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ ptm.setTransactionSynchronizationName("SYNCHRONIZATION_NEVER");
+ tt.setTimeout(10);
+ ptm.afterPropertiesSet();
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ status.setRollbackOnly();
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithExistingTransactionAndRollbackOnly() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 3);
+ ut.setRollbackOnly();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ MockControl synchControl = MockControl.createControl(TransactionSynchronization.class);
+ final TransactionSynchronization synch = (TransactionSynchronization) synchControl.getMock();
+ synch.beforeCompletion();
+ synchControl.setVoidCallable(1);
+ synch.afterCompletion(TransactionSynchronization.STATUS_UNKNOWN);
+ synchControl.setVoidCallable(1);
+ synchControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ TransactionSynchronizationManager.registerSynchronization(synch);
+ status.setRollbackOnly();
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ synchControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithExistingTransactionAndException() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 3);
+ ut.setRollbackOnly();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ MockControl synchControl = MockControl.createControl(TransactionSynchronization.class);
+ final TransactionSynchronization synch = (TransactionSynchronization) synchControl.getMock();
+ synch.beforeCompletion();
+ synchControl.setVoidCallable(1);
+ synch.afterCompletion(TransactionSynchronization.STATUS_UNKNOWN);
+ synchControl.setVoidCallable(1);
+ synchControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ try {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ TransactionSynchronizationManager.registerSynchronization(synch);
+ throw new IllegalStateException("I want a rollback");
+ }
+ });
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ synchControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithExistingTransactionAndCommitException() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 3);
+ ut.setRollbackOnly();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ MockControl synchControl = MockControl.createControl(TransactionSynchronization.class);
+ final TransactionSynchronization synch = (TransactionSynchronization) synchControl.getMock();
+ synch.beforeCommit(false);
+ synchControl.setThrowable(new OptimisticLockingFailureException(""));
+ synch.beforeCompletion();
+ synchControl.setVoidCallable(1);
+ synch.afterCompletion(TransactionSynchronization.STATUS_UNKNOWN);
+ synchControl.setVoidCallable(1);
+ synchControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ try {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ TransactionSynchronizationManager.registerSynchronization(synch);
+ }
+ });
+ fail("Should have thrown OptimisticLockingFailureException");
+ }
+ catch (OptimisticLockingFailureException ex) {
+ // expected
+ }
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ synchControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithExistingTransactionAndRollbackOnlyAndNoGlobalRollback() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 3);
+ ut.setRollbackOnly();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ MockControl synchControl = MockControl.createControl(TransactionSynchronization.class);
+ final TransactionSynchronization synch = (TransactionSynchronization) synchControl.getMock();
+ synch.beforeCompletion();
+ synchControl.setVoidCallable(1);
+ synch.afterCompletion(TransactionSynchronization.STATUS_UNKNOWN);
+ synchControl.setVoidCallable(1);
+ synchControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ ptm.setGlobalRollbackOnParticipationFailure(false);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ TransactionSynchronizationManager.registerSynchronization(synch);
+ status.setRollbackOnly();
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ synchControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithExistingTransactionAndExceptionAndNoGlobalRollback() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ utControl.replay();
+
+ MockControl synchControl = MockControl.createControl(TransactionSynchronization.class);
+ final TransactionSynchronization synch = (TransactionSynchronization) synchControl.getMock();
+ synch.beforeCompletion();
+ synchControl.setVoidCallable(1);
+ synch.afterCompletion(TransactionSynchronization.STATUS_UNKNOWN);
+ synchControl.setVoidCallable(1);
+ synchControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ ptm.setGlobalRollbackOnParticipationFailure(false);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ try {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ TransactionSynchronizationManager.registerSynchronization(synch);
+ throw new IllegalStateException("I want a rollback");
+ }
+ });
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ synchControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithExistingTransactionAndJtaSynchronization() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockJtaTransaction tx = new MockJtaTransaction();
+
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 3);
+ ut.setRollbackOnly();
+ utControl.setVoidCallable(1);
+ tm.getTransaction();
+ tmControl.setReturnValue(tx, 1);
+
+ utControl.replay();
+ tmControl.replay();
+
+ MockControl synchControl = MockControl.createControl(TransactionSynchronization.class);
+ final TransactionSynchronization synch = (TransactionSynchronization) synchControl.getMock();
+ synch.beforeCompletion();
+ synchControl.setVoidCallable(1);
+ synch.afterCompletion(TransactionSynchronization.STATUS_ROLLED_BACK);
+ synchControl.setVoidCallable(1);
+ synchControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut, tm);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ TransactionSynchronizationManager.registerSynchronization(synch);
+ status.setRollbackOnly();
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertNotNull(tx.getSynchronization());
+ tx.getSynchronization().beforeCompletion();
+ tx.getSynchronization().afterCompletion(Status.STATUS_ROLLEDBACK);
+
+ utControl.verify();
+ tmControl.verify();
+ synchControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithExistingTransactionAndSynchronizationOnActual() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 3);
+ ut.setRollbackOnly();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ MockControl synchControl = MockControl.createControl(TransactionSynchronization.class);
+ final TransactionSynchronization synch = (TransactionSynchronization) synchControl.getMock();
+ synch.beforeCompletion();
+ synchControl.setVoidCallable(1);
+ synch.afterCompletion(TransactionSynchronization.STATUS_UNKNOWN);
+ synchControl.setVoidCallable(1);
+ synchControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ ptm.setTransactionSynchronization(JtaTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ TransactionSynchronizationManager.registerSynchronization(synch);
+ status.setRollbackOnly();
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ synchControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithExistingTransactionAndSynchronizationNever() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.setRollbackOnly();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ ptm.setTransactionSynchronization(JtaTransactionManager.SYNCHRONIZATION_NEVER);
+ ptm.afterPropertiesSet();
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ status.setRollbackOnly();
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithExistingAndPropagationSupports() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 3);
+ ut.setRollbackOnly();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ MockControl synchControl = MockControl.createControl(TransactionSynchronization.class);
+ final TransactionSynchronization synch = (TransactionSynchronization) synchControl.getMock();
+ synch.beforeCompletion();
+ synchControl.setVoidCallable(1);
+ synch.afterCompletion(TransactionSynchronization.STATUS_UNKNOWN);
+ synchControl.setVoidCallable(1);
+ synchControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ TransactionSynchronizationManager.registerSynchronization(synch);
+ status.setRollbackOnly();
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ synchControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithPropagationSupports() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ utControl.replay();
+
+ MockControl synchControl = MockControl.createControl(TransactionSynchronization.class);
+ final TransactionSynchronization synch = (TransactionSynchronization) synchControl.getMock();
+ synch.beforeCompletion();
+ synchControl.setVoidCallable(1);
+ synch.afterCompletion(TransactionSynchronization.STATUS_ROLLED_BACK);
+ synchControl.setVoidCallable(1);
+ synchControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ TransactionSynchronizationManager.registerSynchronization(synch);
+ status.setRollbackOnly();
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ synchControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithPropagationSupportsAndSynchronizationOnActual() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ utControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ ptm.setTransactionSynchronization(JtaTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
+ ptm.afterPropertiesSet();
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ status.setRollbackOnly();
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithPropagationSupportsAndSynchronizationNever() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ utControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ ptm.setTransactionSynchronization(JtaTransactionManager.SYNCHRONIZATION_NEVER);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
+ ptm.afterPropertiesSet();
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ status.setRollbackOnly();
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithPropagationNotSupported() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ tm.suspend();
+ tmControl.setReturnValue(tx, 1);
+ tm.resume(tx);
+ tmControl.setVoidCallable(1);
+ utControl.replay();
+ tmControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut, tm);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ status.setRollbackOnly();
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ tmControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithPropagationRequiresNew() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 5);
+ tm.suspend();
+ tmControl.setReturnValue(tx, 1);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.commit();
+ utControl.setVoidCallable(1);
+ tm.resume(tx);
+ tmControl.setVoidCallable(1);
+ ut.commit();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+ tmControl.replay();
+
+ final JtaTransactionManager ptm = newJtaTransactionManager(ut, tm);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ tt.setName("txName");
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertEquals("txName", TransactionSynchronizationManager.getCurrentTransactionName());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ TransactionTemplate tt2 = new TransactionTemplate(ptm);
+ tt2.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ tt2.setReadOnly(true);
+ tt2.setName("txName2");
+ tt2.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertEquals("txName2", TransactionSynchronizationManager.getCurrentTransactionName());
+ assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ }
+ });
+
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertEquals("txName", TransactionSynchronizationManager.getCurrentTransactionName());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ tmControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithPropagationRequiresNewWithinSupports() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 2);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.commit();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ final JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+
+ TransactionTemplate tt2 = new TransactionTemplate(ptm);
+ tt2.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ tt2.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ }
+ });
+
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithPropagationRequiresNewAndExisting() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 3);
+ tm.suspend();
+ tmControl.setReturnValue(tx, 1);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.commit();
+ utControl.setVoidCallable(1);
+ tm.resume(tx);
+ tmControl.setVoidCallable(1);
+ utControl.replay();
+ tmControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut, tm);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ tmControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithPropagationRequiresNewAndExistingWithSuspendException() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ tm.suspend();
+ tmControl.setThrowable(new SystemException());
+ utControl.replay();
+ tmControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut, tm);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ try {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ }
+ });
+ fail("Should have thrown TransactionSystemException");
+ }
+ catch (TransactionSystemException ex) {
+ // expected
+ }
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ tmControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithPropagationRequiresNewAndExistingWithBeginException() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ tm.suspend();
+ tmControl.setReturnValue(tx, 1);
+ ut.begin();
+ utControl.setThrowable(new SystemException());
+ tm.resume(tx);
+ tmControl.setVoidCallable(1);
+ utControl.replay();
+ tmControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut, tm);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ try {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ }
+ });
+ fail("Should have thrown CannotCreateTransactionException");
+ }
+ catch (CannotCreateTransactionException ex) {
+ // expected
+ }
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ tmControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithPropagationRequiresNewAndAdapter() throws Exception {
+ MockControl tmControl = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmControl.getMock();
+ MockControl txControl = MockControl.createControl(Transaction.class);
+ Transaction tx = (Transaction) txControl.getMock();
+ tm.getStatus();
+ tmControl.setReturnValue(Status.STATUS_ACTIVE, 3);
+ tm.suspend();
+ tmControl.setReturnValue(tx, 1);
+ tm.begin();
+ tmControl.setVoidCallable(1);
+ tm.commit();
+ tmControl.setVoidCallable(1);
+ tm.resume(tx);
+ tmControl.setVoidCallable(1);
+ tmControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(tm);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ }
+ });
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ tmControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithPropagationRequiresNewAndSuspensionNotSupported() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ utControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ try {
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ }
+ });
+ fail("Should have thrown TransactionSuspensionNotSupportedException");
+ }
+ catch (TransactionSuspensionNotSupportedException ex) {
+ // expected
+ }
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithIsolationLevel() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ utControl.replay();
+
+ try {
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ }
+ });
+ fail("Should have thrown InvalidIsolationLevelException");
+ }
+ catch (InvalidIsolationLevelException ex) {
+ // expected
+ }
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithSystemExceptionOnIsExisting() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setThrowable(new SystemException("system exception"));
+ utControl.replay();
+
+ try {
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ }
+ });
+ fail("Should have thrown TransactionSystemException");
+ }
+ catch (TransactionSystemException ex) {
+ // expected
+ }
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithNestedBegin() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 3);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.commit();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ }
+ });
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithNotSupportedExceptionOnNestedBegin() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ ut.begin();
+ utControl.setThrowable(new NotSupportedException("not supported"));
+ utControl.replay();
+
+ try {
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ }
+ });
+ fail("Should have thrown NestedTransactionNotSupportedException");
+ }
+ catch (NestedTransactionNotSupportedException ex) {
+ // expected
+ }
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithUnsupportedOperationExceptionOnNestedBegin() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ ut.begin();
+ utControl.setThrowable(new UnsupportedOperationException("not supported"));
+ utControl.replay();
+
+ try {
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ }
+ });
+ fail("Should have thrown NestedTransactionNotSupportedException");
+ }
+ catch (NestedTransactionNotSupportedException ex) {
+ // expected
+ }
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithSystemExceptionOnBegin() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.begin();
+ utControl.setThrowable(new SystemException("system exception"));
+ utControl.replay();
+
+ try {
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ }
+ });
+ fail("Should have thrown CannotCreateTransactionException");
+ }
+ catch (CannotCreateTransactionException ex) {
+ // expected
+ }
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithRollbackExceptionOnCommit() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.commit();
+ utControl.setThrowable(new RollbackException("unexpected rollback"));
+ utControl.replay();
+
+ try {
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
+ public void afterCompletion(int status) {
+ assertTrue("Correct completion status", status == TransactionSynchronization.STATUS_ROLLED_BACK);
+ }
+ });
+ }
+ });
+ fail("Should have thrown UnexpectedRollbackException");
+ }
+ catch (UnexpectedRollbackException ex) {
+ // expected
+ }
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithNoExceptionOnGlobalRollbackOnly() throws Exception {
+ doTestJtaTransactionManagerWithNoExceptionOnGlobalRollbackOnly(false);
+ }
+
+ public void testJtaTransactionManagerWithNoExceptionOnGlobalRollbackOnlyAndFailEarly() throws Exception {
+ doTestJtaTransactionManagerWithNoExceptionOnGlobalRollbackOnly(true);
+ }
+
+ private void doTestJtaTransactionManagerWithNoExceptionOnGlobalRollbackOnly(boolean failEarly) throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_MARKED_ROLLBACK, 3);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ if (failEarly) {
+ ut.rollback();
+ }
+ else {
+ ut.commit();
+ }
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ JtaTransactionManager tm = newJtaTransactionManager(ut);
+ if (failEarly) {
+ tm.setFailEarlyOnGlobalRollbackOnly(true);
+ }
+
+ TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition());
+ boolean outerTransactionBoundaryReached = false;
+ try {
+ assertTrue("Is new transaction", ts.isNewTransaction());
+
+ TransactionTemplate tt = new TransactionTemplate(tm);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
+ public void afterCompletion(int status) {
+ assertTrue("Correct completion status", status == TransactionSynchronization.STATUS_ROLLED_BACK);
+ }
+ });
+ }
+ });
+
+ outerTransactionBoundaryReached = true;
+ tm.commit(ts);
+
+ fail("Should have thrown UnexpectedRollbackException");
+ }
+ catch (UnexpectedRollbackException ex) {
+ // expected
+ if (!outerTransactionBoundaryReached) {
+ tm.rollback(ts);
+ }
+ if (failEarly) {
+ assertFalse(outerTransactionBoundaryReached);
+ }
+ else {
+ assertTrue(outerTransactionBoundaryReached);
+ }
+ }
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithHeuristicMixedExceptionOnCommit() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.commit();
+ utControl.setThrowable(new HeuristicMixedException("heuristic exception"));
+ utControl.replay();
+
+ try {
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
+ public void afterCompletion(int status) {
+ assertTrue("Correct completion status", status == TransactionSynchronization.STATUS_UNKNOWN);
+ }
+ });
+ }
+ });
+ fail("Should have thrown HeuristicCompletionException");
+ }
+ catch (HeuristicCompletionException ex) {
+ // expected
+ assertTrue(ex.getOutcomeState() == HeuristicCompletionException.STATE_MIXED);
+ }
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithHeuristicRollbackExceptionOnCommit() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.commit();
+ utControl.setThrowable(new HeuristicRollbackException("heuristic exception"));
+ utControl.replay();
+
+ try {
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
+ public void afterCompletion(int status) {
+ assertTrue("Correct completion status", status == TransactionSynchronization.STATUS_UNKNOWN);
+ }
+ });
+ }
+ });
+ fail("Should have thrown HeuristicCompletionException");
+ }
+ catch (HeuristicCompletionException ex) {
+ // expected
+ assertTrue(ex.getOutcomeState() == HeuristicCompletionException.STATE_ROLLED_BACK);
+ }
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithSystemExceptionOnCommit() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.commit();
+ utControl.setThrowable(new SystemException("system exception"));
+ utControl.replay();
+
+ try {
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ // something transactional
+ TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
+ public void afterCompletion(int status) {
+ assertTrue("Correct completion status", status == TransactionSynchronization.STATUS_UNKNOWN);
+ }
+ });
+ }
+ });
+ fail("Should have thrown TransactionSystemException");
+ }
+ catch (TransactionSystemException ex) {
+ // expected
+ }
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithSystemExceptionOnRollback() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ ut.rollback();
+ utControl.setThrowable(new SystemException("system exception"));
+ utControl.replay();
+
+ try {
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
+ public void afterCompletion(int status) {
+ assertTrue("Correct completion status", status == TransactionSynchronization.STATUS_UNKNOWN);
+ }
+ });
+ status.setRollbackOnly();
+ }
+ });
+ fail("Should have thrown TransactionSystemException");
+ }
+ catch (TransactionSystemException ex) {
+ // expected
+ }
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithIllegalStateExceptionOnRollbackOnly() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 3);
+ ut.setRollbackOnly();
+ utControl.setThrowable(new IllegalStateException("no existing transaction"));
+ utControl.replay();
+
+ try {
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ status.setRollbackOnly();
+ }
+ });
+ fail("Should have thrown TransactionSystemException");
+ }
+ catch (TransactionSystemException ex) {
+ // expected
+ }
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithSystemExceptionOnRollbackOnly() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 3);
+ ut.setRollbackOnly();
+ utControl.setThrowable(new SystemException("system exception"));
+ utControl.replay();
+
+ try {
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ TransactionTemplate tt = new TransactionTemplate(ptm);
+ tt.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ status.setRollbackOnly();
+ TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
+ public void afterCompletion(int status) {
+ assertTrue("Correct completion status", status == TransactionSynchronization.STATUS_UNKNOWN);
+ }
+ });
+ }
+ });
+ fail("Should have thrown TransactionSystemException");
+ }
+ catch (TransactionSystemException ex) {
+ // expected
+ }
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithDoubleCommit() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.commit();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ TransactionStatus status = ptm.getTransaction(new DefaultTransactionDefinition());
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ // first commit
+ ptm.commit(status);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ try {
+ // second commit attempt
+ ptm.commit(status);
+ fail("Should have thrown IllegalTransactionStateException");
+ }
+ catch (IllegalTransactionStateException ex) {
+ // expected
+ }
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithDoubleRollback() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ ut.rollback();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ TransactionStatus status = ptm.getTransaction(new DefaultTransactionDefinition());
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ // first rollback
+ ptm.rollback(status);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ try {
+ // second rollback attempt
+ ptm.rollback(status);
+ fail("Should have thrown IllegalTransactionStateException");
+ }
+ catch (IllegalTransactionStateException ex) {
+ // expected
+ }
+
+ utControl.verify();
+ }
+
+ public void testJtaTransactionManagerWithRollbackAndCommit() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
+ ut.rollback();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ JtaTransactionManager ptm = newJtaTransactionManager(ut);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ TransactionStatus status = ptm.getTransaction(new DefaultTransactionDefinition());
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ // first: rollback
+ ptm.rollback(status);
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ try {
+ // second: commit attempt
+ ptm.commit(status);
+ fail("Should have thrown IllegalTransactionStateException");
+ }
+ catch (IllegalTransactionStateException ex) {
+ // expected
+ }
+
+ utControl.verify();
+ }
+
+
+ protected JtaTransactionManager newJtaTransactionManager(UserTransaction ut) {
+ return new JtaTransactionManager(ut);
+ }
+
+ protected JtaTransactionManager newJtaTransactionManager(TransactionManager tm) {
+ return new JtaTransactionManager(tm);
+ }
+
+ protected JtaTransactionManager newJtaTransactionManager(UserTransaction ut, TransactionManager tm) {
+ return new JtaTransactionManager(ut, tm);
+ }
+
+
+ /**
+ * Prevent any side-effects due to this test modifying ThreadLocals that might
+ * affect subsequent tests when all tests are run in the same JVM, as with Eclipse.
+ */
+ protected void tearDown() {
+ assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertNull(TransactionSynchronizationManager.getCurrentTransactionName());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertNull(TransactionSynchronizationManager.getCurrentTransactionIsolationLevel());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/MockCallbackPreferringTransactionManager.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/MockCallbackPreferringTransactionManager.java
new file mode 100644
index 00000000000..f810e715b9b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/MockCallbackPreferringTransactionManager.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.transaction;
+
+import org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager;
+import org.springframework.transaction.support.SimpleTransactionStatus;
+import org.springframework.transaction.support.TransactionCallback;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class MockCallbackPreferringTransactionManager implements CallbackPreferringPlatformTransactionManager {
+
+ private TransactionDefinition definition;
+
+ private TransactionStatus status;
+
+
+ public Object execute(TransactionDefinition definition, TransactionCallback callback) throws TransactionException {
+ this.definition = definition;
+ this.status = new SimpleTransactionStatus();
+ return callback.doInTransaction(this.status);
+ }
+
+ public TransactionDefinition getDefinition() {
+ return this.definition;
+ }
+
+ public TransactionStatus getStatus() {
+ return this.status;
+ }
+
+
+ public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void commit(TransactionStatus status) throws TransactionException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void rollback(TransactionStatus status) throws TransactionException {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/MockJtaTransaction.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/MockJtaTransaction.java
new file mode 100644
index 00000000000..c9c8709c48b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/MockJtaTransaction.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.transaction;
+
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.xa.XAResource;
+
+/**
+ * @author Juergen Hoeller
+ * @since 31.08.2004
+ */
+public class MockJtaTransaction implements javax.transaction.Transaction {
+
+ private Synchronization synchronization;
+
+ public int getStatus() {
+ return Status.STATUS_ACTIVE;
+ }
+
+ public void registerSynchronization(Synchronization synchronization) {
+ this.synchronization = synchronization;
+ }
+
+ public Synchronization getSynchronization() {
+ return synchronization;
+ }
+
+ public boolean enlistResource(XAResource xaResource) {
+ return false;
+ }
+
+ public boolean delistResource(XAResource xaResource, int i) {
+ return false;
+ }
+
+ public void commit() {
+ }
+
+ public void rollback() {
+ }
+
+ public void setRollbackOnly() {
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/TestTransactionManager.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/TestTransactionManager.java
new file mode 100644
index 00000000000..f64862b9389
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/TestTransactionManager.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.transaction;
+
+import org.springframework.transaction.support.AbstractPlatformTransactionManager;
+import org.springframework.transaction.support.DefaultTransactionStatus;
+
+/**
+ * @author Juergen Hoeller
+ * @since 29.04.2003
+ */
+class TestTransactionManager extends AbstractPlatformTransactionManager {
+
+ private static final Object TRANSACTION = "transaction";
+
+ private final boolean existingTransaction;
+
+ private final boolean canCreateTransaction;
+
+ protected boolean begin = false;
+
+ protected boolean commit = false;
+
+ protected boolean rollback = false;
+
+ protected boolean rollbackOnly = false;
+
+ protected TestTransactionManager(boolean existingTransaction, boolean canCreateTransaction) {
+ this.existingTransaction = existingTransaction;
+ this.canCreateTransaction = canCreateTransaction;
+ setTransactionSynchronization(SYNCHRONIZATION_NEVER);
+ }
+
+ protected Object doGetTransaction() {
+ return TRANSACTION;
+ }
+
+ protected boolean isExistingTransaction(Object transaction) {
+ return existingTransaction;
+ }
+
+ protected void doBegin(Object transaction, TransactionDefinition definition) {
+ if (!TRANSACTION.equals(transaction)) {
+ throw new IllegalArgumentException("Not the same transaction object");
+ }
+ if (!this.canCreateTransaction) {
+ throw new CannotCreateTransactionException("Cannot create transaction");
+ }
+ this.begin = true;
+ }
+
+ protected void doCommit(DefaultTransactionStatus status) {
+ if (!TRANSACTION.equals(status.getTransaction())) {
+ throw new IllegalArgumentException("Not the same transaction object");
+ }
+ this.commit = true;
+ }
+
+ protected void doRollback(DefaultTransactionStatus status) {
+ if (!TRANSACTION.equals(status.getTransaction())) {
+ throw new IllegalArgumentException("Not the same transaction object");
+ }
+ this.rollback = true;
+ }
+
+ protected void doSetRollbackOnly(DefaultTransactionStatus status) {
+ if (!TRANSACTION.equals(status.getTransaction())) {
+ throw new IllegalArgumentException("Not the same transaction object");
+ }
+ this.rollbackOnly = true;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/TransactionSupportTests.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/TransactionSupportTests.java
new file mode 100644
index 00000000000..a2ec8a3b7c5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/TransactionSupportTests.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.transaction;
+
+import junit.framework.TestCase;
+
+import org.springframework.transaction.support.DefaultTransactionDefinition;
+import org.springframework.transaction.support.DefaultTransactionStatus;
+import org.springframework.transaction.support.TransactionCallbackWithoutResult;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+import org.springframework.transaction.support.TransactionTemplate;
+
+/**
+ * @author Juergen Hoeller
+ * @since 29.04.2003
+ */
+public class TransactionSupportTests extends TestCase {
+
+ public void testNoExistingTransaction() {
+ PlatformTransactionManager tm = new TestTransactionManager(false, true);
+ DefaultTransactionStatus status1 = (DefaultTransactionStatus)
+ tm.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_SUPPORTS));
+ assertTrue("Must not have transaction", status1.getTransaction() == null);
+
+ DefaultTransactionStatus status2 = (DefaultTransactionStatus)
+ tm.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRED));
+ assertTrue("Must have transaction", status2.getTransaction() != null);
+ assertTrue("Must be new transaction", status2.isNewTransaction());
+
+ try {
+ tm.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_MANDATORY));
+ fail("Should not have thrown NoTransactionException");
+ }
+ catch (IllegalTransactionStateException ex) {
+ // expected
+ }
+ }
+
+ public void testExistingTransaction() {
+ PlatformTransactionManager tm = new TestTransactionManager(true, true);
+ DefaultTransactionStatus status1 = (DefaultTransactionStatus)
+ tm.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_SUPPORTS));
+ assertTrue("Must have transaction", status1.getTransaction() != null);
+ assertTrue("Must not be new transaction", !status1.isNewTransaction());
+
+ DefaultTransactionStatus status2 = (DefaultTransactionStatus)
+ tm.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRED));
+ assertTrue("Must have transaction", status2.getTransaction() != null);
+ assertTrue("Must not be new transaction", !status2.isNewTransaction());
+
+ try {
+ DefaultTransactionStatus status3 = (DefaultTransactionStatus)
+ tm.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_MANDATORY));
+ assertTrue("Must have transaction", status3.getTransaction() != null);
+ assertTrue("Must not be new transaction", !status3.isNewTransaction());
+ }
+ catch (NoTransactionException ex) {
+ fail("Should not have thrown NoTransactionException");
+ }
+ }
+
+ public void testCommitWithoutExistingTransaction() {
+ TestTransactionManager tm = new TestTransactionManager(false, true);
+ TransactionStatus status = tm.getTransaction(null);
+ tm.commit(status);
+ assertTrue("triggered begin", tm.begin);
+ assertTrue("triggered commit", tm.commit);
+ assertTrue("no rollback", !tm.rollback);
+ assertTrue("no rollbackOnly", !tm.rollbackOnly);
+ }
+
+ public void testRollbackWithoutExistingTransaction() {
+ TestTransactionManager tm = new TestTransactionManager(false, true);
+ TransactionStatus status = tm.getTransaction(null);
+ tm.rollback(status);
+ assertTrue("triggered begin", tm.begin);
+ assertTrue("no commit", !tm.commit);
+ assertTrue("triggered rollback", tm.rollback);
+ assertTrue("no rollbackOnly", !tm.rollbackOnly);
+ }
+
+ public void testRollbackOnlyWithoutExistingTransaction() {
+ TestTransactionManager tm = new TestTransactionManager(false, true);
+ TransactionStatus status = tm.getTransaction(null);
+ status.setRollbackOnly();
+ tm.commit(status);
+ assertTrue("triggered begin", tm.begin);
+ assertTrue("no commit", !tm.commit);
+ assertTrue("triggered rollback", tm.rollback);
+ assertTrue("no rollbackOnly", !tm.rollbackOnly);
+ }
+
+ public void testCommitWithExistingTransaction() {
+ TestTransactionManager tm = new TestTransactionManager(true, true);
+ TransactionStatus status = tm.getTransaction(null);
+ tm.commit(status);
+ assertTrue("no begin", !tm.begin);
+ assertTrue("no commit", !tm.commit);
+ assertTrue("no rollback", !tm.rollback);
+ assertTrue("no rollbackOnly", !tm.rollbackOnly);
+ }
+
+ public void testRollbackWithExistingTransaction() {
+ TestTransactionManager tm = new TestTransactionManager(true, true);
+ TransactionStatus status = tm.getTransaction(null);
+ tm.rollback(status);
+ assertTrue("no begin", !tm.begin);
+ assertTrue("no commit", !tm.commit);
+ assertTrue("no rollback", !tm.rollback);
+ assertTrue("triggered rollbackOnly", tm.rollbackOnly);
+ }
+
+ public void testRollbackOnlyWithExistingTransaction() {
+ TestTransactionManager tm = new TestTransactionManager(true, true);
+ TransactionStatus status = tm.getTransaction(null);
+ status.setRollbackOnly();
+ tm.commit(status);
+ assertTrue("no begin", !tm.begin);
+ assertTrue("no commit", !tm.commit);
+ assertTrue("no rollback", !tm.rollback);
+ assertTrue("triggered rollbackOnly", tm.rollbackOnly);
+ }
+
+ public void testTransactionTemplate() {
+ TestTransactionManager tm = new TestTransactionManager(false, true);
+ TransactionTemplate template = new TransactionTemplate(tm);
+ template.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ }
+ });
+ assertTrue("triggered begin", tm.begin);
+ assertTrue("triggered commit", tm.commit);
+ assertTrue("no rollback", !tm.rollback);
+ assertTrue("no rollbackOnly", !tm.rollbackOnly);
+ }
+
+ public void testTransactionTemplateWithCallbackPreference() {
+ MockCallbackPreferringTransactionManager ptm = new MockCallbackPreferringTransactionManager();
+ TransactionTemplate template = new TransactionTemplate(ptm);
+ template.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ }
+ });
+ assertSame(template, ptm.getDefinition());
+ assertFalse(ptm.getStatus().isRollbackOnly());
+ }
+
+ public void testTransactionTemplateWithException() {
+ TestTransactionManager tm = new TestTransactionManager(false, true);
+ TransactionTemplate template = new TransactionTemplate(tm);
+ final RuntimeException ex = new RuntimeException("Some application exception");
+ try {
+ template.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ throw ex;
+ }
+ });
+ fail("Should have propagated RuntimeException");
+ }
+ catch (RuntimeException caught) {
+ // expected
+ assertTrue("Correct exception", caught == ex);
+ assertTrue("triggered begin", tm.begin);
+ assertTrue("no commit", !tm.commit);
+ assertTrue("triggered rollback", tm.rollback);
+ assertTrue("no rollbackOnly", !tm.rollbackOnly);
+ }
+ }
+
+ public void testTransactionTemplateWithRollbackException() {
+ final TransactionSystemException tex = new TransactionSystemException("system exception");
+ TestTransactionManager tm = new TestTransactionManager(false, true) {
+ protected void doRollback(DefaultTransactionStatus status) {
+ super.doRollback(status);
+ throw tex;
+ }
+ };
+ TransactionTemplate template = new TransactionTemplate(tm);
+ final RuntimeException ex = new RuntimeException("Some application exception");
+ try {
+ template.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ throw ex;
+ }
+ });
+ fail("Should have propagated RuntimeException");
+ }
+ catch (RuntimeException caught) {
+ // expected
+ assertTrue("Correct exception", caught == tex);
+ assertTrue("triggered begin", tm.begin);
+ assertTrue("no commit", !tm.commit);
+ assertTrue("triggered rollback", tm.rollback);
+ assertTrue("no rollbackOnly", !tm.rollbackOnly);
+ }
+ }
+
+ public void testTransactionTemplateWithError() {
+ TestTransactionManager tm = new TestTransactionManager(false, true);
+ TransactionTemplate template = new TransactionTemplate(tm);
+ try {
+ template.execute(new TransactionCallbackWithoutResult() {
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ throw new Error("Some application error");
+ }
+ });
+ fail("Should have propagated Error");
+ }
+ catch (Error err) {
+ // expected
+ assertTrue("triggered begin", tm.begin);
+ assertTrue("no commit", !tm.commit);
+ assertTrue("triggered rollback", tm.rollback);
+ assertTrue("no rollbackOnly", !tm.rollbackOnly);
+ }
+ }
+
+ public void testTransactionTemplateInitialization() {
+ TestTransactionManager tm = new TestTransactionManager(false, true);
+ TransactionTemplate template = new TransactionTemplate();
+ template.setTransactionManager(tm);
+ assertTrue("correct transaction manager set", template.getTransactionManager() == tm);
+
+ try {
+ template.setPropagationBehaviorName("TIMEOUT_DEFAULT");
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ template.setPropagationBehaviorName("PROPAGATION_SUPPORTS");
+ assertTrue("Correct propagation behavior set", template.getPropagationBehavior() == TransactionDefinition.PROPAGATION_SUPPORTS);
+
+ try {
+ template.setPropagationBehavior(999);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ template.setPropagationBehavior(TransactionDefinition.PROPAGATION_MANDATORY);
+ assertTrue("Correct propagation behavior set", template.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY);
+
+ try {
+ template.setIsolationLevelName("TIMEOUT_DEFAULT");
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ template.setIsolationLevelName("ISOLATION_SERIALIZABLE");
+ assertTrue("Correct isolation level set", template.getIsolationLevel() == TransactionDefinition.ISOLATION_SERIALIZABLE);
+
+ try {
+ template.setIsolationLevel(999);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ template.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
+ assertTrue("Correct isolation level set", template.getIsolationLevel() == TransactionDefinition.ISOLATION_REPEATABLE_READ);
+ }
+
+ protected void tearDown() {
+ assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/TxNamespaceHandlerEventTests.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/TxNamespaceHandlerEventTests.java
new file mode 100644
index 00000000000..e2a96b972ac
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/TxNamespaceHandlerEventTests.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.transaction;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.factory.parsing.BeanComponentDefinition;
+import org.springframework.beans.factory.parsing.CollectingReaderEventListener;
+import org.springframework.beans.factory.parsing.ComponentDefinition;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Torsten Juergeleit
+ * @author Juergen Hoeller
+ */
+public class TxNamespaceHandlerEventTests extends TestCase {
+
+ private DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
+
+ private CollectingReaderEventListener eventListener = new CollectingReaderEventListener();
+
+
+ public void setUp() throws Exception {
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this.beanFactory);
+ reader.setEventListener(this.eventListener);
+ reader.loadBeanDefinitions(new ClassPathResource("txNamespaceHandlerTests.xml", getClass()));
+ }
+
+ public void testComponentEventReceived() {
+ ComponentDefinition component = this.eventListener.getComponentDefinition("txAdvice");
+ assertTrue(component instanceof BeanComponentDefinition);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/TxNamespaceHandlerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/TxNamespaceHandlerTests.java
new file mode 100644
index 00000000000..b83f83ebd4b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/TxNamespaceHandlerTests.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.transaction;
+
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.support.AopUtils;
+import org.springframework.beans.ITestBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.transaction.interceptor.TransactionAttribute;
+import org.springframework.transaction.interceptor.TransactionAttributeSource;
+import org.springframework.transaction.interceptor.TransactionInterceptor;
+
+/**
+ * @author Rob Harrop
+ * @author Adrian Colyer
+ */
+public class TxNamespaceHandlerTests extends TestCase {
+
+ private ApplicationContext context;
+
+ private Method getAgeMethod;
+
+ private Method setAgeMethod;
+
+ public void setUp() throws Exception {
+ this.context = new ClassPathXmlApplicationContext("txNamespaceHandlerTests.xml", getClass());
+ this.getAgeMethod = ITestBean.class.getMethod("getAge", new Class[0]);
+ this.setAgeMethod = ITestBean.class.getMethod("setAge", new Class[] {int.class});
+ }
+
+ public void testIsProxy() throws Exception {
+ ITestBean bean = getTestBean();
+ assertTrue("testBean is not a proxy", AopUtils.isAopProxy(bean));
+ }
+
+ public void testInvokeTransactional() throws Exception {
+ ITestBean testBean = getTestBean();
+ CallCountingTransactionManager ptm = (CallCountingTransactionManager) context.getBean("transactionManager");
+
+ // try with transactional
+ assertEquals("Should not have any started transactions", 0, ptm.begun);
+ testBean.getName();
+ assertTrue(ptm.lastDefinition.isReadOnly());
+ assertEquals("Should have 1 started transaction", 1, ptm.begun);
+ assertEquals("Should have 1 committed transaction", 1, ptm.commits);
+
+ // try with non-transaction
+ testBean.haveBirthday();
+ assertEquals("Should not have started another transaction", 1, ptm.begun);
+
+ // try with exceptional
+ try {
+ testBean.exceptional(new IllegalArgumentException("foo"));
+ fail("Should NEVER get here");
+ }
+ catch (Throwable throwable) {
+ assertEquals("Should have another started transaction", 2, ptm.begun);
+ assertEquals("Should have 1 rolled back transaction", 1, ptm.rollbacks);
+ }
+ }
+
+ public void testRollbackRules() {
+ TransactionInterceptor txInterceptor = (TransactionInterceptor) context.getBean("txRollbackAdvice");
+ TransactionAttributeSource txAttrSource = txInterceptor.getTransactionAttributeSource();
+ TransactionAttribute txAttr = txAttrSource.getTransactionAttribute(getAgeMethod,ITestBean.class);
+ assertTrue("should be configured to rollback on Exception",txAttr.rollbackOn(new Exception()));
+
+ txAttr = txAttrSource.getTransactionAttribute(setAgeMethod, ITestBean.class);
+ assertFalse("should not rollback on RuntimeException",txAttr.rollbackOn(new RuntimeException()));
+ }
+
+ private ITestBean getTestBean() {
+ return (ITestBean)context.getBean("testBean");
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/AbstractTransactionAspectTests.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/AbstractTransactionAspectTests.java
new file mode 100644
index 00000000000..790c0ee53cf
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/AbstractTransactionAspectTests.java
@@ -0,0 +1,599 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.transaction.interceptor;
+
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.dao.OptimisticLockingFailureException;
+import org.springframework.transaction.CannotCreateTransactionException;
+import org.springframework.transaction.MockCallbackPreferringTransactionManager;
+import org.springframework.transaction.NoTransactionException;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.TransactionSystemException;
+import org.springframework.transaction.UnexpectedRollbackException;
+import org.springframework.transaction.interceptor.TransactionAspectSupport.TransactionInfo;
+
+/**
+ * Mock object based tests for transaction aspects.
+ * True unit test in that it tests how the transaction aspect uses
+ * the PlatformTransactionManager helper, rather than indirectly
+ * testing the helper implementation.
+ *
+ * This is a superclass to allow testing both the AOP Alliance MethodInterceptor
+ * and the AspectJ aspect.
+ *
+ * @author Rod Johnson
+ * @since 16.03.2003
+ */
+public abstract class AbstractTransactionAspectTests extends TestCase {
+
+ protected Method exceptionalMethod;
+
+ protected Method getNameMethod;
+
+ protected Method setNameMethod;
+
+
+ public AbstractTransactionAspectTests() {
+ try {
+ // Cache the methods we'll be testing
+ exceptionalMethod = ITestBean.class.getMethod("exceptional", new Class[] { Throwable.class });
+ getNameMethod = ITestBean.class.getMethod("getName", (Class[]) null);
+ setNameMethod = ITestBean.class.getMethod("setName", new Class[] { String.class} );
+ }
+ catch (NoSuchMethodException ex) {
+ throw new RuntimeException("Shouldn't happen", ex);
+ }
+ }
+
+
+ public void testNoTransaction() throws Exception {
+ MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
+ PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
+
+ // expect no calls
+ ptmControl.replay();
+
+ TestBean tb = new TestBean();
+ TransactionAttributeSource tas = new MapTransactionAttributeSource();
+
+ // All the methods in this class use the advised() template method
+ // to obtain a transaction object, configured with the given PlatformTransactionManager
+ // and transaction attribute source
+ ITestBean itb = (ITestBean) advised(tb, ptm, tas);
+
+ checkTransactionStatus(false);
+ itb.getName();
+ checkTransactionStatus(false);
+
+ ptmControl.verify();
+ }
+
+ /**
+ * Check that a transaction is created and committed.
+ */
+ public void testTransactionShouldSucceed() throws Exception {
+ TransactionAttribute txatt = new DefaultTransactionAttribute();
+
+ MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
+ tas.register(getNameMethod, txatt);
+
+ TransactionStatus status = transactionStatusForNewTransaction();
+ MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
+ PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
+ // expect a transaction
+ ptm.getTransaction(txatt);
+ ptmControl.setReturnValue(status, 1);
+ ptm.commit(status);
+ ptmControl.setVoidCallable(1);
+ ptmControl.replay();
+
+ TestBean tb = new TestBean();
+ ITestBean itb = (ITestBean) advised(tb, ptm, tas);
+
+ checkTransactionStatus(false);
+ itb.getName();
+ checkTransactionStatus(false);
+
+ ptmControl.verify();
+ }
+
+ /**
+ * Check that a transaction is created and committed using
+ * CallbackPreferringPlatformTransactionManager.
+ */
+ public void testTransactionShouldSucceedWithCallbackPreference() throws Exception {
+ TransactionAttribute txatt = new DefaultTransactionAttribute();
+
+ MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
+ tas.register(getNameMethod, txatt);
+
+ MockCallbackPreferringTransactionManager ptm = new MockCallbackPreferringTransactionManager();
+
+ TestBean tb = new TestBean();
+ ITestBean itb = (ITestBean) advised(tb, ptm, tas);
+
+ checkTransactionStatus(false);
+ itb.getName();
+ checkTransactionStatus(false);
+
+ assertSame(txatt, ptm.getDefinition());
+ assertFalse(ptm.getStatus().isRollbackOnly());
+ }
+
+ public void testTransactionExceptionPropagatedWithCallbackPreference() throws Throwable {
+ TransactionAttribute txatt = new DefaultTransactionAttribute();
+
+ MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
+ tas.register(exceptionalMethod, txatt);
+
+ MockCallbackPreferringTransactionManager ptm = new MockCallbackPreferringTransactionManager();
+
+ TestBean tb = new TestBean();
+ ITestBean itb = (ITestBean) advised(tb, ptm, tas);
+
+ checkTransactionStatus(false);
+ try {
+ itb.exceptional(new OptimisticLockingFailureException(""));
+ fail("Should have thrown OptimisticLockingFailureException");
+ }
+ catch (OptimisticLockingFailureException ex) {
+ // expected
+ }
+ checkTransactionStatus(false);
+
+ assertSame(txatt, ptm.getDefinition());
+ assertFalse(ptm.getStatus().isRollbackOnly());
+ }
+
+ /**
+ * Check that two transactions are created and committed.
+ */
+ public void testTwoTransactionsShouldSucceed() throws Exception {
+ TransactionAttribute txatt = new DefaultTransactionAttribute();
+
+ MapTransactionAttributeSource tas1 = new MapTransactionAttributeSource();
+ tas1.register(getNameMethod, txatt);
+ MapTransactionAttributeSource tas2 = new MapTransactionAttributeSource();
+ tas2.register(setNameMethod, txatt);
+
+ TransactionStatus status = transactionStatusForNewTransaction();
+ MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
+ PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
+ // expect a transaction
+ ptm.getTransaction(txatt);
+ ptmControl.setReturnValue(status, 2);
+ ptm.commit(status);
+ ptmControl.setVoidCallable(2);
+ ptmControl.replay();
+
+ TestBean tb = new TestBean();
+ ITestBean itb = (ITestBean) advised(tb, ptm, new TransactionAttributeSource[] {tas1, tas2});
+
+ checkTransactionStatus(false);
+ itb.getName();
+ checkTransactionStatus(false);
+ itb.setName("myName");
+ checkTransactionStatus(false);
+
+ ptmControl.verify();
+ }
+
+ /**
+ * Check that a transaction is created and committed.
+ */
+ public void testTransactionShouldSucceedWithNotNew() throws Exception {
+ TransactionAttribute txatt = new DefaultTransactionAttribute();
+
+ MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
+ tas.register(getNameMethod, txatt);
+
+ MockControl statusControl = MockControl.createControl(TransactionStatus.class);
+ TransactionStatus status = (TransactionStatus) statusControl.getMock();
+ MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
+ PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
+ // expect a transaction
+ ptm.getTransaction(txatt);
+ ptmControl.setReturnValue(status, 1);
+ ptm.commit(status);
+ ptmControl.setVoidCallable(1);
+ ptmControl.replay();
+
+ TestBean tb = new TestBean();
+ ITestBean itb = (ITestBean) advised(tb, ptm, tas);
+
+ checkTransactionStatus(false);
+ // verification!?
+ itb.getName();
+ checkTransactionStatus(false);
+
+ ptmControl.verify();
+ }
+
+ public void testEnclosingTransactionWithNonTransactionMethodOnAdvisedInside() throws Throwable {
+ TransactionAttribute txatt = new DefaultTransactionAttribute();
+
+ MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
+ tas.register(exceptionalMethod, txatt);
+
+ TransactionStatus status = transactionStatusForNewTransaction();
+ MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
+ PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
+ // Expect a transaction
+ ptm.getTransaction(txatt);
+ ptmControl.setReturnValue(status, 1);
+ ptm.commit(status);
+ ptmControl.setVoidCallable(1);
+ ptmControl.replay();
+
+ final String spouseName = "innerName";
+
+ TestBean outer = new TestBean() {
+ public void exceptional(Throwable t) throws Throwable {
+ TransactionInfo ti = TransactionAspectSupport.currentTransactionInfo();
+ assertTrue(ti.hasTransaction());
+ assertEquals(spouseName, getSpouse().getName());
+ }
+ };
+ TestBean inner = new TestBean() {
+ public String getName() {
+ // Assert that we're in the inner proxy
+ TransactionInfo ti = TransactionAspectSupport.currentTransactionInfo();
+ assertFalse(ti.hasTransaction());
+ return spouseName;
+ }
+ };
+
+ ITestBean outerProxy = (ITestBean) advised(outer, ptm, tas);
+ ITestBean innerProxy = (ITestBean) advised(inner, ptm, tas);
+ outer.setSpouse(innerProxy);
+
+ checkTransactionStatus(false);
+
+ // Will invoke inner.getName, which is non-transactional
+ outerProxy.exceptional(null);
+
+ checkTransactionStatus(false);
+
+ ptmControl.verify();
+ }
+
+ public void testEnclosingTransactionWithNestedTransactionOnAdvisedInside() throws Throwable {
+ final TransactionAttribute outerTxatt = new DefaultTransactionAttribute();
+ final TransactionAttribute innerTxatt = new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_NESTED);
+
+ Method outerMethod = exceptionalMethod;
+ Method innerMethod = getNameMethod;
+ MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
+ tas.register(outerMethod, outerTxatt);
+ tas.register(innerMethod, innerTxatt);
+
+ TransactionStatus outerStatus = transactionStatusForNewTransaction();
+ TransactionStatus innerStatus = transactionStatusForNewTransaction();
+
+ MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
+ PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
+ // Expect a transaction
+ ptm.getTransaction(outerTxatt);
+ ptmControl.setReturnValue(outerStatus, 1);
+
+ ptm.getTransaction(innerTxatt);
+ ptmControl.setReturnValue(innerStatus, 1);
+
+ ptm.commit(innerStatus);
+ ptmControl.setVoidCallable(1);
+
+ ptm.commit(outerStatus);
+ ptmControl.setVoidCallable(1);
+ ptmControl.replay();
+
+ final String spouseName = "innerName";
+
+ TestBean outer = new TestBean() {
+ public void exceptional(Throwable t) throws Throwable {
+ TransactionInfo ti = TransactionAspectSupport.currentTransactionInfo();
+ assertTrue(ti.hasTransaction());
+ assertEquals(outerTxatt, ti.getTransactionAttribute());
+ assertEquals(spouseName, getSpouse().getName());
+ }
+ };
+ TestBean inner = new TestBean() {
+ public String getName() {
+ // Assert that we're in the inner proxy
+ TransactionInfo ti = TransactionAspectSupport.currentTransactionInfo();
+ // Has nested transaction
+ assertTrue(ti.hasTransaction());
+ assertEquals(innerTxatt, ti.getTransactionAttribute());
+ return spouseName;
+ }
+ };
+
+ ITestBean outerProxy = (ITestBean) advised(outer, ptm, tas);
+ ITestBean innerProxy = (ITestBean) advised(inner, ptm, tas);
+ outer.setSpouse(innerProxy);
+
+ checkTransactionStatus(false);
+
+ // Will invoke inner.getName, which is non-transactional
+ outerProxy.exceptional(null);
+
+ checkTransactionStatus(false);
+
+ ptmControl.verify();
+ }
+
+ public void testRollbackOnCheckedException() throws Throwable {
+ doTestRollbackOnException(new Exception(), true, false);
+ }
+
+ public void testNoRollbackOnCheckedException() throws Throwable {
+ doTestRollbackOnException(new Exception(), false, false);
+ }
+
+ public void testRollbackOnUncheckedException() throws Throwable {
+ doTestRollbackOnException(new RuntimeException(), true, false);
+ }
+
+ public void testNoRollbackOnUncheckedException() throws Throwable {
+ doTestRollbackOnException(new RuntimeException(), false, false);
+ }
+
+ public void testRollbackOnCheckedExceptionWithRollbackException() throws Throwable {
+ doTestRollbackOnException(new Exception(), true, true);
+ }
+
+ public void testNoRollbackOnCheckedExceptionWithRollbackException() throws Throwable {
+ doTestRollbackOnException(new Exception(), false, true);
+ }
+
+ public void testRollbackOnUncheckedExceptionWithRollbackException() throws Throwable {
+ doTestRollbackOnException(new RuntimeException(), true, true);
+ }
+
+ public void testNoRollbackOnUncheckedExceptionWithRollbackException() throws Throwable {
+ doTestRollbackOnException(new RuntimeException(), false, true);
+ }
+
+ /**
+ * Check that the given exception thrown by the target can produce the
+ * desired behavior with the appropriate transaction attribute.
+ * @param ex exception to be thrown by the target
+ * @param shouldRollback whether this should cause a transaction rollback
+ */
+ protected void doTestRollbackOnException(
+ final Exception ex, final boolean shouldRollback, boolean rollbackException) throws Exception {
+
+ TransactionAttribute txatt = new DefaultTransactionAttribute() {
+ public boolean rollbackOn(Throwable t) {
+ assertTrue(t == ex);
+ return shouldRollback;
+ }
+ };
+
+ Method m = exceptionalMethod;
+ MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
+ tas.register(m, txatt);
+
+ MockControl statusControl = MockControl.createControl(TransactionStatus.class);
+ TransactionStatus status = (TransactionStatus) statusControl.getMock();
+ MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
+ PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
+ // Gets additional call(s) from TransactionControl
+
+ ptm.getTransaction(txatt);
+ ptmControl.setReturnValue(status, 1);
+
+ if (shouldRollback) {
+ ptm.rollback(status);
+ }
+ else {
+ ptm.commit(status);
+ }
+ TransactionSystemException tex = new TransactionSystemException("system exception");
+ if (rollbackException) {
+ ptmControl.setThrowable(tex, 1);
+ }
+ else {
+ ptmControl.setVoidCallable(1);
+ }
+ ptmControl.replay();
+
+ TestBean tb = new TestBean();
+ ITestBean itb = (ITestBean) advised(tb, ptm, tas);
+
+ try {
+ itb.exceptional(ex);
+ fail("Should have thrown exception");
+ }
+ catch (Throwable t) {
+ if (rollbackException) {
+ assertEquals("Caught wrong exception", tex, t );
+ }
+ else {
+ assertEquals("Caught wrong exception", ex, t);
+ }
+ }
+
+ ptmControl.verify();
+ }
+
+ /**
+ * Test that TransactionStatus.setRollbackOnly works.
+ */
+ public void testProgrammaticRollback() throws Exception {
+ TransactionAttribute txatt = new DefaultTransactionAttribute();
+
+ Method m = getNameMethod;
+ MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
+ tas.register(m, txatt);
+
+ TransactionStatus status = transactionStatusForNewTransaction();
+ MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
+ PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
+
+ ptm.getTransaction(txatt);
+ ptmControl.setReturnValue(status, 1);
+ ptm.commit(status);
+ ptmControl.setVoidCallable(1);
+ ptmControl.replay();
+
+ final String name = "jenny";
+ TestBean tb = new TestBean() {
+ public String getName() {
+ TransactionStatus txStatus = TransactionInterceptor.currentTransactionStatus();
+ txStatus.setRollbackOnly();
+ return name;
+ }
+ };
+
+ ITestBean itb = (ITestBean) advised(tb, ptm, tas);
+
+ // verification!?
+ assertTrue(name.equals(itb.getName()));
+
+ ptmControl.verify();
+ }
+
+ /**
+ * @return a TransactionStatus object configured for a new transaction
+ */
+ private TransactionStatus transactionStatusForNewTransaction() {
+ MockControl statusControl = MockControl.createControl(TransactionStatus.class);
+ return (TransactionStatus) statusControl.getMock();
+ }
+
+ /**
+ * Simulate a transaction infrastructure failure.
+ * Shouldn't invoke target method.
+ */
+ public void testCannotCreateTransaction() throws Exception {
+ TransactionAttribute txatt = new DefaultTransactionAttribute();
+
+ Method m = getNameMethod;
+ MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
+ tas.register(m, txatt);
+
+ MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
+ PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
+ // Expect a transaction
+ ptm.getTransaction(txatt);
+ CannotCreateTransactionException ex = new CannotCreateTransactionException("foobar", null);
+ ptmControl.setThrowable(ex);
+ ptmControl.replay();
+
+ TestBean tb = new TestBean() {
+ public String getName() {
+ throw new UnsupportedOperationException(
+ "Shouldn't have invoked target method when couldn't create transaction for transactional method");
+ }
+ };
+ ITestBean itb = (ITestBean) advised(tb, ptm, tas);
+
+ try {
+ itb.getName();
+ fail("Shouldn't have invoked method");
+ }
+ catch (CannotCreateTransactionException thrown) {
+ assertTrue(thrown == ex);
+ }
+ ptmControl.verify();
+ }
+
+ /**
+ * Simulate failure of the underlying transaction infrastructure to commit.
+ * Check that the target method was invoked, but that the transaction
+ * infrastructure exception was thrown to the client
+ */
+ public void testCannotCommitTransaction() throws Exception {
+ TransactionAttribute txatt = new DefaultTransactionAttribute();
+
+ Method m = setNameMethod;
+ MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
+ tas.register(m, txatt);
+ Method m2 = getNameMethod;
+ // No attributes for m2
+
+ MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
+ PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
+
+ TransactionStatus status = transactionStatusForNewTransaction();
+ ptm.getTransaction(txatt);
+ ptmControl.setReturnValue(status);
+ UnexpectedRollbackException ex = new UnexpectedRollbackException("foobar", null);
+ ptm.commit(status);
+ ptmControl.setThrowable(ex);
+ ptmControl.replay();
+
+ TestBean tb = new TestBean();
+ ITestBean itb = (ITestBean) advised(tb, ptm, tas);
+
+ String name = "new name";
+ try {
+ itb.setName(name);
+ fail("Shouldn't have succeeded");
+ }
+ catch (UnexpectedRollbackException thrown) {
+ assertTrue(thrown == ex);
+ }
+
+ // Should have invoked target and changed name
+ assertTrue(itb.getName() == name);
+ ptmControl.verify();
+ }
+
+ protected void checkTransactionStatus(boolean expected) {
+ try {
+ TransactionInterceptor.currentTransactionStatus();
+ if (!expected) {
+ fail("Should have thrown NoTransactionException");
+ }
+ }
+ catch (NoTransactionException ex) {
+ if (expected) {
+ fail("Should have current TransactionStatus");
+ }
+ }
+ }
+
+
+ protected Object advised(
+ Object target, PlatformTransactionManager ptm, TransactionAttributeSource[] tas) throws Exception {
+
+ return advised(target, ptm, new CompositeTransactionAttributeSource(tas));
+ }
+
+ /**
+ * Subclasses must implement this to create an advised object based on the
+ * given target. In the case of AspectJ, the advised object will already
+ * have been created, as there's no distinction between target and proxy.
+ * In the case of Spring's own AOP framework, a proxy must be created
+ * using a suitably configured transaction interceptor
+ * @param target target if there's a distinct target. If not (AspectJ),
+ * return target.
+ * @return transactional advised object
+ */
+ protected abstract Object advised(
+ Object target, PlatformTransactionManager ptm, TransactionAttributeSource tas) throws Exception;
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/BeanFactoryTransactionTests.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/BeanFactoryTransactionTests.java
new file mode 100644
index 00000000000..f83009c4668
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/BeanFactoryTransactionTests.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.transaction.interceptor;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Map;
+
+import junit.framework.TestCase;
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+import org.easymock.MockControl;
+
+import org.springframework.aop.support.AopUtils;
+import org.springframework.aop.support.StaticMethodMatcherPointcut;
+import org.springframework.aop.target.HotSwappableTargetSource;
+import org.springframework.beans.DerivedTestBean;
+import org.springframework.beans.FatalBeanException;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.transaction.CallCountingTransactionManager;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionException;
+import org.springframework.transaction.TransactionStatus;
+
+/**
+ * Test cases for AOP transaction management.
+ *
+ * @author Rod Johnson
+ * @since 23.04.2003
+ */
+public class BeanFactoryTransactionTests extends TestCase {
+
+ private XmlBeanFactory factory;
+
+ public void setUp() {
+ this.factory = new XmlBeanFactory(new ClassPathResource("transactionalBeanFactory.xml", getClass()));
+ }
+
+ public void testGetsAreNotTransactionalWithProxyFactory1() throws NoSuchMethodException {
+ ITestBean testBean = (ITestBean) factory.getBean("proxyFactory1");
+ assertTrue("testBean is a dynamic proxy", Proxy.isProxyClass(testBean.getClass()));
+ doTestGetsAreNotTransactional(testBean, ITestBean.class);
+ }
+
+ public void testGetsAreNotTransactionalWithProxyFactory2DynamicProxy() throws NoSuchMethodException {
+ this.factory.preInstantiateSingletons();
+ ITestBean testBean = (ITestBean) factory.getBean("proxyFactory2DynamicProxy");
+ assertTrue("testBean is a dynamic proxy", Proxy.isProxyClass(testBean.getClass()));
+ doTestGetsAreNotTransactional(testBean, ITestBean.class);
+ }
+
+ public void testGetsAreNotTransactionalWithProxyFactory2Cglib() throws NoSuchMethodException {
+ ITestBean testBean = (ITestBean) factory.getBean("proxyFactory2Cglib");
+ assertTrue("testBean is CGLIB advised", AopUtils.isCglibProxy(testBean));
+ doTestGetsAreNotTransactional(testBean, TestBean.class);
+ }
+
+ public void testProxyFactory2Lazy() throws NoSuchMethodException {
+ ITestBean testBean = (ITestBean) factory.getBean("proxyFactory2Lazy");
+ assertFalse(factory.containsSingleton("target"));
+ assertEquals(666, testBean.getAge());
+ assertTrue(factory.containsSingleton("target"));
+ }
+
+ public void testCglibTransactionProxyImplementsNoInterfaces() throws NoSuchMethodException {
+ ImplementsNoInterfaces ini = (ImplementsNoInterfaces) factory.getBean("cglibNoInterfaces");
+ assertTrue("testBean is CGLIB advised", AopUtils.isCglibProxy(ini));
+ String newName = "Gordon";
+
+ // Install facade
+ CallCountingTransactionManager ptm = new CallCountingTransactionManager();
+ PlatformTransactionManagerFacade.delegate = ptm;
+
+ ini.setName(newName);
+ assertEquals(newName, ini.getName());
+ assertEquals(2, ptm.commits);
+ }
+
+ public void testGetsAreNotTransactionalWithProxyFactory3() throws NoSuchMethodException {
+ ITestBean testBean = (ITestBean) factory.getBean("proxyFactory3");
+ assertTrue("testBean is a full proxy", testBean instanceof DerivedTestBean);
+ InvocationCounterPointcut txnCounter = (InvocationCounterPointcut) factory.getBean("txnInvocationCounterPointcut");
+ InvocationCounterInterceptor preCounter = (InvocationCounterInterceptor) factory.getBean("preInvocationCounterInterceptor");
+ InvocationCounterInterceptor postCounter = (InvocationCounterInterceptor) factory.getBean("postInvocationCounterInterceptor");
+ txnCounter.counter = 0;
+ preCounter.counter = 0;
+ postCounter.counter = 0;
+ doTestGetsAreNotTransactional(testBean, TestBean.class);
+ // Can't assert it's equal to 4 as the pointcut may be optimized and only invoked once
+ assertTrue(0 < txnCounter.counter && txnCounter.counter <= 4);
+ assertEquals(4, preCounter.counter);
+ assertEquals(4, postCounter.counter);
+ }
+
+ private void doTestGetsAreNotTransactional(final ITestBean testBean, final Class proxyClass) {
+ // Install facade
+ MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
+ PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
+ // Expect no methods
+ ptmControl.replay();
+ PlatformTransactionManagerFacade.delegate = ptm;
+
+ assertTrue("Age should not be " + testBean.getAge(), testBean.getAge() == 666);
+ // Check no calls
+ ptmControl.verify();
+
+ // Install facade expecting a call
+ MockControl statusControl = MockControl.createControl(TransactionStatus.class);
+ final TransactionStatus ts = (TransactionStatus) statusControl.getMock();
+ ptm = new PlatformTransactionManager() {
+ private boolean invoked;
+ public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
+ if (invoked) {
+ throw new IllegalStateException("getTransaction should not get invoked more than once");
+ }
+ invoked = true;
+ if (!((definition.getName().indexOf(proxyClass.getName()) != -1) &&
+ (definition.getName().indexOf("setAge") != -1))) {
+ throw new IllegalStateException(
+ "transaction name should contain class and method name: " + definition.getName());
+ }
+ return ts;
+ }
+ public void commit(TransactionStatus status) throws TransactionException {
+ assertTrue(status == ts);
+ }
+ public void rollback(TransactionStatus status) throws TransactionException {
+ throw new IllegalStateException("rollback should not get invoked");
+ }
+ };
+ PlatformTransactionManagerFacade.delegate = ptm;
+
+ // TODO same as old age to avoid ordering effect for now
+ int age = 666;
+ testBean.setAge(age);
+ assertTrue(testBean.getAge() == age);
+ ptmControl.verify();
+ }
+
+ public void testGetBeansOfTypeWithAbstract() {
+ Map beansOfType = factory.getBeansOfType(ITestBean.class, true, true);
+ }
+
+ /**
+ * Check that we fail gracefully if the user doesn't set any transaction attributes.
+ */
+ public void testNoTransactionAttributeSource() {
+ try {
+ XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("noTransactionAttributeSource.xml", getClass()));
+ ITestBean testBean = (ITestBean) bf.getBean("noTransactionAttributeSource");
+ fail("Should require TransactionAttributeSource to be set");
+ }
+ catch (FatalBeanException ex) {
+ // Ok
+ }
+ }
+
+ /**
+ * Test that we can set the target to a dynamic TargetSource.
+ */
+ public void testDynamicTargetSource() throws NoSuchMethodException {
+ // Install facade
+ CallCountingTransactionManager txMan = new CallCountingTransactionManager();
+ PlatformTransactionManagerFacade.delegate = txMan;
+
+ TestBean tb = (TestBean) factory.getBean("hotSwapped");
+ assertEquals(666, tb.getAge());
+ int newAge = 557;
+ tb.setAge(newAge);
+ assertEquals(newAge, tb.getAge());
+
+ TestBean target2 = new TestBean();
+ target2.setAge(65);
+ HotSwappableTargetSource ts = (HotSwappableTargetSource) factory.getBean("swapper");
+ ts.swap(target2);
+ assertEquals(target2.getAge(), tb.getAge());
+ tb.setAge(newAge);
+ assertEquals(newAge, target2.getAge());
+
+ assertEquals(0, txMan.inflight);
+ assertEquals(2, txMan.commits);
+ assertEquals(0, txMan.rollbacks);
+ }
+
+
+ public static class InvocationCounterPointcut extends StaticMethodMatcherPointcut {
+
+ int counter = 0;
+
+ public boolean matches(Method method, Class clazz) {
+ counter++;
+ return true;
+ }
+ }
+
+
+ public static class InvocationCounterInterceptor implements MethodInterceptor {
+
+ int counter = 0;
+
+ public Object invoke(MethodInvocation methodInvocation) throws Throwable {
+ counter++;
+ return methodInvocation.proceed();
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/ImplementsNoInterfaces.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/ImplementsNoInterfaces.java
new file mode 100644
index 00000000000..90f0361eed7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/ImplementsNoInterfaces.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.transaction.interceptor;
+
+import org.springframework.beans.TestBean;
+
+/**
+ * Test for CGLIB proxying that implements no interfaces
+ * and has one dependency.
+ *
+ * @author Rod Johnson
+ */
+public class ImplementsNoInterfaces {
+
+ private TestBean testBean;
+
+ public void setDependency(TestBean testBean) {
+ this.testBean = testBean;
+ }
+
+ public String getName() {
+ return testBean.getName();
+ }
+
+ public void setName(String name) {
+ testBean.setName(name);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/MapTransactionAttributeSource.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/MapTransactionAttributeSource.java
new file mode 100644
index 00000000000..35ef3bf103e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/MapTransactionAttributeSource.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.transaction.interceptor;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Inherits fallback behavior from AbstractFallbackTransactionAttributeSource.
+ *
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public class MapTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource {
+
+ /** Map from Method or Clazz to TransactionAttribute */
+ private final Map attributeMap = new HashMap();
+
+ public void register(Method m, TransactionAttribute txAtt) {
+ this.attributeMap.put(m, txAtt);
+ }
+
+ public void register(Class clazz, TransactionAttribute txAtt) {
+ this.attributeMap.put(clazz, txAtt);
+ }
+
+
+ protected TransactionAttribute findTransactionAttribute(Method method) {
+ return (TransactionAttribute) this.attributeMap.get(method);
+ }
+
+ protected TransactionAttribute findTransactionAttribute(Class clazz) {
+ return (TransactionAttribute) this.attributeMap.get(clazz);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/PlatformTransactionManagerFacade.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/PlatformTransactionManagerFacade.java
new file mode 100644
index 00000000000..78360642277
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/PlatformTransactionManagerFacade.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.transaction.interceptor;
+
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionStatus;
+
+/**
+ * Used for testing only (for example, when we must replace the
+ * behavior of a PlatformTransactionManager bean we don't have access to).
+ *
+ *
Allows behavior of an entire class to change with static delegate change.
+ * Not multi-threaded.
+ *
+ * @author Rod Johnson
+ * @since 26.04.2003
+ */
+public class PlatformTransactionManagerFacade implements PlatformTransactionManager {
+
+ /**
+ * This member can be changed to change behavior class-wide.
+ */
+ public static PlatformTransactionManager delegate;
+
+ public TransactionStatus getTransaction(TransactionDefinition definition) {
+ return delegate.getTransaction(definition);
+ }
+
+ public void commit(TransactionStatus status) {
+ delegate.commit(status);
+ }
+
+ public void rollback(TransactionStatus status) {
+ delegate.rollback(status);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/RollbackRuleTests.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/RollbackRuleTests.java
new file mode 100644
index 00000000000..789ff37a158
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/RollbackRuleTests.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.transaction.interceptor;
+
+import javax.servlet.ServletException;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.FatalBeanException;
+import org.springframework.mail.MailSendException;
+
+/**
+ * Unit tests for the {@link RollbackRuleAttribute} class.
+ *
+ * @author Rod Johnson
+ * @author Rick Evans
+ * @since 09.04.2003
+ */
+public class RollbackRuleTests extends TestCase {
+
+ public void testFoundImmediatelyWithString() {
+ RollbackRuleAttribute rr = new RollbackRuleAttribute("java.lang.Exception");
+ assertTrue(rr.getDepth(new Exception()) == 0);
+ }
+
+ public void testFoundImmediatelyWithClass() {
+ RollbackRuleAttribute rr = new RollbackRuleAttribute(Exception.class);
+ assertTrue(rr.getDepth(new Exception()) == 0);
+ }
+
+ public void testNotFound() {
+ RollbackRuleAttribute rr = new RollbackRuleAttribute("javax.servlet.ServletException");
+ assertTrue(rr.getDepth(new MailSendException("")) == -1);
+ }
+
+ public void testAncestry() {
+ RollbackRuleAttribute rr = new RollbackRuleAttribute("java.lang.Exception");
+ // Exception -> Runtime -> NestedRuntime -> MailException -> MailSendException
+ assertTrue(rr.getDepth(new MailSendException("")) == 4);
+ }
+
+ public void testAlwaysTrueForThrowable() {
+ RollbackRuleAttribute rr = new RollbackRuleAttribute("java.lang.Throwable");
+ assertTrue(rr.getDepth(new MailSendException("")) > 0);
+ assertTrue(rr.getDepth(new ServletException()) > 0);
+ assertTrue(rr.getDepth(new FatalBeanException(null,null)) > 0);
+ assertTrue(rr.getDepth(new RuntimeException()) > 0);
+ }
+
+ public void testCtorArgMustBeAThrowableClassWithNonThrowableType() {
+ try {
+ new RollbackRuleAttribute(StringBuffer.class);
+ fail("Cannot construct a RollbackRuleAttribute with a non-Throwable type");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testCtorArgMustBeAThrowableClassWithNullThrowableType() {
+ try {
+ new RollbackRuleAttribute((Class) null);
+ fail("Cannot construct a RollbackRuleAttribute with a null-Throwable type");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testCtorArgExceptionStringNameVersionWithNull() {
+ try {
+ new RollbackRuleAttribute((String) null);
+ fail("Cannot construct a RollbackRuleAttribute with a null-Throwable type");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/RuleBasedTransactionAttributeTests.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/RuleBasedTransactionAttributeTests.java
new file mode 100644
index 00000000000..b147c23a912
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/RuleBasedTransactionAttributeTests.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.transaction.interceptor;
+
+import java.rmi.RemoteException;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.servlet.ServletException;
+
+import junit.framework.TestCase;
+
+import org.springframework.mail.MailSendException;
+import org.springframework.transaction.TransactionDefinition;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ * @since 09.04.2003
+ */
+public class RuleBasedTransactionAttributeTests extends TestCase {
+
+ public void testDefaultRule() {
+ RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute();
+ assertTrue(rta.rollbackOn(new RuntimeException()));
+ assertTrue(rta.rollbackOn(new MailSendException("")));
+ assertFalse(rta.rollbackOn(new Exception()));
+ assertFalse(rta.rollbackOn(new ServletException()));
+ }
+
+ /**
+ * Test one checked exception that should roll back.
+ */
+ public void testRuleForRollbackOnChecked() {
+ List list = new LinkedList();
+ list.add(new RollbackRuleAttribute("javax.servlet.ServletException"));
+ RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, list);
+
+ assertTrue(rta.rollbackOn(new RuntimeException()));
+ assertTrue(rta.rollbackOn(new MailSendException("")));
+ assertFalse(rta.rollbackOn(new Exception()));
+ // Check that default behaviour is overridden
+ assertTrue(rta.rollbackOn(new ServletException()));
+ }
+
+ public void testRuleForCommitOnUnchecked() {
+ List list = new LinkedList();
+ list.add(new NoRollbackRuleAttribute("org.springframework.mail.MailSendException"));
+ list.add(new RollbackRuleAttribute("javax.servlet.ServletException"));
+ RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, list);
+
+ assertTrue(rta.rollbackOn(new RuntimeException()));
+ // Check default behaviour is overridden
+ assertFalse(rta.rollbackOn(new MailSendException("")));
+ assertFalse(rta.rollbackOn(new Exception()));
+ // Check that default behaviour is overridden
+ assertTrue(rta.rollbackOn(new ServletException()));
+ }
+
+ public void testRuleForSelectiveRollbackOnCheckedWithString() {
+ List l = new LinkedList();
+ l.add(new RollbackRuleAttribute("java.rmi.RemoteException"));
+ RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, l);
+ doTestRuleForSelectiveRollbackOnChecked(rta);
+ }
+
+ public void testRuleForSelectiveRollbackOnCheckedWithClass() {
+ List l = Collections.singletonList(new RollbackRuleAttribute(RemoteException.class));
+ RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, l);
+ doTestRuleForSelectiveRollbackOnChecked(rta);
+ }
+
+ private void doTestRuleForSelectiveRollbackOnChecked(RuleBasedTransactionAttribute rta) {
+ assertTrue(rta.rollbackOn(new RuntimeException()));
+ // Check default behaviour is overridden
+ assertFalse(rta.rollbackOn(new Exception()));
+ // Check that default behaviour is overridden
+ assertTrue(rta.rollbackOn(new RemoteException()));
+ }
+
+ /**
+ * Check that a rule can cause commit on a ServletException
+ * when Exception prompts a rollback.
+ */
+ public void testRuleForCommitOnSubclassOfChecked() {
+ List list = new LinkedList();
+ // Note that it's important to ensure that we have this as
+ // a FQN: otherwise it will match everything!
+ list.add(new RollbackRuleAttribute("java.lang.Exception"));
+ list.add(new NoRollbackRuleAttribute("ServletException"));
+ RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, list);
+
+ assertTrue(rta.rollbackOn(new RuntimeException()));
+ assertTrue(rta.rollbackOn(new Exception()));
+ // Check that default behaviour is overridden
+ assertFalse(rta.rollbackOn(new ServletException()));
+ }
+
+ public void testRollbackNever() {
+ List list = new LinkedList();
+ list.add(new NoRollbackRuleAttribute("Throwable"));
+ RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, list);
+
+ assertFalse(rta.rollbackOn(new Throwable()));
+ assertFalse(rta.rollbackOn(new RuntimeException()));
+ assertFalse(rta.rollbackOn(new MailSendException("")));
+ assertFalse(rta.rollbackOn(new Exception()));
+ assertFalse(rta.rollbackOn(new ServletException()));
+ }
+
+ public void testToStringMatchesEditor() {
+ List list = new LinkedList();
+ list.add(new NoRollbackRuleAttribute("Throwable"));
+ RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, list);
+
+ TransactionAttributeEditor tae = new TransactionAttributeEditor();
+ tae.setAsText(rta.toString());
+ rta = (RuleBasedTransactionAttribute) tae.getValue();
+
+ assertFalse(rta.rollbackOn(new Throwable()));
+ assertFalse(rta.rollbackOn(new RuntimeException()));
+ assertFalse(rta.rollbackOn(new MailSendException("")));
+ assertFalse(rta.rollbackOn(new Exception()));
+ assertFalse(rta.rollbackOn(new ServletException()));
+ }
+
+ /**
+ * See this forum post.
+ */
+ public void testConflictingRulesToDetermineExactContract() {
+ List list = new LinkedList();
+ list.add(new NoRollbackRuleAttribute(MyBusinessWarningException.class));
+ list.add(new RollbackRuleAttribute(MyBusinessException.class));
+ RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, list);
+
+ assertTrue(rta.rollbackOn(new MyBusinessException()));
+ assertFalse(rta.rollbackOn(new MyBusinessWarningException()));
+ }
+
+
+ public static class MyBusinessException extends Exception {}
+
+
+ public static final class MyBusinessWarningException extends MyBusinessException {}
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/TransactionAttributeEditorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/TransactionAttributeEditorTests.java
new file mode 100644
index 00000000000..993bcf80fab
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/TransactionAttributeEditorTests.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.transaction.interceptor;
+
+import javax.servlet.ServletException;
+
+import junit.framework.TestCase;
+
+import org.springframework.mail.MailSendException;
+import org.springframework.transaction.TransactionDefinition;
+
+/**
+ * Tests to check conversion from String to TransactionAttribute.
+ *
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @since 26.04.2003
+ */
+public class TransactionAttributeEditorTests extends TestCase {
+
+ public void testNull() {
+ TransactionAttributeEditor pe = new TransactionAttributeEditor();
+ pe.setAsText(null);
+ TransactionAttribute ta = (TransactionAttribute) pe.getValue();
+ assertTrue(ta == null);
+ }
+
+ public void testEmptyString() {
+ TransactionAttributeEditor pe = new TransactionAttributeEditor();
+ pe.setAsText("");
+ TransactionAttribute ta = (TransactionAttribute) pe.getValue();
+ assertTrue(ta == null);
+ }
+
+ public void testValidPropagationCodeOnly() {
+ TransactionAttributeEditor pe = new TransactionAttributeEditor();
+ pe.setAsText("PROPAGATION_REQUIRED");
+ TransactionAttribute ta = (TransactionAttribute) pe.getValue();
+ assertTrue(ta != null);
+ assertTrue(ta.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED);
+ assertTrue(ta.getIsolationLevel() == TransactionDefinition.ISOLATION_DEFAULT);
+ assertTrue(!ta.isReadOnly());
+ }
+
+ public void testInvalidPropagationCodeOnly() {
+ TransactionAttributeEditor pe = new TransactionAttributeEditor();
+ try {
+ pe.setAsText("XXPROPAGATION_REQUIRED");
+ fail("Should have failed with bogus propagation code");
+ }
+ catch (IllegalArgumentException ex) {
+ // Ok
+ }
+ }
+
+ public void testValidPropagationCodeAndIsolationCode() {
+ TransactionAttributeEditor pe = new TransactionAttributeEditor();
+ pe.setAsText("PROPAGATION_REQUIRED, ISOLATION_READ_UNCOMMITTED");
+ TransactionAttribute ta = (TransactionAttribute) pe.getValue();
+ assertTrue(ta != null);
+ assertTrue(ta.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED);
+ assertTrue(ta.getIsolationLevel() == TransactionDefinition.ISOLATION_READ_UNCOMMITTED);
+ }
+
+ public void testValidPropagationAndIsolationCodesAndInvalidRollbackRule() {
+ TransactionAttributeEditor pe = new TransactionAttributeEditor();
+ try {
+ pe.setAsText("PROPAGATION_REQUIRED,ISOLATION_READ_UNCOMMITTED,XXX");
+ fail("Should have failed with bogus rollback rule");
+ }
+ catch (IllegalArgumentException ex) {
+ // Ok
+ }
+ }
+
+ public void testValidPropagationCodeAndIsolationCodeAndRollbackRules1() {
+ TransactionAttributeEditor pe = new TransactionAttributeEditor();
+ pe.setAsText("PROPAGATION_MANDATORY,ISOLATION_REPEATABLE_READ,timeout_10,-ServletException,+MailSendException");
+ TransactionAttribute ta = (TransactionAttribute) pe.getValue();
+ assertNotNull(ta);
+ assertEquals(ta.getPropagationBehavior(), TransactionDefinition.PROPAGATION_MANDATORY);
+ assertEquals(ta.getIsolationLevel(), TransactionDefinition.ISOLATION_REPEATABLE_READ);
+ assertEquals(ta.getTimeout(), 10);
+ assertFalse(ta.isReadOnly());
+ assertTrue(ta.rollbackOn(new RuntimeException()));
+ assertFalse(ta.rollbackOn(new Exception()));
+ // Check for our bizarre customized rollback rules
+ assertTrue(ta.rollbackOn(new ServletException()));
+ assertTrue(!ta.rollbackOn(new MailSendException("")));
+ }
+
+ public void testValidPropagationCodeAndIsolationCodeAndRollbackRules2() {
+ TransactionAttributeEditor pe = new TransactionAttributeEditor();
+ pe.setAsText("+ServletException,readOnly,ISOLATION_READ_COMMITTED,-MailSendException,PROPAGATION_SUPPORTS");
+ TransactionAttribute ta = (TransactionAttribute) pe.getValue();
+ assertNotNull(ta);
+ assertEquals(ta.getPropagationBehavior(), TransactionDefinition.PROPAGATION_SUPPORTS);
+ assertEquals(ta.getIsolationLevel(), TransactionDefinition.ISOLATION_READ_COMMITTED);
+ assertEquals(ta.getTimeout(), TransactionDefinition.TIMEOUT_DEFAULT);
+ assertTrue(ta.isReadOnly());
+ assertTrue(ta.rollbackOn(new RuntimeException()));
+ assertFalse(ta.rollbackOn(new Exception()));
+ // Check for our bizarre customized rollback rules
+ assertFalse(ta.rollbackOn(new ServletException()));
+ assertTrue(ta.rollbackOn(new MailSendException("")));
+ }
+
+ public void testDefaultTransactionAttributeToString() {
+ DefaultTransactionAttribute source = new DefaultTransactionAttribute();
+ source.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
+ source.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
+ source.setTimeout(10);
+ source.setReadOnly(true);
+
+ TransactionAttributeEditor pe = new TransactionAttributeEditor();
+ pe.setAsText(source.toString());
+ TransactionAttribute ta = (TransactionAttribute) pe.getValue();
+ assertEquals(ta, source);
+ assertEquals(ta.getPropagationBehavior(), TransactionDefinition.PROPAGATION_SUPPORTS);
+ assertEquals(ta.getIsolationLevel(), TransactionDefinition.ISOLATION_REPEATABLE_READ);
+ assertEquals(ta.getTimeout(), 10);
+ assertTrue(ta.isReadOnly());
+ assertTrue(ta.rollbackOn(new RuntimeException()));
+ assertFalse(ta.rollbackOn(new Exception()));
+
+ source.setTimeout(9);
+ assertNotSame(ta, source);
+ source.setTimeout(10);
+ assertEquals(ta, source);
+ }
+
+ public void testRuleBasedTransactionAttributeToString() {
+ RuleBasedTransactionAttribute source = new RuleBasedTransactionAttribute();
+ source.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
+ source.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
+ source.setTimeout(10);
+ source.setReadOnly(true);
+ source.getRollbackRules().add(new RollbackRuleAttribute("IllegalArgumentException"));
+ source.getRollbackRules().add(new NoRollbackRuleAttribute("IllegalStateException"));
+
+ TransactionAttributeEditor pe = new TransactionAttributeEditor();
+ pe.setAsText(source.toString());
+ TransactionAttribute ta = (TransactionAttribute) pe.getValue();
+ assertEquals(ta, source);
+ assertEquals(ta.getPropagationBehavior(), TransactionDefinition.PROPAGATION_SUPPORTS);
+ assertEquals(ta.getIsolationLevel(), TransactionDefinition.ISOLATION_REPEATABLE_READ);
+ assertEquals(ta.getTimeout(), 10);
+ assertTrue(ta.isReadOnly());
+ assertTrue(ta.rollbackOn(new IllegalArgumentException()));
+ assertFalse(ta.rollbackOn(new IllegalStateException()));
+
+ source.getRollbackRules().clear();
+ assertNotSame(ta, source);
+ source.getRollbackRules().add(new RollbackRuleAttribute("IllegalArgumentException"));
+ source.getRollbackRules().add(new NoRollbackRuleAttribute("IllegalStateException"));
+ assertEquals(ta, source);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/TransactionAttributeSourceAdvisorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/TransactionAttributeSourceAdvisorTests.java
new file mode 100644
index 00000000000..8911d31bb12
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/TransactionAttributeSourceAdvisorTests.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.transaction.interceptor;
+
+import java.util.Properties;
+
+import org.springframework.util.SerializationTestUtils;
+
+import junit.framework.TestCase;
+
+/**
+ *
+ * @author Rod Johnson
+ */
+public class TransactionAttributeSourceAdvisorTests extends TestCase {
+
+ public TransactionAttributeSourceAdvisorTests(String s) {
+ super(s);
+ }
+
+ public void testSerializability() throws Exception {
+ TransactionInterceptor ti = new TransactionInterceptor();
+ ti.setTransactionAttributes(new Properties());
+ TransactionAttributeSourceAdvisor tas = new TransactionAttributeSourceAdvisor(ti);
+ SerializationTestUtils.serializeAndDeserialize(tas);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/TransactionAttributeSourceEditorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/TransactionAttributeSourceEditorTests.java
new file mode 100644
index 00000000000..1c74ff2e096
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/TransactionAttributeSourceEditorTests.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.transaction.interceptor;
+
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.springframework.transaction.TransactionDefinition;
+
+/**
+ * Format is
+ * FQN.Method=tx attribute representation
+ *
+ * @author Rod Johnson
+ * @since 26.04.2003
+ */
+public class TransactionAttributeSourceEditorTests extends TestCase {
+
+ public void testNull() throws Exception {
+ TransactionAttributeSourceEditor pe = new TransactionAttributeSourceEditor();
+ pe.setAsText(null);
+ TransactionAttributeSource tas = (TransactionAttributeSource) pe.getValue();
+
+ Method m = Object.class.getMethod("hashCode", (Class[]) null);
+ assertTrue(tas.getTransactionAttribute(m, null) == null);
+ }
+
+ public void testInvalid() throws Exception {
+ TransactionAttributeSourceEditor pe = new TransactionAttributeSourceEditor();
+ try {
+ pe.setAsText("foo=bar");
+ fail();
+ }
+ catch (IllegalArgumentException ex) {
+ // Ok
+ }
+ }
+
+ public void testMatchesSpecific() throws Exception {
+ TransactionAttributeSourceEditor pe = new TransactionAttributeSourceEditor();
+ // TODO need FQN?
+ pe.setAsText(
+ "java.lang.Object.hashCode=PROPAGATION_REQUIRED\n" +
+ "java.lang.Object.equals=PROPAGATION_MANDATORY\n" +
+ "java.lang.Object.*it=PROPAGATION_SUPPORTS\n" +
+ "java.lang.Object.notify=PROPAGATION_SUPPORTS\n" +
+ "java.lang.Object.not*=PROPAGATION_REQUIRED");
+ TransactionAttributeSource tas = (TransactionAttributeSource) pe.getValue();
+
+ checkTransactionProperties(tas, Object.class.getMethod("hashCode", (Class[]) null),
+ TransactionDefinition.PROPAGATION_REQUIRED);
+ checkTransactionProperties(tas, Object.class.getMethod("equals", new Class[] { Object.class }),
+ TransactionDefinition.PROPAGATION_MANDATORY);
+ checkTransactionProperties(tas, Object.class.getMethod("wait", (Class[]) null),
+ TransactionDefinition.PROPAGATION_SUPPORTS);
+ checkTransactionProperties(tas, Object.class.getMethod("wait", new Class[] { long.class }),
+ TransactionDefinition.PROPAGATION_SUPPORTS);
+ checkTransactionProperties(tas, Object.class.getMethod("wait", new Class[] { long.class, int.class }),
+ TransactionDefinition.PROPAGATION_SUPPORTS);
+ checkTransactionProperties(tas, Object.class.getMethod("notify", (Class[]) null),
+ TransactionDefinition.PROPAGATION_SUPPORTS);
+ checkTransactionProperties(tas, Object.class.getMethod("notifyAll", (Class[]) null),
+ TransactionDefinition.PROPAGATION_REQUIRED);
+ checkTransactionProperties(tas, Object.class.getMethod("toString", (Class[]) null), -1);
+ }
+
+ public void testMatchesAll() throws Exception {
+ TransactionAttributeSourceEditor pe = new TransactionAttributeSourceEditor();
+ pe.setAsText("java.lang.Object.*=PROPAGATION_REQUIRED");
+ TransactionAttributeSource tas = (TransactionAttributeSource) pe.getValue();
+
+ checkTransactionProperties(tas, Object.class.getMethod("hashCode", (Class[]) null),
+ TransactionDefinition.PROPAGATION_REQUIRED);
+ checkTransactionProperties(tas, Object.class.getMethod("equals", new Class[] { Object.class }),
+ TransactionDefinition.PROPAGATION_REQUIRED);
+ checkTransactionProperties(tas, Object.class.getMethod("wait", (Class[]) null),
+ TransactionDefinition.PROPAGATION_REQUIRED);
+ checkTransactionProperties(tas, Object.class.getMethod("wait", new Class[] { long.class }),
+ TransactionDefinition.PROPAGATION_REQUIRED);
+ checkTransactionProperties(tas, Object.class.getMethod("wait", new Class[] { long.class, int.class }),
+ TransactionDefinition.PROPAGATION_REQUIRED);
+ checkTransactionProperties(tas, Object.class.getMethod("notify", (Class[]) null),
+ TransactionDefinition.PROPAGATION_REQUIRED);
+ checkTransactionProperties(tas, Object.class.getMethod("notifyAll", (Class[]) null),
+ TransactionDefinition.PROPAGATION_REQUIRED);
+ checkTransactionProperties(tas, Object.class.getMethod("toString", (Class[]) null),
+ TransactionDefinition.PROPAGATION_REQUIRED);
+ }
+
+ private void checkTransactionProperties(TransactionAttributeSource tas, Method method, int propagationBehavior) {
+ TransactionAttribute ta = tas.getTransactionAttribute(method, null);
+ if (propagationBehavior >= 0) {
+ assertTrue(ta != null);
+ assertTrue(ta.getIsolationLevel() == TransactionDefinition.ISOLATION_DEFAULT);
+ assertTrue(ta.getPropagationBehavior() == propagationBehavior);
+ }
+ else {
+ assertTrue(ta == null);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/TransactionAttributeSourceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/TransactionAttributeSourceTests.java
new file mode 100644
index 00000000000..5ffe826a9b7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/TransactionAttributeSourceTests.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.transaction.interceptor;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.servlet.ServletException;
+
+import junit.framework.TestCase;
+
+import org.springframework.transaction.TransactionDefinition;
+
+/**
+ * Unit tests for the various {@link TransactionAttributeSource} implementations.
+ *
+ * @author Colin Sampaleanu
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ * @since 15.10.2003
+ * @see org.springframework.transaction.interceptor.TransactionProxyFactoryBean
+ */
+public final class TransactionAttributeSourceTests extends TestCase {
+
+ public void testMatchAlwaysTransactionAttributeSource() throws Exception {
+ MatchAlwaysTransactionAttributeSource tas = new MatchAlwaysTransactionAttributeSource();
+ TransactionAttribute ta = tas.getTransactionAttribute(
+ Object.class.getMethod("hashCode", (Class[]) null), null);
+ assertNotNull(ta);
+ assertTrue(TransactionDefinition.PROPAGATION_REQUIRED == ta.getPropagationBehavior());
+
+ tas.setTransactionAttribute(new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_SUPPORTS));
+ ta = tas.getTransactionAttribute(
+ ServletException.class.getMethod("getMessage", (Class[]) null), ServletException.class);
+ assertNotNull(ta);
+ assertTrue(TransactionDefinition.PROPAGATION_SUPPORTS == ta.getPropagationBehavior());
+ }
+
+ public void testMethodMapTransactionAttributeSource() throws NoSuchMethodException {
+ MethodMapTransactionAttributeSource tas = new MethodMapTransactionAttributeSource();
+ Map methodMap = new HashMap();
+ methodMap.put(Object.class.getName() + ".hashCode", "PROPAGATION_REQUIRED");
+ methodMap.put(Object.class.getName() + ".toString",
+ new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_SUPPORTS));
+ tas.setMethodMap(methodMap);
+ tas.afterPropertiesSet();
+ TransactionAttribute ta = tas.getTransactionAttribute(
+ Object.class.getMethod("hashCode", (Class[]) null), null);
+ assertNotNull(ta);
+ assertEquals(TransactionDefinition.PROPAGATION_REQUIRED, ta.getPropagationBehavior());
+ ta = tas.getTransactionAttribute(Object.class.getMethod("toString", (Class[]) null), null);
+ assertNotNull(ta);
+ assertEquals(TransactionDefinition.PROPAGATION_SUPPORTS, ta.getPropagationBehavior());
+ }
+
+ public void testMethodMapTransactionAttributeSourceWithLazyInit() throws NoSuchMethodException {
+ MethodMapTransactionAttributeSource tas = new MethodMapTransactionAttributeSource();
+ Map methodMap = new HashMap();
+ methodMap.put(Object.class.getName() + ".hashCode", "PROPAGATION_REQUIRED");
+ methodMap.put(Object.class.getName() + ".toString",
+ new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_SUPPORTS));
+ tas.setMethodMap(methodMap);
+ TransactionAttribute ta = tas.getTransactionAttribute(
+ Object.class.getMethod("hashCode", (Class[]) null), null);
+ assertNotNull(ta);
+ assertEquals(TransactionDefinition.PROPAGATION_REQUIRED, ta.getPropagationBehavior());
+ ta = tas.getTransactionAttribute(Object.class.getMethod("toString", (Class[]) null), null);
+ assertNotNull(ta);
+ assertEquals(TransactionDefinition.PROPAGATION_SUPPORTS, ta.getPropagationBehavior());
+ }
+
+ public void testNameMatchTransactionAttributeSource() throws NoSuchMethodException {
+ NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();
+ Map methodMap = new HashMap();
+ methodMap.put("hashCode", "PROPAGATION_REQUIRED");
+ methodMap.put("toString", new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_SUPPORTS));
+ tas.setNameMap(methodMap);
+ TransactionAttribute ta = tas.getTransactionAttribute(
+ Object.class.getMethod("hashCode", (Class[]) null), null);
+ assertNotNull(ta);
+ assertEquals(TransactionDefinition.PROPAGATION_REQUIRED, ta.getPropagationBehavior());
+ ta = tas.getTransactionAttribute(Object.class.getMethod("toString", (Class[]) null), null);
+ assertNotNull(ta);
+ assertEquals(TransactionDefinition.PROPAGATION_SUPPORTS, ta.getPropagationBehavior());
+ }
+
+ public void testNameMatchTransactionAttributeSourceWithStarAtStartOfMethodName() throws NoSuchMethodException {
+ NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();
+ Properties attributes = new Properties();
+ attributes.put("*ashCode", "PROPAGATION_REQUIRED");
+ tas.setProperties(attributes);
+ TransactionAttribute ta = tas.getTransactionAttribute(
+ Object.class.getMethod("hashCode", (Class[]) null), null);
+ assertNotNull(ta);
+ assertEquals(TransactionDefinition.PROPAGATION_REQUIRED, ta.getPropagationBehavior());
+ }
+
+ public void testNameMatchTransactionAttributeSourceWithStarAtEndOfMethodName() throws NoSuchMethodException {
+ NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();
+ Properties attributes = new Properties();
+ attributes.put("hashCod*", "PROPAGATION_REQUIRED");
+ tas.setProperties(attributes);
+ TransactionAttribute ta = tas.getTransactionAttribute(
+ Object.class.getMethod("hashCode", (Class[]) null), null);
+ assertNotNull(ta);
+ assertEquals(TransactionDefinition.PROPAGATION_REQUIRED, ta.getPropagationBehavior());
+ }
+
+ public void testNameMatchTransactionAttributeSourceMostSpecificMethodNameIsDefinitelyMatched() throws NoSuchMethodException {
+ NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();
+ Properties attributes = new Properties();
+ attributes.put("*", "PROPAGATION_REQUIRED");
+ attributes.put("hashCode", "PROPAGATION_MANDATORY");
+ tas.setProperties(attributes);
+ TransactionAttribute ta = tas.getTransactionAttribute(
+ Object.class.getMethod("hashCode", (Class[]) null), null);
+ assertNotNull(ta);
+ assertEquals(TransactionDefinition.PROPAGATION_MANDATORY, ta.getPropagationBehavior());
+ }
+
+ public void testNameMatchTransactionAttributeSourceWithEmptyMethodName() throws NoSuchMethodException {
+ NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();
+ Properties attributes = new Properties();
+ attributes.put("", "PROPAGATION_MANDATORY");
+ tas.setProperties(attributes);
+ TransactionAttribute ta = tas.getTransactionAttribute(
+ Object.class.getMethod("hashCode", (Class[]) null), null);
+ assertNull(ta);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/TransactionInterceptorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/TransactionInterceptorTests.java
new file mode 100644
index 00000000000..fbe4b9f6cee
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/TransactionInterceptorTests.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.transaction.interceptor;
+
+import java.io.Serializable;
+import java.util.Properties;
+
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionException;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.util.SerializationTestUtils;
+
+/**
+ * Mock object based tests for TransactionInterceptor.
+ *
+ * @author Rod Johnson
+ * @since 16.03.2003
+ */
+public class TransactionInterceptorTests extends AbstractTransactionAspectTests {
+
+ protected Object advised(Object target, PlatformTransactionManager ptm, TransactionAttributeSource[] tas) throws Exception {
+ TransactionInterceptor ti = new TransactionInterceptor();
+ ti.setTransactionManager(ptm);
+ ti.setTransactionAttributeSources(tas);
+
+ ProxyFactory pf = new ProxyFactory(target);
+ pf.addAdvice(0, ti);
+ return pf.getProxy();
+ }
+
+ /**
+ * Template method to create an advised object given the
+ * target object and transaction setup.
+ * Creates a TransactionInterceptor and applies it.
+ */
+ protected Object advised(Object target, PlatformTransactionManager ptm, TransactionAttributeSource tas) {
+ TransactionInterceptor ti = new TransactionInterceptor();
+ ti.setTransactionManager(ptm);
+ assertEquals(ptm, ti.getTransactionManager());
+ ti.setTransactionAttributeSource(tas);
+ assertEquals(tas, ti.getTransactionAttributeSource());
+
+ ProxyFactory pf = new ProxyFactory(target);
+ pf.addAdvice(0, ti);
+ return pf.getProxy();
+ }
+
+/**
+ * A TransactionInterceptor should be serializable if its
+ * PlatformTransactionManager is.
+ */
+ public void testSerializableWithAttributeProperties() throws Exception {
+ TransactionInterceptor ti = new TransactionInterceptor();
+ Properties props = new Properties();
+ props.setProperty("methodName", "PROPAGATION_REQUIRED");
+ ti.setTransactionAttributes(props);
+ PlatformTransactionManager ptm = new SerializableTransactionManager();
+ ti.setTransactionManager(ptm);
+ ti = (TransactionInterceptor) SerializationTestUtils.serializeAndDeserialize(ti);
+
+ // Check that logger survived deserialization
+ assertNotNull(ti.logger);
+ assertTrue(ti.getTransactionManager() instanceof SerializableTransactionManager);
+ assertNotNull(ti.getTransactionAttributeSource());
+ }
+
+ public void testSerializableWithCompositeSource() throws Exception {
+ NameMatchTransactionAttributeSource tas1 = new NameMatchTransactionAttributeSource();
+ Properties props = new Properties();
+ props.setProperty("methodName", "PROPAGATION_REQUIRED");
+ tas1.setProperties(props);
+
+ NameMatchTransactionAttributeSource tas2 = new NameMatchTransactionAttributeSource();
+ props = new Properties();
+ props.setProperty("otherMethodName", "PROPAGATION_REQUIRES_NEW");
+ tas2.setProperties(props);
+
+ TransactionInterceptor ti = new TransactionInterceptor();
+ ti.setTransactionAttributeSources(new TransactionAttributeSource[] {tas1, tas2});
+ PlatformTransactionManager ptm = new SerializableTransactionManager();
+ ti.setTransactionManager(ptm);
+ ti = (TransactionInterceptor) SerializationTestUtils.serializeAndDeserialize(ti);
+
+ assertTrue(ti.getTransactionManager() instanceof SerializableTransactionManager);
+ assertTrue(ti.getTransactionAttributeSource() instanceof CompositeTransactionAttributeSource);
+ CompositeTransactionAttributeSource ctas = (CompositeTransactionAttributeSource) ti.getTransactionAttributeSource();
+ assertTrue(ctas.getTransactionAttributeSources()[0] instanceof NameMatchTransactionAttributeSource);
+ assertTrue(ctas.getTransactionAttributeSources()[1] instanceof NameMatchTransactionAttributeSource);
+ }
+
+
+ /**
+ * We won't use this: we just want to know it's serializable.
+ */
+ public static class SerializableTransactionManager implements PlatformTransactionManager, Serializable {
+
+ public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void commit(TransactionStatus status) throws TransactionException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void rollback(TransactionStatus status) throws TransactionException {
+ throw new UnsupportedOperationException();
+ }
+
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/noTransactionAttributeSource.xml b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/noTransactionAttributeSource.xml
new file mode 100644
index 00000000000..09c860fffd5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/noTransactionAttributeSource.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+ custom
+ 666
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/transactionalBeanFactory.xml b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/transactionalBeanFactory.xml
new file mode 100644
index 00000000000..942a13ddbef
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/interceptor/transactionalBeanFactory.xml
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+ dependency
+
+
+
+
+ custom
+ 666
+
+
+
+
+
+
+
+
+
+
+
+ org.springframework.beans.ITestBean.s*=PROPAGATION_MANDATORY
+ org.springframework.beans.ITestBean.setAg*=PROPAGATION_REQUIRED
+ org.springframework.beans.ITestBean.set*= PROPAGATION_SUPPORTS , readOnly
+
+
+
+
+
+
+ org.springframework.beans.ITestBean
+
+
+
+ txInterceptor
+ target
+
+
+
+
+
+
+
+
+ PROPAGATION_MANDATORY
+ PROPAGATION_REQUIRED , readOnly
+ PROPAGATION_SUPPORTS
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PROPAGATION_REQUIRED
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PROPAGATION_MANDATORY
+ PROPAGATION_REQUIRED
+ PROPAGATION_SUPPORTS
+
+
+ true
+ false
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/jta/MockUOWManager.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/jta/MockUOWManager.java
new file mode 100644
index 00000000000..94ca9025802
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/jta/MockUOWManager.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.transaction.jta;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.transaction.Synchronization;
+
+import com.ibm.wsspi.uow.UOWAction;
+import com.ibm.wsspi.uow.UOWActionException;
+import com.ibm.wsspi.uow.UOWException;
+import com.ibm.wsspi.uow.UOWManager;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class MockUOWManager implements UOWManager {
+
+ private int type = UOW_TYPE_GLOBAL_TRANSACTION;
+
+ private boolean joined;
+
+ private int timeout;
+
+ private boolean rollbackOnly;
+
+ private int status = UOW_STATUS_NONE;
+
+ private final Map resources = new HashMap();
+
+ private final List synchronizations = new LinkedList();
+
+
+ public void runUnderUOW(int type, boolean join, UOWAction action) throws UOWActionException, UOWException {
+ this.type = type;
+ this.joined = join;
+ try {
+ this.status = UOW_STATUS_ACTIVE;
+ action.run();
+ this.status = (this.rollbackOnly ? UOW_STATUS_ROLLEDBACK : UOW_STATUS_COMMITTED);
+ }
+ catch (Error err) {
+ this.status = UOW_STATUS_ROLLEDBACK;
+ throw err;
+ }
+ catch (RuntimeException ex) {
+ this.status = UOW_STATUS_ROLLEDBACK;
+ throw ex;
+ }
+ catch (Exception ex) {
+ this.status = UOW_STATUS_ROLLEDBACK;
+ throw new UOWActionException(ex);
+ }
+ }
+
+ public int getUOWType() {
+ return this.type;
+ }
+
+ public boolean getJoined() {
+ return this.joined;
+ }
+
+ public long getLocalUOWId() {
+ return 0;
+ }
+
+ public void setUOWTimeout(int uowType, int timeout) {
+ this.timeout = timeout;
+ }
+
+ public int getUOWTimeout() {
+ return this.timeout;
+ }
+
+ public void setRollbackOnly() {
+ this.rollbackOnly = true;
+ }
+
+ public boolean getRollbackOnly() {
+ return this.rollbackOnly;
+ }
+
+ public void setUOWStatus(int status) {
+ this.status = status;
+ }
+
+ public int getUOWStatus() {
+ return this.status;
+ }
+
+ public void putResource(Object key, Object value) {
+ this.resources.put(key, value);
+ }
+
+ public Object getResource(Object key) throws NullPointerException {
+ return this.resources.get(key);
+ }
+
+ public void registerInterposedSynchronization(Synchronization sync) {
+ this.synchronizations.add(sync);
+ }
+
+ public List getSynchronizations() {
+ return this.synchronizations;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/jta/WebSphereUowTransactionManagerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/jta/WebSphereUowTransactionManagerTests.java
new file mode 100644
index 00000000000..8c80f0f0131
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/jta/WebSphereUowTransactionManagerTests.java
@@ -0,0 +1,629 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.transaction.jta;
+
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.UserTransaction;
+
+import com.ibm.wsspi.uow.UOWAction;
+import com.ibm.wsspi.uow.UOWException;
+import com.ibm.wsspi.uow.UOWManager;
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.dao.OptimisticLockingFailureException;
+import org.springframework.mock.jndi.ExpectedLookupTemplate;
+import org.springframework.transaction.IllegalTransactionStateException;
+import org.springframework.transaction.NestedTransactionNotSupportedException;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.TransactionSystemException;
+import org.springframework.transaction.support.DefaultTransactionDefinition;
+import org.springframework.transaction.support.TransactionCallback;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class WebSphereUowTransactionManagerTests extends TestCase {
+
+ public void testUowManagerFoundInJndi() {
+ MockUOWManager manager = new MockUOWManager();
+ ExpectedLookupTemplate jndiTemplate =
+ new ExpectedLookupTemplate(WebSphereUowTransactionManager.DEFAULT_UOW_MANAGER_NAME, manager);
+ WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager();
+ ptm.setJndiTemplate(jndiTemplate);
+ ptm.afterPropertiesSet();
+
+ DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
+ assertEquals("result", ptm.execute(definition, new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ return "result";
+ }
+ }));
+
+ assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
+ assertFalse(manager.getJoined());
+ assertFalse(manager.getRollbackOnly());
+ }
+
+ public void testUowManagerAndUserTransactionFoundInJndi() throws Exception {
+ MockControl utControl = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utControl.getMock();
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
+ ut.getStatus();
+ utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
+ ut.begin();
+ utControl.setVoidCallable(1);
+ ut.commit();
+ utControl.setVoidCallable(1);
+ utControl.replay();
+
+ MockUOWManager manager = new MockUOWManager();
+ ExpectedLookupTemplate jndiTemplate = new ExpectedLookupTemplate();
+ jndiTemplate.addObject(WebSphereUowTransactionManager.DEFAULT_USER_TRANSACTION_NAME, ut);
+ jndiTemplate.addObject(WebSphereUowTransactionManager.DEFAULT_UOW_MANAGER_NAME, manager);
+ WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager();
+ ptm.setJndiTemplate(jndiTemplate);
+ ptm.afterPropertiesSet();
+
+ DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
+ TransactionStatus ts = ptm.getTransaction(definition);
+ ptm.commit(ts);
+ assertEquals("result", ptm.execute(definition, new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ return "result";
+ }
+ }));
+
+ assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
+ assertFalse(manager.getJoined());
+ assertFalse(manager.getRollbackOnly());
+ }
+
+ public void testPropagationMandatoryFailsInCaseOfNoExistingTransaction() {
+ MockUOWManager manager = new MockUOWManager();
+ WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
+ DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
+ definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_MANDATORY);
+
+ try {
+ ptm.execute(definition, new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ return "result";
+ }
+ });
+ fail("Should have thrown IllegalTransactionStateException");
+ }
+ catch (IllegalTransactionStateException ex) {
+ // expected
+ }
+ }
+
+ public void testNewTransactionSynchronizationUsingPropagationSupports() {
+ doTestNewTransactionSynchronization(
+ TransactionDefinition.PROPAGATION_SUPPORTS, WebSphereUowTransactionManager.SYNCHRONIZATION_ALWAYS);
+ }
+
+ public void testNewTransactionSynchronizationUsingPropagationNotSupported() {
+ doTestNewTransactionSynchronization(
+ TransactionDefinition.PROPAGATION_NOT_SUPPORTED, WebSphereUowTransactionManager.SYNCHRONIZATION_ALWAYS);
+ }
+
+ public void testNewTransactionSynchronizationUsingPropagationNever() {
+ doTestNewTransactionSynchronization(
+ TransactionDefinition.PROPAGATION_NEVER, WebSphereUowTransactionManager.SYNCHRONIZATION_ALWAYS);
+ }
+
+ public void testNewTransactionSynchronizationUsingPropagationSupportsAndSynchOnActual() {
+ doTestNewTransactionSynchronization(
+ TransactionDefinition.PROPAGATION_SUPPORTS, WebSphereUowTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
+ }
+
+ public void testNewTransactionSynchronizationUsingPropagationNotSupportedAndSynchOnActual() {
+ doTestNewTransactionSynchronization(
+ TransactionDefinition.PROPAGATION_NOT_SUPPORTED, WebSphereUowTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
+ }
+
+ public void testNewTransactionSynchronizationUsingPropagationNeverAndSynchOnActual() {
+ doTestNewTransactionSynchronization(
+ TransactionDefinition.PROPAGATION_NEVER, WebSphereUowTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
+ }
+
+ public void testNewTransactionSynchronizationUsingPropagationSupportsAndSynchNever() {
+ doTestNewTransactionSynchronization(
+ TransactionDefinition.PROPAGATION_SUPPORTS, WebSphereUowTransactionManager.SYNCHRONIZATION_NEVER);
+ }
+
+ public void testNewTransactionSynchronizationUsingPropagationNotSupportedAndSynchNever() {
+ doTestNewTransactionSynchronization(
+ TransactionDefinition.PROPAGATION_NOT_SUPPORTED, WebSphereUowTransactionManager.SYNCHRONIZATION_NEVER);
+ }
+
+ public void testNewTransactionSynchronizationUsingPropagationNeverAndSynchNever() {
+ doTestNewTransactionSynchronization(
+ TransactionDefinition.PROPAGATION_NEVER, WebSphereUowTransactionManager.SYNCHRONIZATION_NEVER);
+ }
+
+ private void doTestNewTransactionSynchronization(int propagationBehavior, final int synchMode) {
+ MockUOWManager manager = new MockUOWManager();
+ WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
+ ptm.setTransactionSynchronization(synchMode);
+ DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
+ definition.setPropagationBehavior(propagationBehavior);
+ definition.setReadOnly(true);
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ assertEquals("result", ptm.execute(definition, new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ if (synchMode == WebSphereUowTransactionManager.SYNCHRONIZATION_ALWAYS) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ }
+ else {
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ }
+ return "result";
+ }
+ }));
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ assertEquals(0, manager.getUOWTimeout());
+ assertEquals(UOWManager.UOW_TYPE_LOCAL_TRANSACTION, manager.getUOWType());
+ assertFalse(manager.getJoined());
+ assertFalse(manager.getRollbackOnly());
+ }
+
+ public void testNewTransactionWithCommitUsingPropagationRequired() {
+ doTestNewTransactionWithCommit(
+ TransactionDefinition.PROPAGATION_REQUIRED, WebSphereUowTransactionManager.SYNCHRONIZATION_ALWAYS);
+ }
+
+ public void testNewTransactionWithCommitUsingPropagationRequiresNew() {
+ doTestNewTransactionWithCommit(
+ TransactionDefinition.PROPAGATION_REQUIRES_NEW, WebSphereUowTransactionManager.SYNCHRONIZATION_ALWAYS);
+ }
+
+ public void testNewTransactionWithCommitUsingPropagationNested() {
+ doTestNewTransactionWithCommit(
+ TransactionDefinition.PROPAGATION_NESTED, WebSphereUowTransactionManager.SYNCHRONIZATION_ALWAYS);
+ }
+
+ public void testNewTransactionWithCommitUsingPropagationRequiredAndSynchOnActual() {
+ doTestNewTransactionWithCommit(
+ TransactionDefinition.PROPAGATION_REQUIRED, WebSphereUowTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
+ }
+
+ public void testNewTransactionWithCommitUsingPropagationRequiresNewAndSynchOnActual() {
+ doTestNewTransactionWithCommit(
+ TransactionDefinition.PROPAGATION_REQUIRES_NEW, WebSphereUowTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
+ }
+
+ public void testNewTransactionWithCommitUsingPropagationNestedAndSynchOnActual() {
+ doTestNewTransactionWithCommit(
+ TransactionDefinition.PROPAGATION_NESTED, WebSphereUowTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
+ }
+
+ public void testNewTransactionWithCommitUsingPropagationRequiredAndSynchNever() {
+ doTestNewTransactionWithCommit(
+ TransactionDefinition.PROPAGATION_REQUIRED, WebSphereUowTransactionManager.SYNCHRONIZATION_NEVER);
+ }
+
+ public void testNewTransactionWithCommitUsingPropagationRequiresNewAndSynchNever() {
+ doTestNewTransactionWithCommit(
+ TransactionDefinition.PROPAGATION_REQUIRES_NEW, WebSphereUowTransactionManager.SYNCHRONIZATION_NEVER);
+ }
+
+ public void testNewTransactionWithCommitUsingPropagationNestedAndSynchNever() {
+ doTestNewTransactionWithCommit(
+ TransactionDefinition.PROPAGATION_NESTED, WebSphereUowTransactionManager.SYNCHRONIZATION_NEVER);
+ }
+
+ private void doTestNewTransactionWithCommit(int propagationBehavior, final int synchMode) {
+ MockUOWManager manager = new MockUOWManager();
+ WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
+ ptm.setTransactionSynchronization(synchMode);
+ DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
+ definition.setPropagationBehavior(propagationBehavior);
+ definition.setReadOnly(true);
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ assertEquals("result", ptm.execute(definition, new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ if (synchMode != WebSphereUowTransactionManager.SYNCHRONIZATION_NEVER) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ }
+ else {
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ }
+ return "result";
+ }
+ }));
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ assertEquals(0, manager.getUOWTimeout());
+ assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
+ assertFalse(manager.getJoined());
+ assertFalse(manager.getRollbackOnly());
+ }
+
+ public void testNewTransactionWithCommitAndTimeout() {
+ MockUOWManager manager = new MockUOWManager();
+ WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
+ DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
+ definition.setTimeout(10);
+ definition.setReadOnly(true);
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ assertEquals("result", ptm.execute(definition, new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ return "result";
+ }
+ }));
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ assertEquals(10, manager.getUOWTimeout());
+ assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
+ assertFalse(manager.getJoined());
+ assertFalse(manager.getRollbackOnly());
+ }
+
+ public void testNewTransactionWithCommitException() {
+ final RollbackException rex = new RollbackException();
+ MockUOWManager manager = new MockUOWManager() {
+ public void runUnderUOW(int type, boolean join, UOWAction action) throws UOWException {
+ throw new UOWException(rex);
+ }
+ };
+ WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
+ DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ try {
+ ptm.execute(definition, new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ return "result";
+ }
+ });
+ fail("Should have thrown TransactionSystemException");
+ }
+ catch (TransactionSystemException ex) {
+ // expected
+ assertTrue(ex.getCause() instanceof UOWException);
+ assertSame(rex, ex.getRootCause());
+ assertSame(rex, ex.getMostSpecificCause());
+ }
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ assertEquals(0, manager.getUOWTimeout());
+ }
+
+ public void testNewTransactionWithRollback() {
+ MockUOWManager manager = new MockUOWManager();
+ WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
+ DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ try {
+ ptm.execute(definition, new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ throw new OptimisticLockingFailureException("");
+ }
+ });
+ fail("Should have thrown OptimisticLockingFailureException");
+ }
+ catch (OptimisticLockingFailureException ex) {
+ // expected
+ }
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ assertEquals(0, manager.getUOWTimeout());
+ assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
+ assertFalse(manager.getJoined());
+ assertFalse(manager.getRollbackOnly());
+ }
+
+ public void testNewTransactionWithRollbackOnly() {
+ MockUOWManager manager = new MockUOWManager();
+ WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
+ DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ assertEquals("result", ptm.execute(definition, new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ status.setRollbackOnly();
+ return "result";
+ }
+ }));
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ assertEquals(0, manager.getUOWTimeout());
+ assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
+ assertFalse(manager.getJoined());
+ assertTrue(manager.getRollbackOnly());
+ }
+
+ public void testExistingNonSpringTransaction() {
+ MockUOWManager manager = new MockUOWManager();
+ manager.setUOWStatus(UOWManager.UOW_STATUS_ACTIVE);
+ WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
+ DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ assertEquals("result", ptm.execute(definition, new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ return "result";
+ }
+ }));
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ assertEquals(0, manager.getUOWTimeout());
+ assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
+ assertTrue(manager.getJoined());
+ assertFalse(manager.getRollbackOnly());
+ }
+
+ public void testPropagationNeverFailsInCaseOfExistingTransaction() {
+ MockUOWManager manager = new MockUOWManager();
+ manager.setUOWStatus(UOWManager.UOW_STATUS_ACTIVE);
+ WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
+ DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
+ definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_NEVER);
+
+ try {
+ ptm.execute(definition, new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ return "result";
+ }
+ });
+ fail("Should have thrown IllegalTransactionStateException");
+ }
+ catch (IllegalTransactionStateException ex) {
+ // expected
+ }
+ }
+
+ public void testPropagationNestedFailsInCaseOfExistingTransaction() {
+ MockUOWManager manager = new MockUOWManager();
+ manager.setUOWStatus(UOWManager.UOW_STATUS_ACTIVE);
+ WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
+ DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
+ definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED);
+
+ try {
+ ptm.execute(definition, new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ return "result";
+ }
+ });
+ fail("Should have thrown NestedTransactionNotSupportedException");
+ }
+ catch (NestedTransactionNotSupportedException ex) {
+ // expected
+ }
+ }
+
+ public void testExistingTransactionWithParticipationUsingPropagationRequired() {
+ doTestExistingTransactionWithParticipation(TransactionDefinition.PROPAGATION_REQUIRED);
+ }
+
+ public void testExistingTransactionWithParticipationUsingPropagationSupports() {
+ doTestExistingTransactionWithParticipation(TransactionDefinition.PROPAGATION_SUPPORTS);
+ }
+
+ public void testExistingTransactionWithParticipationUsingPropagationMandatory() {
+ doTestExistingTransactionWithParticipation(TransactionDefinition.PROPAGATION_MANDATORY);
+ }
+
+ private void doTestExistingTransactionWithParticipation(int propagationBehavior) {
+ MockUOWManager manager = new MockUOWManager();
+ final WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
+ DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
+ final DefaultTransactionDefinition definition2 = new DefaultTransactionDefinition();
+ definition2.setPropagationBehavior(propagationBehavior);
+ definition2.setReadOnly(true);
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ assertEquals("result", ptm.execute(definition, new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertEquals("result2", ptm.execute(definition2, new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ return "result2";
+ }
+ }));
+ return "result";
+ }
+ }));
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ assertEquals(0, manager.getUOWTimeout());
+ assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
+ assertTrue(manager.getJoined());
+ assertFalse(manager.getRollbackOnly());
+ }
+
+ public void testExistingTransactionWithSuspensionUsingPropagationRequiresNew() {
+ doTestExistingTransactionWithSuspension(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+ }
+
+ public void testExistingTransactionWithSuspensionUsingPropagationNotSupported() {
+ doTestExistingTransactionWithSuspension(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
+ }
+
+ private void doTestExistingTransactionWithSuspension(final int propagationBehavior) {
+ MockUOWManager manager = new MockUOWManager();
+ final WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
+ DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
+ final DefaultTransactionDefinition definition2 = new DefaultTransactionDefinition();
+ definition2.setPropagationBehavior(propagationBehavior);
+ definition2.setReadOnly(true);
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ assertEquals("result", ptm.execute(definition, new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertEquals("result2", ptm.execute(definition2, new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertEquals(propagationBehavior == TransactionDefinition.PROPAGATION_REQUIRES_NEW,
+ TransactionSynchronizationManager.isActualTransactionActive());
+ assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ return "result2";
+ }
+ }));
+ return "result";
+ }
+ }));
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ assertEquals(0, manager.getUOWTimeout());
+ if (propagationBehavior == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
+ assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
+ }
+ else {
+ assertEquals(UOWManager.UOW_TYPE_LOCAL_TRANSACTION, manager.getUOWType());
+ }
+ assertFalse(manager.getJoined());
+ assertFalse(manager.getRollbackOnly());
+ }
+
+ public void testExistingTransactionUsingPropagationNotSupported() {
+ MockUOWManager manager = new MockUOWManager();
+ final WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
+ DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
+ final DefaultTransactionDefinition definition2 = new DefaultTransactionDefinition();
+ definition2.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
+ definition2.setReadOnly(true);
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ assertEquals("result", ptm.execute(definition, new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ assertEquals("result2", ptm.execute(definition2, new TransactionCallback() {
+ public Object doInTransaction(TransactionStatus status) {
+ assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+ return "result2";
+ }
+ }));
+ return "result";
+ }
+ }));
+
+ assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
+ assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
+ assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
+
+ assertEquals(0, manager.getUOWTimeout());
+ assertEquals(UOWManager.UOW_TYPE_LOCAL_TRANSACTION, manager.getUOWType());
+ assertFalse(manager.getJoined());
+ assertFalse(manager.getRollbackOnly());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/support/JtaTransactionManagerSerializationTests.java b/org.springframework.testsuite/src/test/java/org/springframework/transaction/support/JtaTransactionManagerSerializationTests.java
new file mode 100644
index 00000000000..19513be7ee8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/support/JtaTransactionManagerSerializationTests.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.transaction.support;
+
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.mock.jndi.SimpleNamingContextBuilder;
+import org.springframework.transaction.jta.JtaTransactionManager;
+import org.springframework.util.SerializationTestUtils;
+
+/**
+ * @author Rod Johnson
+ */
+public class JtaTransactionManagerSerializationTests extends TestCase {
+
+ public void testSerializable() throws Exception {
+ MockControl utMock = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut = (UserTransaction) utMock.getMock();
+ MockControl ut2Mock = MockControl.createControl(UserTransaction.class);
+ UserTransaction ut2 = (UserTransaction) ut2Mock.getMock();
+ MockControl tmMock = MockControl.createControl(TransactionManager.class);
+ TransactionManager tm = (TransactionManager) tmMock.getMock();
+
+ JtaTransactionManager jtam = new JtaTransactionManager();
+ jtam.setUserTransaction(ut);
+ jtam.setTransactionManager(tm);
+ jtam.setRollbackOnCommitFailure(true);
+ jtam.afterPropertiesSet();
+
+ SimpleNamingContextBuilder jndiEnv = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
+ jndiEnv.bind(JtaTransactionManager.DEFAULT_USER_TRANSACTION_NAME, ut2);
+ JtaTransactionManager serializedJtatm =
+ (JtaTransactionManager) SerializationTestUtils.serializeAndDeserialize(jtam);
+
+ // should do client-side lookup
+ assertNotNull("Logger must survive serialization", serializedJtatm.logger);
+ assertTrue("UserTransaction looked up on client", serializedJtatm.getUserTransaction() == ut2);
+ assertNull("TransactionManager didn't survive", serializedJtatm.getTransactionManager());
+ assertEquals(true, serializedJtatm.isRollbackOnCommitFailure());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/transaction/txNamespaceHandlerTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/transaction/txNamespaceHandlerTests.xml
new file mode 100644
index 00000000000..0a4b7e9f1c5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/transaction/txNamespaceHandlerTests.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/ui/ModelMapTests.java b/org.springframework.testsuite/src/test/java/org/springframework/ui/ModelMapTests.java
new file mode 100644
index 00000000000..5d41de4f58d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/ui/ModelMapTests.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.ui;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.beans.TestBean;
+import org.springframework.test.AssertThrows;
+import org.springframework.util.ClassUtils;
+import org.springframework.util.StringUtils;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public final class ModelMapTests extends TestCase {
+
+ public void testNoArgCtorYieldsEmptyModel() throws Exception {
+ assertEquals(0, new ModelMap().size());
+ }
+
+ /*
+ * SPR-2185 - Null model assertion causes backwards compatibility issue
+ */
+ public void testAddNullObjectWithExplicitKey() throws Exception {
+ ModelMap model = new ModelMap();
+ model.addAttribute("foo", null);
+ assertTrue(model.containsKey("foo"));
+ assertNull(model.get("foo"));
+ }
+
+ /*
+ * SPR-2185 - Null model assertion causes backwards compatibility issue
+ */
+ public void testAddNullObjectViaCtorWithExplicitKey() throws Exception {
+ ModelMap model = new ModelMap("foo", null);
+ assertTrue(model.containsKey("foo"));
+ assertNull(model.get("foo"));
+ }
+
+ public void testNamedObjectCtor() throws Exception {
+ ModelMap model = new ModelMap("foo", "bing");
+ assertEquals(1, model.size());
+ String bing = (String) model.get("foo");
+ assertNotNull(bing);
+ assertEquals("bing", bing);
+ }
+
+ public void testUnnamedCtorScalar() throws Exception {
+ ModelMap model = new ModelMap("foo", "bing");
+ assertEquals(1, model.size());
+ String bing = (String) model.get("foo");
+ assertNotNull(bing);
+ assertEquals("bing", bing);
+ }
+
+ public void testOneArgCtorWithScalar() throws Exception {
+ ModelMap model = new ModelMap("bing");
+ assertEquals(1, model.size());
+ String string = (String) model.get("string");
+ assertNotNull(string);
+ assertEquals("bing", string);
+ }
+
+ public void testOneArgCtorWithNull() throws Exception {
+ new AssertThrows(IllegalArgumentException.class, "Null model arguments added without a name being explicitly supplied are not allowed.") {
+ public void test() throws Exception {
+ new ModelMap(null);
+ }
+ }.runTest();
+ }
+
+ public void testOneArgCtorWithCollection() throws Exception {
+ ModelMap model = new ModelMap(new String[]{"foo", "boing"});
+ assertEquals(1, model.size());
+ String[] strings = (String[]) model.get("stringList");
+ assertNotNull(strings);
+ assertEquals(2, strings.length);
+ assertEquals("foo", strings[0]);
+ assertEquals("boing", strings[1]);
+ }
+
+ public void testOneArgCtorWithEmptyCollection() throws Exception {
+ ModelMap model = new ModelMap(new HashSet());
+ // must not add if collection is empty...
+ assertEquals(0, model.size());
+ }
+
+ public void testAddObjectWithNull() throws Exception {
+ new AssertThrows(IllegalArgumentException.class, "Null model arguments added without a name being explicitly supplied are not allowed.") {
+ public void test() throws Exception {
+ ModelMap model = new ModelMap();
+ model.addAttribute(null);
+ }
+ }.runTest();
+ }
+
+ public void testAddObjectWithEmptyArray() throws Exception {
+ ModelMap model = new ModelMap(new int[]{});
+ assertEquals(1, model.size());
+ int[] ints = (int[]) model.get("intList");
+ assertNotNull(ints);
+ assertEquals(0, ints.length);
+ }
+
+ public void testAddAllObjectsWithNullMap() throws Exception {
+ ModelMap model = new ModelMap();
+ model.addAllAttributes((Map) null);
+ assertEquals(0, model.size());
+ }
+
+ public void testAddAllObjectsWithNullCollection() throws Exception {
+ ModelMap model = new ModelMap();
+ model.addAllAttributes((Collection) null);
+ assertEquals(0, model.size());
+ }
+
+ public void testAddAllObjectsWithSparseArrayList() throws Exception {
+ new AssertThrows(IllegalArgumentException.class, "Null model arguments added without a name being explicitly supplied are not allowed.") {
+ public void test() throws Exception {
+ ModelMap model = new ModelMap();
+ ArrayList list = new ArrayList();
+ list.add("bing");
+ list.add(null);
+ model.addAllAttributes(list);
+ }
+ }.runTest();
+ }
+
+ public void testAddMap() throws Exception {
+ Map map = new HashMap();
+ map.put("one", "one-value");
+ map.put("two", "two-value");
+ ModelMap model = new ModelMap();
+ model.addAttribute(map);
+ assertEquals(1, model.size());
+ String key = StringUtils.uncapitalize(ClassUtils.getShortName(map.getClass()));
+ assertTrue(model.containsKey(key));
+ }
+
+ public void testAddObjectNoKeyOfSameTypeOverrides() throws Exception {
+ ModelMap model = new ModelMap();
+ model.addAttribute("foo");
+ model.addAttribute("bar");
+ assertEquals(1, model.size());
+ String bar = (String) model.get("string");
+ assertEquals("bar", bar);
+ }
+
+ public void testAddListOfTheSameObjects() throws Exception {
+ List beans = new ArrayList();
+ beans.add(new TestBean("one"));
+ beans.add(new TestBean("two"));
+ beans.add(new TestBean("three"));
+ ModelMap model = new ModelMap();
+ model.addAllAttributes(beans);
+ assertEquals(1, model.size());
+ }
+
+ public void testMergeMapWithOverriding() throws Exception {
+ Map beans = new HashMap();
+ beans.put("one", new TestBean("one"));
+ beans.put("two", new TestBean("two"));
+ beans.put("three", new TestBean("three"));
+ ModelMap model = new ModelMap();
+ model.put("one", new TestBean("oneOld"));
+ model.mergeAttributes(beans);
+ assertEquals(3, model.size());
+ assertEquals("oneOld", ((TestBean) model.get("one")).getName());
+ }
+
+ public void testInnerClass() throws Exception {
+ ModelMap map = new ModelMap();
+ SomeInnerClass inner = new SomeInnerClass();
+ map.addAttribute(inner);
+ assertSame(inner, map.get("someInnerClass"));
+ }
+
+ public void testInnerClassWithTwoUpperCaseLetters() throws Exception {
+ ModelMap map = new ModelMap();
+ UKInnerClass inner = new UKInnerClass();
+ map.addAttribute(inner);
+ assertSame(inner, map.get("UKInnerClass"));
+ }
+
+ public void testAopCglibProxy() throws Exception {
+ ModelMap map = new ModelMap();
+ ProxyFactory factory = new ProxyFactory();
+ Date date = new Date();
+ factory.setTarget(date);
+ factory.setProxyTargetClass(true);
+ map.addAttribute(factory.getProxy());
+ assertTrue(map.containsKey("date"));
+ assertEquals(date, map.get("date"));
+ }
+
+ public void testAopJdkProxy() throws Exception {
+ ModelMap map = new ModelMap();
+ ProxyFactory factory = new ProxyFactory();
+ Map target = new HashMap();
+ factory.setTarget(target);
+ factory.addInterface(Map.class);
+ Object proxy = factory.getProxy();
+ map.addAttribute(proxy);
+ assertSame(proxy, map.get("map"));
+ }
+
+ public void testAopJdkProxyWithMultipleInterfaces() throws Exception {
+ ModelMap map = new ModelMap();
+ Map target = new HashMap();
+ ProxyFactory factory = new ProxyFactory();
+ factory.setTarget(target);
+ factory.addInterface(Serializable.class);
+ factory.addInterface(Cloneable.class);
+ factory.addInterface(Comparable.class);
+ factory.addInterface(Map.class);
+ Object proxy = factory.getProxy();
+ map.addAttribute(proxy);
+ assertSame(proxy, map.get("map"));
+ }
+
+ public void testAopJdkProxyWithDetectedInterfaces() throws Exception {
+ ModelMap map = new ModelMap();
+ Map target = new HashMap();
+ ProxyFactory factory = new ProxyFactory(target);
+ Object proxy = factory.getProxy();
+ map.addAttribute(proxy);
+ assertSame(proxy, map.get("map"));
+ }
+
+ public void testRawJdkProxy() throws Exception {
+ ModelMap map = new ModelMap();
+ Object proxy = Proxy.newProxyInstance(
+ getClass().getClassLoader(),
+ new Class[] {Map.class},
+ new InvocationHandler() {
+ public Object invoke(Object proxy, Method method, Object[] args) {
+ return "proxy";
+ }
+ });
+ map.addAttribute(proxy);
+ assertSame(proxy, map.get("map"));
+ }
+
+
+ private static class SomeInnerClass {
+ }
+
+
+ private static class UKInnerClass {
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/DataSourceReport.jasper b/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/DataSourceReport.jasper
new file mode 100644
index 00000000000..8414447e09d
Binary files /dev/null and b/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/DataSourceReport.jasper differ
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/DataSourceReport.jrxml b/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/DataSourceReport.jrxml
new file mode 100644
index 00000000000..2df89cfb9e7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/DataSourceReport.jrxml
@@ -0,0 +1,185 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/JasperReportsUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/JasperReportsUtilsTests.java
new file mode 100644
index 00000000000..62c1807259e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/JasperReportsUtilsTests.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.ui.jasperreports;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+import junit.framework.TestCase;
+import net.sf.jasperreports.engine.JRDataSource;
+import net.sf.jasperreports.engine.JRParameter;
+import net.sf.jasperreports.engine.JasperFillManager;
+import net.sf.jasperreports.engine.JasperPrint;
+import net.sf.jasperreports.engine.JasperReport;
+import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
+import net.sf.jasperreports.engine.export.JRCsvExporterParameter;
+import net.sf.jasperreports.engine.export.JRExportProgressMonitor;
+import net.sf.jasperreports.engine.export.JRHtmlExporter;
+import net.sf.jasperreports.engine.export.JRHtmlExporterParameter;
+import net.sf.jasperreports.engine.export.JRPdfExporter;
+import net.sf.jasperreports.engine.export.JRPdfExporterParameter;
+import net.sf.jasperreports.engine.export.JRXlsExporterParameter;
+import net.sf.jasperreports.engine.util.JRLoader;
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+
+import org.springframework.core.io.ClassPathResource;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ * @since 18.11.2004
+ */
+public class JasperReportsUtilsTests extends TestCase {
+
+ public void testRenderAsCsvWithDataSource() throws Exception {
+ StringWriter writer = new StringWriter();
+ JasperReportsUtils.renderAsCsv(getReport(), getParameters(), getDataSource(), writer);
+ String output = writer.getBuffer().toString();
+ assertCsvOutputCorrect(output);
+ }
+
+ public void testRenderAsCsvWithCollection() throws Exception {
+ StringWriter writer = new StringWriter();
+ JasperReportsUtils.renderAsCsv(getReport(), getParameters(), getData(), writer);
+ String output = writer.getBuffer().toString();
+ assertCsvOutputCorrect(output);
+ }
+
+ public void testRenderAsCsvWithExporterParameters() throws Exception {
+ StringWriter writer = new StringWriter();
+ Map exporterParameters = new HashMap();
+ exporterParameters.put(JRCsvExporterParameter.FIELD_DELIMITER, "~");
+ JasperReportsUtils.renderAsCsv(getReport(), getParameters(), getData(), writer, exporterParameters);
+ String output = writer.getBuffer().toString();
+ assertCsvOutputCorrect(output);
+ assertTrue("Delimiter is incorrect", output.indexOf("~") > -1);
+ }
+
+ public void testRenderAsHtmlWithDataSource() throws Exception {
+ StringWriter writer = new StringWriter();
+ JasperReportsUtils.renderAsHtml(getReport(), getParameters(), getDataSource(), writer);
+ String output = writer.getBuffer().toString();
+ assertHtmlOutputCorrect(output);
+ }
+
+ public void testRenderAsHtmlWithCollection() throws Exception {
+ StringWriter writer = new StringWriter();
+ JasperReportsUtils.renderAsHtml(getReport(), getParameters(), getData(), writer);
+ String output = writer.getBuffer().toString();
+ assertHtmlOutputCorrect(output);
+ }
+
+ public void testRenderAsHtmlWithExporterParameters() throws Exception {
+ StringWriter writer = new StringWriter();
+ Map exporterParameters = new HashMap();
+ String uri = "/my/uri";
+ exporterParameters.put(JRHtmlExporterParameter.IMAGES_URI, uri);
+ JasperReportsUtils.renderAsHtml(getReport(), getParameters(), getData(), writer, exporterParameters);
+ String output = writer.getBuffer().toString();
+ assertHtmlOutputCorrect(output);
+ assertTrue("URI not included", output.indexOf(uri) > -1);
+ }
+
+ public void testRenderAsPdfWithDataSource() throws Exception {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ JasperReportsUtils.renderAsPdf(getReport(), getParameters(), getDataSource(), os);
+ byte[] output = os.toByteArray();
+ assertPdfOutputCorrect(output);
+ }
+
+ public void testRenderAsPdfWithCollection() throws Exception {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ JasperReportsUtils.renderAsPdf(getReport(), getParameters(), getData(), os);
+ byte[] output = os.toByteArray();
+ assertPdfOutputCorrect(output);
+ }
+
+ public void testRenderAsPdfWithExporterParameters() throws Exception {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ Map exporterParameters = new HashMap();
+ exporterParameters.put(JRPdfExporterParameter.PDF_VERSION, JRPdfExporterParameter.PDF_VERSION_1_6.toString());
+ JasperReportsUtils.renderAsPdf(getReport(), getParameters(), getData(), os, exporterParameters);
+ byte[] output = os.toByteArray();
+ assertPdfOutputCorrect(output);
+ assertTrue(new String(output).indexOf("PDF-1.6") > -1);
+ }
+
+ public void testRenderAsXlsWithDataSource() throws Exception {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ JasperReportsUtils.renderAsXls(getReport(), getParameters(), getDataSource(), os);
+ byte[] output = os.toByteArray();
+ assertXlsOutputCorrect(output);
+ }
+
+ public void testRenderAsXlsWithCollection() throws Exception {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ JasperReportsUtils.renderAsXls(getReport(), getParameters(), getData(), os);
+ byte[] output = os.toByteArray();
+ assertXlsOutputCorrect(output);
+ }
+
+ public void testRenderAsXlsWithExporterParameters() throws Exception {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ Map exporterParameters = new HashMap();
+
+ SimpleProgressMonitor monitor = new SimpleProgressMonitor();
+ exporterParameters.put(JRXlsExporterParameter.PROGRESS_MONITOR, monitor);
+
+ JasperReportsUtils.renderAsXls(getReport(), getParameters(), getData(), os, exporterParameters);
+ byte[] output = os.toByteArray();
+ assertXlsOutputCorrect(output);
+ assertTrue(monitor.isInvoked());
+ }
+
+ public void testRenderWithWriter() throws Exception {
+ StringWriter writer = new StringWriter();
+ JasperPrint print = JasperFillManager.fillReport(getReport(), getParameters(), getDataSource());
+ JasperReportsUtils.render(new JRHtmlExporter(), print, writer);
+ String output = writer.getBuffer().toString();
+ assertHtmlOutputCorrect(output);
+ }
+
+ public void testRenderWithOutputStream() throws Exception {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ JasperPrint print = JasperFillManager.fillReport(getReport(), getParameters(), getDataSource());
+ JasperReportsUtils.render(new JRPdfExporter(), print, os);
+ byte[] output = os.toByteArray();
+ assertPdfOutputCorrect(output);
+ }
+
+ private void assertCsvOutputCorrect(String output) {
+ assertTrue("Output length should be greater than 0", (output.length() > 0));
+ assertTrue("Output should start with Dear Lord!", output.startsWith("Dear Lord!"));
+ assertTrue("Output should contain 'MeineSeite'", output.indexOf("MeineSeite") > -1);
+ }
+
+ private void assertHtmlOutputCorrect(String output) {
+ assertTrue("Output length should be greater than 0", (output.length() > 0));
+ assertTrue("Output should contain ", output.indexOf("") > -1);
+ assertTrue("Output should contain 'MeineSeite'", output.indexOf("MeineSeite") > -1);
+ }
+
+ private void assertPdfOutputCorrect(byte[] output) throws Exception {
+ assertTrue("Output length should be greater than 0", (output.length > 0));
+
+ String translated = new String(output, "US-ASCII");
+ assertTrue("Output should start with %PDF", translated.startsWith("%PDF"));
+ }
+
+ private void assertXlsOutputCorrect(byte[] output) throws Exception {
+ HSSFWorkbook workbook = new HSSFWorkbook(new ByteArrayInputStream(output));
+ HSSFSheet sheet = workbook.getSheetAt(0);
+ assertNotNull("Sheet should not be null", sheet);
+ HSSFRow row = sheet.getRow(3);
+ HSSFCell cell = row.getCell((short) 1);
+ assertNotNull("Cell should not be null", cell);
+ assertEquals("Cell content should be Dear Lord!", "Dear Lord!", cell.getStringCellValue());
+ }
+
+ private JasperReport getReport() throws Exception {
+ ClassPathResource resource = new ClassPathResource("DataSourceReport.jasper", getClass());
+ return (JasperReport) JRLoader.loadObject(resource.getInputStream());
+ }
+
+ private Map getParameters() {
+ Map model = new HashMap();
+ model.put("ReportTitle", "Dear Lord!");
+ model.put(JRParameter.REPORT_LOCALE, Locale.GERMAN);
+ model.put(JRParameter.REPORT_RESOURCE_BUNDLE,
+ ResourceBundle.getBundle("org/springframework/ui/jasperreports/messages", Locale.GERMAN));
+ return model;
+ }
+
+ private JRDataSource getDataSource() {
+ return new JRBeanCollectionDataSource(getData());
+ }
+
+ private List getData() {
+ List list = new ArrayList();
+ for (int x = 0; x < 10; x++) {
+ PersonBean bean = new PersonBean();
+ bean.setId(x);
+ bean.setName("Rob Harrop");
+ bean.setStreet("foo");
+ list.add(bean);
+ }
+ return list;
+ }
+
+
+ private static class SimpleProgressMonitor implements JRExportProgressMonitor {
+
+ private boolean invoked = false;
+
+ public void afterPageExport() {
+ this.invoked = true;
+ }
+
+ public boolean isInvoked() {
+ return invoked;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/PersonBean.java b/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/PersonBean.java
new file mode 100644
index 00000000000..c3f19cf3e95
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/PersonBean.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.ui.jasperreports;
+
+/**
+ * @author Rob Harrop
+ */
+public class PersonBean {
+
+ private int id;
+
+ private String name;
+
+ private String street;
+
+ private String city;
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getStreet() {
+ return street;
+ }
+
+ public void setStreet(String street) {
+ this.street = street;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/ProductBean.java b/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/ProductBean.java
new file mode 100644
index 00000000000..4d83be1e923
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/ProductBean.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.ui.jasperreports;
+
+/**
+ * @author Rob Harrop
+ */
+public class ProductBean {
+
+ private int id;
+
+ private String name;
+
+ private float quantity;
+
+ private float price;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public float getQuantity() {
+ return quantity;
+ }
+
+ public void setQuantity(float quantity) {
+ this.quantity = quantity;
+ }
+
+ public float getPrice() {
+ return price;
+ }
+
+ public void setPrice(float price) {
+ this.price = price;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/messages_de.properties b/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/messages_de.properties
new file mode 100644
index 00000000000..4dd7d2be865
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/messages_de.properties
@@ -0,0 +1 @@
+page=MeineSeite
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/subReportChild.jasper b/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/subReportChild.jasper
new file mode 100644
index 00000000000..cd8ad2052ff
Binary files /dev/null and b/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/subReportChild.jasper differ
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/subReportChild.jrxml b/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/subReportChild.jrxml
new file mode 100644
index 00000000000..ede2a092214
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/subReportChild.jrxml
@@ -0,0 +1,227 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/subReportParent.jasper b/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/subReportParent.jasper
new file mode 100644
index 00000000000..aba7bb207d4
Binary files /dev/null and b/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/subReportParent.jasper differ
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/subReportParent.jrxml b/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/subReportParent.jrxml
new file mode 100644
index 00000000000..f2f9c08d3f9
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/ui/jasperreports/subReportParent.jrxml
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/AssertTests.java b/org.springframework.testsuite/src/test/java/org/springframework/util/AssertTests.java
new file mode 100644
index 00000000000..c910fb2daaa
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/AssertTests.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.util;
+
+import junit.framework.TestCase;
+import org.springframework.test.AssertThrows;
+
+import java.util.*;
+
+/**
+ * Unit tests for the {@link Assert} class.
+ *
+ * @author Keith Donald
+ * @author Erwin Vervaet
+ * @author Rick Evans
+ */
+public class AssertTests extends TestCase {
+
+ public void testInstanceOf() {
+ final Set set = new HashSet();
+ Assert.isInstanceOf(HashSet.class, set);
+ new AssertThrows(IllegalArgumentException.class, "a hash map is not a set") {
+ public void test() throws Exception {
+ Assert.isInstanceOf(HashMap.class, set);
+ }
+ }.runTest();
+ }
+
+ public void testIsNullDoesNotThrowExceptionIfArgumentIsNullWithMessage() {
+ Assert.isNull(null, "Bla");
+ }
+
+ public void testIsNullDoesNotThrowExceptionIfArgumentIsNull() {
+ Assert.isNull(null);
+ }
+
+ public void testIsNullThrowsExceptionIfArgumentIsNotNull() {
+ new AssertThrows(IllegalArgumentException.class, "object is not null") {
+ public void test() throws Exception {
+ Assert.isNull(new Object());
+ }
+ }.runTest();
+ }
+
+ public void testIsNullThrowsExceptionIfArgumentIsNotNullWithMessage() {
+ new AssertThrows(IllegalArgumentException.class, "object is not null") {
+ public void test() throws Exception {
+ Assert.isNull(new Object(), "Bla");
+ }
+
+ protected void checkExceptionExpectations(Exception actualException) {
+ assertEquals("Bla", actualException.getMessage());
+ super.checkExceptionExpectations(actualException);
+ }
+ }.runTest();
+ }
+
+ public void testIsTrueWithFalseExpressionThrowsException() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ Assert.isTrue(false);
+ }
+ }.runTest();
+ }
+
+ public void testIsTrueWithTrueExpressionSunnyDay() throws Exception {
+ Assert.isTrue(true);
+ }
+
+ public void testHasLengthWithNullStringThrowsException() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ Assert.hasLength(null);
+ }
+ }.runTest();
+ }
+
+ public void testHasLengthWithEmptyStringThrowsException() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ Assert.hasLength("");
+ }
+ }.runTest();
+ }
+
+ public void testHasLengthWithWhitespaceOnlyStringDoesNotThrowException() throws Exception {
+ Assert.hasLength("\t ");
+ }
+
+ public void testHasLengthSunnyDay() throws Exception {
+ Assert.hasLength("I Heart ...");
+ }
+
+ public void testDoesNotContainWithNullSearchStringDoesNotThrowException() throws Exception {
+ Assert.doesNotContain(null, "rod");
+ }
+
+ public void testDoesNotContainWithNullSubstringDoesNotThrowException() throws Exception {
+ Assert.doesNotContain("A cool chick's name is Brod. ", null);
+ }
+
+ public void testDoesNotContainWithEmptySubstringDoesNotThrowException() throws Exception {
+ Assert.doesNotContain("A cool chick's name is Brod. ", "");
+ }
+
+ public void testAssertNotEmptyWithNullCollectionThrowsException() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ Assert.notEmpty((Collection) null);
+ }
+ }.runTest();
+ }
+
+ public void testAssertNotEmptyWithEmptyCollectionThrowsException() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ Assert.notEmpty(new ArrayList());
+ }
+ }.runTest();
+ }
+
+ public void testAssertNotEmptyWithCollectionSunnyDay() throws Exception {
+ List collection = new ArrayList();
+ collection.add("");
+ Assert.notEmpty(collection);
+ }
+
+ public void testAssertNotEmptyWithNullMapThrowsException() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ Assert.notEmpty((Map) null);
+ }
+ }.runTest();
+ }
+
+ public void testAssertNotEmptyWithEmptyMapThrowsException() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ Assert.notEmpty(new HashMap());
+ }
+ }.runTest();
+ }
+
+ public void testAssertNotEmptyWithMapSunnyDay() throws Exception {
+ Map map = new HashMap();
+ map.put("", "");
+ Assert.notEmpty(map);
+ }
+
+ public void testIsInstanceofClassWithNullInstanceThrowsException() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ Assert.isInstanceOf(String.class, null);
+ }
+ }.runTest();
+ }
+
+ public void testStateWithFalseExpressionThrowsException() throws Exception {
+ new AssertThrows(IllegalStateException.class) {
+ public void test() throws Exception {
+ Assert.state(false);
+ }
+ }.runTest();
+ }
+
+ public void testStateWithTrueExpressionSunnyDay() throws Exception {
+ Assert.state(true);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/AutoPopulatingListTests.java b/org.springframework.testsuite/src/test/java/org/springframework/util/AutoPopulatingListTests.java
new file mode 100644
index 00000000000..31cd8626eab
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/AutoPopulatingListTests.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.util;
+
+import java.util.LinkedList;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class AutoPopulatingListTests extends TestCase {
+
+ public void testWithClass() throws Exception {
+ doTestWithClass(new AutoPopulatingList(TestBean.class));
+ }
+
+ public void testWithClassAndUserSuppliedBackingList() throws Exception {
+ doTestWithClass(new AutoPopulatingList(new LinkedList(), TestBean.class));
+ }
+
+ public void testWithElementFactory() throws Exception {
+ doTestWithElementFactory(new AutoPopulatingList(new MockElementFactory()));
+ }
+
+ public void testWithElementFactoryAndUserSuppliedBackingList() throws Exception {
+ doTestWithElementFactory(new AutoPopulatingList(new LinkedList(), new MockElementFactory()));
+ }
+
+ private void doTestWithClass(AutoPopulatingList list) {
+ Object lastElement = null;
+ for (int x = 0; x < 10; x++) {
+ Object element = list.get(x);
+ assertNotNull("Element is null", list.get(x));
+ assertTrue("Element is incorrect type", element instanceof TestBean);
+ assertNotSame(lastElement, element);
+ lastElement = element;
+ }
+
+ String helloWorld = "Hello World!";
+ list.add(10, null);
+ list.add(11, helloWorld);
+ assertEquals(helloWorld, list.get(11));
+
+ assertTrue(list.get(10) instanceof TestBean);
+ assertTrue(list.get(12) instanceof TestBean);
+ assertTrue(list.get(13) instanceof TestBean);
+ assertTrue(list.get(20) instanceof TestBean);
+ }
+
+ private void doTestWithElementFactory(AutoPopulatingList list) {
+ doTestWithClass(list);
+
+ for(int x = 0; x < list.size(); x++) {
+ Object element = list.get(x);
+ if(element instanceof TestBean) {
+ assertEquals(x, ((TestBean) element).getAge());
+ }
+ }
+ }
+
+ public void testSerialization() throws Exception {
+ AutoPopulatingList list = new AutoPopulatingList(TestBean.class);
+ assertEquals(list, SerializationTestUtils.serializeAndDeserialize(list));
+ }
+
+
+ private static class MockElementFactory implements AutoPopulatingList.ElementFactory {
+
+ public Object createElement(int index) {
+ TestBean bean = new TestBean();
+ bean.setAge(index);
+ return bean;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/CachingMapDecoratorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/util/CachingMapDecoratorTests.java
new file mode 100644
index 00000000000..04623853620
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/CachingMapDecoratorTests.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.util;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Keith Donald
+ */
+public class CachingMapDecoratorTests extends TestCase {
+
+ public void testValidCache() {
+ MyCachingMap cache = new MyCachingMap();
+ Object value;
+
+ value = cache.get("value key");
+ assertTrue(cache.createCalled());
+ assertEquals(value, "expensive value to cache");
+
+ cache.get("value key 2");
+ assertTrue(cache.createCalled());
+
+ value = cache.get("value key");
+ assertEquals(cache.createCalled(), false);
+ assertEquals(value, "expensive value to cache");
+
+ cache.get("value key 2");
+ assertEquals(cache.createCalled(), false);
+ assertEquals(value, "expensive value to cache");
+ }
+
+
+ private static class MyCachingMap extends CachingMapDecorator {
+
+ private boolean createCalled;
+
+ protected Object create(Object key) {
+ createCalled = true;
+ return "expensive value to cache";
+ }
+
+ public boolean createCalled() {
+ boolean c = createCalled;
+ this.createCalled = false;
+ return c;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/ClassUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/util/ClassUtilsTests.java
new file mode 100644
index 00000000000..af74cbc5932
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/ClassUtilsTests.java
@@ -0,0 +1,320 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.util;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.beans.DerivedTestBean;
+import org.springframework.beans.IOther;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+
+/**
+ * @author Colin Sampaleanu
+ * @author Juergen Hoeller
+ * @author Rob Harrop
+ * @author Rick Evans
+ */
+public class ClassUtilsTests extends TestCase {
+
+ public void setUp() {
+ InnerClass.noArgCalled = false;
+ InnerClass.argCalled = false;
+ InnerClass.overloadedCalled = false;
+ }
+
+ public void testIsPresent() throws Exception {
+ assertTrue(ClassUtils.isPresent("java.lang.String"));
+ assertFalse(ClassUtils.isPresent("java.lang.MySpecialString"));
+ }
+
+ public void testForName() throws ClassNotFoundException {
+ assertEquals(String.class, ClassUtils.forName("java.lang.String"));
+ assertEquals(String[].class, ClassUtils.forName("java.lang.String[]"));
+ assertEquals(String[].class, ClassUtils.forName(String[].class.getName()));
+ assertEquals(String[][].class, ClassUtils.forName(String[][].class.getName()));
+ assertEquals(String[][][].class, ClassUtils.forName(String[][][].class.getName()));
+ assertEquals(TestBean.class, ClassUtils.forName("org.springframework.beans.TestBean"));
+ assertEquals(TestBean[].class, ClassUtils.forName("org.springframework.beans.TestBean[]"));
+ assertEquals(TestBean[].class, ClassUtils.forName(TestBean[].class.getName()));
+ assertEquals(TestBean[][].class, ClassUtils.forName("org.springframework.beans.TestBean[][]"));
+ assertEquals(TestBean[][].class, ClassUtils.forName(TestBean[][].class.getName()));
+ }
+
+ public void testForNameWithPrimitiveClasses() throws ClassNotFoundException {
+ assertEquals(boolean.class, ClassUtils.forName("boolean"));
+ assertEquals(byte.class, ClassUtils.forName("byte"));
+ assertEquals(char.class, ClassUtils.forName("char"));
+ assertEquals(short.class, ClassUtils.forName("short"));
+ assertEquals(int.class, ClassUtils.forName("int"));
+ assertEquals(long.class, ClassUtils.forName("long"));
+ assertEquals(float.class, ClassUtils.forName("float"));
+ assertEquals(double.class, ClassUtils.forName("double"));
+ }
+
+ public void testForNameWithPrimitiveArrays() throws ClassNotFoundException {
+ assertEquals(boolean[].class, ClassUtils.forName("boolean[]"));
+ assertEquals(byte[].class, ClassUtils.forName("byte[]"));
+ assertEquals(char[].class, ClassUtils.forName("char[]"));
+ assertEquals(short[].class, ClassUtils.forName("short[]"));
+ assertEquals(int[].class, ClassUtils.forName("int[]"));
+ assertEquals(long[].class, ClassUtils.forName("long[]"));
+ assertEquals(float[].class, ClassUtils.forName("float[]"));
+ assertEquals(double[].class, ClassUtils.forName("double[]"));
+ }
+
+ public void testForNameWithPrimitiveArraysInternalName() throws ClassNotFoundException {
+ assertEquals(boolean[].class, ClassUtils.forName(boolean[].class.getName()));
+ assertEquals(byte[].class, ClassUtils.forName(byte[].class.getName()));
+ assertEquals(char[].class, ClassUtils.forName(char[].class.getName()));
+ assertEquals(short[].class, ClassUtils.forName(short[].class.getName()));
+ assertEquals(int[].class, ClassUtils.forName(int[].class.getName()));
+ assertEquals(long[].class, ClassUtils.forName(long[].class.getName()));
+ assertEquals(float[].class, ClassUtils.forName(float[].class.getName()));
+ assertEquals(double[].class, ClassUtils.forName(double[].class.getName()));
+ }
+
+ public void testGetShortName() {
+ String className = ClassUtils.getShortName(getClass());
+ assertEquals("Class name did not match", "ClassUtilsTests", className);
+ }
+
+ public void testGetShortNameForObjectArrayClass() {
+ String className = ClassUtils.getShortName(Object[].class);
+ assertEquals("Class name did not match", "Object[]", className);
+ }
+
+ public void testGetShortNameForMultiDimensionalObjectArrayClass() {
+ String className = ClassUtils.getShortName(Object[][].class);
+ assertEquals("Class name did not match", "Object[][]", className);
+ }
+
+ public void testGetShortNameForPrimitiveArrayClass() {
+ String className = ClassUtils.getShortName(byte[].class);
+ assertEquals("Class name did not match", "byte[]", className);
+ }
+
+ public void testGetShortNameForMultiDimensionalPrimitiveArrayClass() {
+ String className = ClassUtils.getShortName(byte[][][].class);
+ assertEquals("Class name did not match", "byte[][][]", className);
+ }
+
+ public void testGetShortNameForInnerClass() {
+ String className = ClassUtils.getShortName(InnerClass.class);
+ assertEquals("Class name did not match", "ClassUtilsTests.InnerClass", className);
+ }
+
+ public void testGetShortNameForCglibClass() {
+ TestBean tb = new TestBean();
+ ProxyFactory pf = new ProxyFactory();
+ pf.setTarget(tb);
+ pf.setProxyTargetClass(true);
+ TestBean proxy = (TestBean) pf.getProxy();
+ String className = ClassUtils.getShortName(proxy.getClass());
+ assertEquals("Class name did not match", "TestBean", className);
+ }
+
+ public void testGetShortNameAsProperty() {
+ String shortName = ClassUtils.getShortNameAsProperty(this.getClass());
+ assertEquals("Class name did not match", "classUtilsTests", shortName);
+ }
+
+ public void testGetClassFileName() {
+ assertEquals("String.class", ClassUtils.getClassFileName(String.class));
+ assertEquals("ClassUtilsTests.class", ClassUtils.getClassFileName(getClass()));
+ }
+
+ public void testGetPackageName() {
+ assertEquals("java.lang", ClassUtils.getPackageName(String.class));
+ assertEquals(getClass().getPackage().getName(), ClassUtils.getPackageName(getClass()));
+ }
+
+ public void testGetQualifiedName() {
+ String className = ClassUtils.getQualifiedName(getClass());
+ assertEquals("Class name did not match", "org.springframework.util.ClassUtilsTests", className);
+ }
+
+ public void testGetQualifiedNameForObjectArrayClass() {
+ String className = ClassUtils.getQualifiedName(Object[].class);
+ assertEquals("Class name did not match", "java.lang.Object[]", className);
+ }
+
+ public void testGetQualifiedNameForMultiDimensionalObjectArrayClass() {
+ String className = ClassUtils.getQualifiedName(Object[][].class);
+ assertEquals("Class name did not match", "java.lang.Object[][]", className);
+ }
+
+ public void testGetQualifiedNameForPrimitiveArrayClass() {
+ String className = ClassUtils.getQualifiedName(byte[].class);
+ assertEquals("Class name did not match", "byte[]", className);
+ }
+
+ public void testGetQualifiedNameForMultiDimensionalPrimitiveArrayClass() {
+ String className = ClassUtils.getQualifiedName(byte[][].class);
+ assertEquals("Class name did not match", "byte[][]", className);
+ }
+
+ public void testHasMethod() throws Exception {
+ assertTrue(ClassUtils.hasMethod(Collection.class, "size", null));
+ assertTrue(ClassUtils.hasMethod(Collection.class, "remove", new Class[] {Object.class}));
+ assertFalse(ClassUtils.hasMethod(Collection.class, "remove", null));
+ assertFalse(ClassUtils.hasMethod(Collection.class, "someOtherMethod", null));
+ }
+
+ public void testGetMethodIfAvailable() throws Exception {
+ Method method = ClassUtils.getMethodIfAvailable(Collection.class, "size", null);
+ assertNotNull(method);
+ assertEquals("size", method.getName());
+
+ method = ClassUtils.getMethodIfAvailable(Collection.class, "remove", new Class[] {Object.class});
+ assertNotNull(method);
+ assertEquals("remove", method.getName());
+
+ assertNull(ClassUtils.getMethodIfAvailable(Collection.class, "remove", null));
+ assertNull(ClassUtils.getMethodIfAvailable(Collection.class, "someOtherMethod", null));
+ }
+
+ public void testGetMethodCountForName() {
+ assertEquals("Verifying number of overloaded 'print' methods for OverloadedMethodsClass.", 2,
+ ClassUtils.getMethodCountForName(OverloadedMethodsClass.class, "print"));
+ assertEquals("Verifying number of overloaded 'print' methods for SubOverloadedMethodsClass.", 4,
+ ClassUtils.getMethodCountForName(SubOverloadedMethodsClass.class, "print"));
+ }
+
+ public void testCountOverloadedMethods() {
+ assertFalse(ClassUtils.hasAtLeastOneMethodWithName(TestBean.class, "foobar"));
+ // no args
+ assertTrue(ClassUtils.hasAtLeastOneMethodWithName(TestBean.class, "hashCode"));
+ // matches although it takes an arg
+ assertTrue(ClassUtils.hasAtLeastOneMethodWithName(TestBean.class, "setAge"));
+ }
+
+ public void testNoArgsStaticMethod() throws IllegalAccessException, InvocationTargetException {
+ Method method = ClassUtils.getStaticMethod(InnerClass.class, "staticMethod", (Class[]) null);
+ method.invoke(null, (Object[]) null);
+ assertTrue("no argument method was not invoked.",
+ InnerClass.noArgCalled);
+ }
+
+ public void testArgsStaticMethod() throws IllegalAccessException, InvocationTargetException {
+ Method method = ClassUtils.getStaticMethod(InnerClass.class, "argStaticMethod",
+ new Class[] {String.class});
+ method.invoke(null, new Object[] {"test"});
+ assertTrue("argument method was not invoked.", InnerClass.argCalled);
+ }
+
+ public void testOverloadedStaticMethod() throws IllegalAccessException, InvocationTargetException {
+ Method method = ClassUtils.getStaticMethod(InnerClass.class, "staticMethod",
+ new Class[] {String.class});
+ method.invoke(null, new Object[] {"test"});
+ assertTrue("argument method was not invoked.",
+ InnerClass.overloadedCalled);
+ }
+
+ public void testClassPackageAsResourcePath() {
+ String result = ClassUtils.classPackageAsResourcePath(Proxy.class);
+ assertTrue(result.equals("java/lang/reflect"));
+ }
+
+ public void testAddResourcePathToPackagePath() {
+ String result = "java/lang/reflect/xyzabc.xml";
+ assertEquals(result, ClassUtils.addResourcePathToPackagePath(Proxy.class, "xyzabc.xml"));
+ assertEquals(result, ClassUtils.addResourcePathToPackagePath(Proxy.class, "/xyzabc.xml"));
+
+ assertEquals("java/lang/reflect/a/b/c/d.xml",
+ ClassUtils.addResourcePathToPackagePath(Proxy.class, "a/b/c/d.xml"));
+ }
+
+ public void testGetAllInterfaces() {
+ DerivedTestBean testBean = new DerivedTestBean();
+ List ifcs = Arrays.asList(ClassUtils.getAllInterfaces(testBean));
+ assertEquals("Correct number of interfaces", 7, ifcs.size());
+ assertTrue("Contains Serializable", ifcs.contains(Serializable.class));
+ assertTrue("Contains ITestBean", ifcs.contains(ITestBean.class));
+ assertTrue("Contains IOther", ifcs.contains(IOther.class));
+ }
+
+ public void testClassNamesToString() {
+ List ifcs = new LinkedList();
+ ifcs.add(Serializable.class);
+ ifcs.add(Runnable.class);
+ assertEquals("[interface java.io.Serializable, interface java.lang.Runnable]", ifcs.toString());
+ assertEquals("[java.io.Serializable, java.lang.Runnable]", ClassUtils.classNamesToString(ifcs));
+
+ List classes = new LinkedList();
+ classes.add(LinkedList.class);
+ classes.add(Integer.class);
+ assertEquals("[class java.util.LinkedList, class java.lang.Integer]", classes.toString());
+ assertEquals("[java.util.LinkedList, java.lang.Integer]", ClassUtils.classNamesToString(classes));
+
+ assertEquals("[interface java.util.List]", Collections.singletonList(List.class).toString());
+ assertEquals("[java.util.List]", ClassUtils.classNamesToString(Collections.singletonList(List.class)));
+
+ assertEquals("[]", Collections.EMPTY_LIST.toString());
+ assertEquals("[]", ClassUtils.classNamesToString(Collections.EMPTY_LIST));
+ }
+
+
+ public static class InnerClass {
+
+ static boolean noArgCalled;
+ static boolean argCalled;
+ static boolean overloadedCalled;
+
+ public static void staticMethod() {
+ noArgCalled = true;
+ }
+
+ public static void staticMethod(String anArg) {
+ overloadedCalled = true;
+ }
+
+ public static void argStaticMethod(String anArg) {
+ argCalled = true;
+ }
+ }
+
+ private static class OverloadedMethodsClass {
+ public void print(String messages) {
+ /* no-op */
+ }
+ public void print(String[] messages) {
+ /* no-op */
+ }
+ }
+
+ private static class SubOverloadedMethodsClass extends OverloadedMethodsClass{
+ public void print(String header, String[] messages) {
+ /* no-op */
+ }
+ void print(String header, String[] messages, String footer) {
+ /* no-op */
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/CollectionUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/util/CollectionUtilsTests.java
new file mode 100644
index 00000000000..6f9150a4b72
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/CollectionUtilsTests.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.util;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ */
+public class CollectionUtilsTests extends TestCase {
+
+ public void testIsEmpty() {
+ assertTrue(CollectionUtils.isEmpty((Set) null));
+ assertTrue(CollectionUtils.isEmpty((Map) null));
+ assertTrue(CollectionUtils.isEmpty(new HashMap()));
+ assertTrue(CollectionUtils.isEmpty(new HashSet()));
+
+ List list = new LinkedList();
+ list.add(new Object());
+ assertFalse(CollectionUtils.isEmpty(list));
+
+ Map map = new HashMap();
+ map.put("foo", "bar");
+ assertFalse(CollectionUtils.isEmpty(map));
+ }
+
+ public void testMergeArrayIntoCollection() {
+ Object[] arr = new Object[] {"value1", "value2"};
+ List list = new LinkedList();
+ list.add("value3");
+
+ CollectionUtils.mergeArrayIntoCollection(arr, list);
+ assertEquals("value3", list.get(0));
+ assertEquals("value1", list.get(1));
+ assertEquals("value2", list.get(2));
+ }
+
+ public void testMergePrimitiveArrayIntoCollection() {
+ int[] arr = new int[] {1, 2};
+ List list = new LinkedList();
+ list.add(new Integer(3));
+
+ CollectionUtils.mergeArrayIntoCollection(arr, list);
+ assertEquals(new Integer(3), list.get(0));
+ assertEquals(new Integer(1), list.get(1));
+ assertEquals(new Integer(2), list.get(2));
+ }
+
+ public void testMergePropertiesIntoMap() {
+ Properties defaults = new Properties();
+ defaults.setProperty("prop1", "value1");
+ Properties props = new Properties(defaults);
+ props.setProperty("prop2", "value2");
+
+ Map map = new HashMap();
+ map.put("prop3", "value3");
+
+ CollectionUtils.mergePropertiesIntoMap(props, map);
+ assertEquals("value1", map.get("prop1"));
+ assertEquals("value2", map.get("prop2"));
+ assertEquals("value3", map.get("prop3"));
+ }
+
+ public void testContains() {
+ assertFalse(CollectionUtils.contains((Iterator) null, "myElement"));
+ assertFalse(CollectionUtils.contains((Enumeration) null, "myElement"));
+ assertFalse(CollectionUtils.contains(new LinkedList().iterator(), "myElement"));
+ assertFalse(CollectionUtils.contains(new Hashtable().keys(), "myElement"));
+
+ List list = new LinkedList();
+ list.add("myElement");
+ assertTrue(CollectionUtils.contains(list.iterator(), "myElement"));
+
+ Hashtable ht = new Hashtable();
+ ht.put("myElement", "myValue");
+ assertTrue(CollectionUtils.contains(ht.keys(), "myElement"));
+ }
+
+ public void testContainsAny() throws Exception {
+ List source = new ArrayList();
+ source.add("abc");
+ source.add("def");
+ source.add("ghi");
+
+ List candidates = new ArrayList();
+ candidates.add("xyz");
+ candidates.add("def");
+ candidates.add("abc");
+
+ assertTrue(CollectionUtils.containsAny(source, candidates));
+ candidates.remove("def");
+ assertTrue(CollectionUtils.containsAny(source, candidates));
+ candidates.remove("abc");
+ assertFalse(CollectionUtils.containsAny(source, candidates));
+ }
+
+ public void testContainsInstanceWithNullCollection() throws Exception {
+ assertFalse("Must return false if supplied Collection argument is null",
+ CollectionUtils.containsInstance(null, this));
+ }
+
+ public void testContainsInstanceWithInstancesThatAreEqualButDistinct() throws Exception {
+ List list = new ArrayList();
+ list.add(new Instance("fiona"));
+ assertFalse("Must return false if instance is not in the supplied Collection argument",
+ CollectionUtils.containsInstance(list, new Instance("fiona")));
+ }
+
+ public void testContainsInstanceWithSameInstance() throws Exception {
+ List list = new ArrayList();
+ list.add(new Instance("apple"));
+ Instance instance = new Instance("fiona");
+ list.add(instance);
+ assertTrue("Must return true if instance is in the supplied Collection argument",
+ CollectionUtils.containsInstance(list, instance));
+ }
+
+ public void testContainsInstanceWithNullInstance() throws Exception {
+ List list = new ArrayList();
+ list.add(new Instance("apple"));
+ list.add(new Instance("fiona"));
+ assertFalse("Must return false if null instance is supplied",
+ CollectionUtils.containsInstance(list, null));
+ }
+
+ public void testFindFirstMatch() throws Exception {
+ List source = new ArrayList();
+ source.add("abc");
+ source.add("def");
+ source.add("ghi");
+
+ List candidates = new ArrayList();
+ candidates.add("xyz");
+ candidates.add("def");
+ candidates.add("abc");
+
+ assertEquals("def", CollectionUtils.findFirstMatch(source, candidates));
+ }
+
+ public void testHasUniqueObject() {
+ List list = new LinkedList();
+ list.add("myElement");
+ list.add("myOtherElement");
+ assertFalse(CollectionUtils.hasUniqueObject(list));
+
+ list = new LinkedList();
+ list.add("myElement");
+ assertTrue(CollectionUtils.hasUniqueObject(list));
+
+ list = new LinkedList();
+ list.add("myElement");
+ list.add(null);
+ assertFalse(CollectionUtils.hasUniqueObject(list));
+
+ list = new LinkedList();
+ list.add(null);
+ list.add("myElement");
+ assertFalse(CollectionUtils.hasUniqueObject(list));
+
+ list = new LinkedList();
+ list.add(null);
+ list.add(null);
+ assertTrue(CollectionUtils.hasUniqueObject(list));
+
+ list = new LinkedList();
+ list.add(null);
+ assertTrue(CollectionUtils.hasUniqueObject(list));
+
+ list = new LinkedList();
+ assertFalse(CollectionUtils.hasUniqueObject(list));
+ }
+
+
+ private static final class Instance {
+
+ private final String name;
+
+ public Instance(String name) {
+ this.name = name;
+ }
+
+ public boolean equals(Object rhs) {
+ if (this == rhs) {
+ return true;
+ }
+ if (rhs == null || this.getClass() != rhs.getClass()) {
+ return false;
+ }
+ Instance instance = (Instance) rhs;
+ return this.name.equals(instance.name);
+ }
+
+ public int hashCode() {
+ return this.name.hashCode();
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/FileCopyUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/util/FileCopyUtilsTests.java
new file mode 100644
index 00000000000..6848c4d197f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/FileCopyUtilsTests.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for the FileCopyUtils class.
+ *
+ * @author Juergen Hoeller
+ * @since 12.03.2005
+ */
+public class FileCopyUtilsTests extends TestCase {
+
+ public void testCopyFromInputStream() throws IOException {
+ byte[] content = "content".getBytes();
+ ByteArrayInputStream in = new ByteArrayInputStream(content);
+ ByteArrayOutputStream out = new ByteArrayOutputStream(content.length);
+ int count = FileCopyUtils.copy(in, out);
+ assertEquals(content.length, count);
+ assertTrue(Arrays.equals(content, out.toByteArray()));
+ }
+
+ public void testCopyFromByteArray() throws IOException {
+ byte[] content = "content".getBytes();
+ ByteArrayOutputStream out = new ByteArrayOutputStream(content.length);
+ FileCopyUtils.copy(content, out);
+ assertTrue(Arrays.equals(content, out.toByteArray()));
+ }
+
+ public void testCopyToByteArray() throws IOException {
+ byte[] content = "content".getBytes();
+ ByteArrayInputStream in = new ByteArrayInputStream(content);
+ byte[] result = FileCopyUtils.copyToByteArray(in);
+ assertTrue(Arrays.equals(content, result));
+ }
+
+ public void testCopyFromReader() throws IOException {
+ String content = "content";
+ StringReader in = new StringReader(content);
+ StringWriter out = new StringWriter();
+ int count = FileCopyUtils.copy(in, out);
+ assertEquals(content.length(), count);
+ assertEquals(content, out.toString());
+ }
+
+ public void testCopyFromString() throws IOException {
+ String content = "content";
+ StringWriter out = new StringWriter();
+ FileCopyUtils.copy(content, out);
+ assertEquals(content, out.toString());
+ }
+
+ public void testCopyToString() throws IOException {
+ String content = "content";
+ StringReader in = new StringReader(content);
+ String result = FileCopyUtils.copyToString(in);
+ assertEquals(content, result);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/FileSystemUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/util/FileSystemUtilsTests.java
new file mode 100644
index 00000000000..f15b52ffc4d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/FileSystemUtilsTests.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.util;
+
+import java.io.File;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rob Harrop
+ */
+public class FileSystemUtilsTests extends TestCase {
+
+ public void testDeleteRecursively() throws Exception {
+ File root = new File("./tmp/root");
+ File child = new File(root, "child");
+ File grandchild = new File(child, "grandchild");
+
+ grandchild.mkdirs();
+
+ File bar = new File(child, "bar.txt");
+ bar.createNewFile();
+
+ assertTrue(root.exists());
+ assertTrue(child.exists());
+ assertTrue(grandchild.exists());
+ assertTrue(bar.exists());
+
+ FileSystemUtils.deleteRecursively(root);
+
+ assertFalse(root.exists());
+ assertFalse(child.exists());
+ assertFalse(grandchild.exists());
+ assertFalse(bar.exists());
+ }
+
+ public void testCopyRecursively() throws Exception {
+ File src = new File("./tmp/src");
+ File child = new File(src, "child");
+ File grandchild = new File(child, "grandchild");
+
+ grandchild.mkdirs();
+
+ File bar = new File(child, "bar.txt");
+ bar.createNewFile();
+
+ assertTrue(src.exists());
+ assertTrue(child.exists());
+ assertTrue(grandchild.exists());
+ assertTrue(bar.exists());
+
+ File dest = new File("./dest");
+ FileSystemUtils.copyRecursively(src, dest);
+
+ assertTrue(dest.exists());
+ assertTrue(new File(dest, child.getName()).exists());
+
+ FileSystemUtils.deleteRecursively(src);
+ assertTrue(!src.exists());
+ }
+
+ protected void tearDown() throws Exception {
+ File tmp = new File("./tmp");
+ if (tmp.exists()) {
+ FileSystemUtils.deleteRecursively(tmp);
+ }
+ File dest = new File("./dest");
+ if (dest.exists()) {
+ FileSystemUtils.deleteRecursively(dest);
+ }
+ super.tearDown();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/Log4jConfigurerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/util/Log4jConfigurerTests.java
new file mode 100644
index 00000000000..5b36d46f893
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/Log4jConfigurerTests.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.util;
+
+import java.io.FileNotFoundException;
+import java.net.URL;
+
+import junit.framework.TestCase;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * @author Alef Arendsen
+ * @author Juergen Hoeller
+ */
+public class Log4jConfigurerTests extends TestCase {
+
+ public void testInitLoggingWithClasspath() throws FileNotFoundException {
+ doTestInitLogging("classpath:org/springframework/util/testlog4j.properties", false);
+ }
+
+ public void testInitLoggingWithRelativeFilePath() throws FileNotFoundException {
+ doTestInitLogging("test/org/springframework/util/testlog4j.properties", false);
+ }
+
+ public void testInitLoggingWithAbsoluteFilePath() throws FileNotFoundException {
+ URL url = getClass().getResource("testlog4j.properties");
+ doTestInitLogging(url.toString(), false);
+ }
+
+ public void testInitLoggingWithClasspathAndRefreshInterval() throws FileNotFoundException {
+ doTestInitLogging("classpath:org/springframework/util/testlog4j.properties", true);
+ }
+
+ public void testInitLoggingWithRelativeFilePathAndRefreshInterval() throws FileNotFoundException {
+ doTestInitLogging("test/org/springframework/util/testlog4j.properties", true);
+ }
+
+ /* only works on Windows
+ public void testInitLoggingWithAbsoluteFilePathAndRefreshInterval() throws FileNotFoundException {
+ URL url = getClass().getResource("testlog4j.properties");
+ doTestInitLogging(url.getFile(), true);
+ }
+ */
+
+ public void testInitLoggingWithFileUrlAndRefreshInterval() throws FileNotFoundException {
+ URL url = getClass().getResource("testlog4j.properties");
+ doTestInitLogging(url.toString(), true);
+ }
+
+ private void doTestInitLogging(String location, boolean refreshInterval) throws FileNotFoundException {
+ if (refreshInterval) {
+ Log4jConfigurer.initLogging(location, 10);
+ }
+ else {
+ Log4jConfigurer.initLogging(location);
+ }
+
+ Log log = LogFactory.getLog(this.getClass());
+ log.debug("debug");
+ log.info("info");
+ log.warn("warn");
+ log.error("error");
+ log.fatal("fatal");
+
+ assertTrue(MockLog4jAppender.loggingStrings.contains("debug"));
+ assertTrue(MockLog4jAppender.loggingStrings.contains("info"));
+ assertTrue(MockLog4jAppender.loggingStrings.contains("warn"));
+ assertTrue(MockLog4jAppender.loggingStrings.contains("error"));
+ assertTrue(MockLog4jAppender.loggingStrings.contains("fatal"));
+
+ Log4jConfigurer.shutdownLogging();
+ assertTrue(MockLog4jAppender.closeCalled);
+ }
+
+ public void testInitLoggingWithRefreshIntervalAndFileNotFound() throws FileNotFoundException {
+ try {
+ Log4jConfigurer.initLogging("test/org/springframework/util/bla.properties", 10);
+ fail("Exception should have been thrown, file does not exist!");
+ }
+ catch (FileNotFoundException ex) {
+ // OK
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/MethodInvokerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/util/MethodInvokerTests.java
new file mode 100644
index 00000000000..955d788c746
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/MethodInvokerTests.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Colin Sampaleanu
+ * @author Juergen Hoeller
+ * @since 21.11.2003
+ */
+public class MethodInvokerTests extends TestCase {
+
+ public void testPlainMethodInvoker() throws Exception {
+ // sanity check: singleton, non-static should work
+ TestClass1 tc1 = new TestClass1();
+ MethodInvoker mi = new MethodInvoker();
+ mi.setTargetObject(tc1);
+ mi.setTargetMethod("method1");
+ mi.prepare();
+ Integer i = (Integer) mi.invoke();
+ assertEquals(1, i.intValue());
+
+ // sanity check: check that argument count matching works
+ mi = new MethodInvoker();
+ mi.setTargetClass(TestClass1.class);
+ mi.setTargetMethod("supertypes");
+ mi.setArguments(new Object[] {new ArrayList(), new ArrayList(), "hello"});
+ mi.prepare();
+ assertEquals("hello", mi.invoke());
+
+ mi = new MethodInvoker();
+ mi.setTargetClass(TestClass1.class);
+ mi.setTargetMethod("supertypes2");
+ mi.setArguments(new Object[] {new ArrayList(), new ArrayList(), "hello", "bogus"});
+ mi.prepare();
+ assertEquals("hello", mi.invoke());
+
+ // Sanity check: check that argument conversion doesn't work with plain MethodInvoker
+ mi = new MethodInvoker();
+ mi.setTargetClass(TestClass1.class);
+ mi.setTargetMethod("supertypes2");
+ mi.setArguments(new Object[] {new ArrayList(), new ArrayList(), "hello", Boolean.TRUE});
+ try {
+ mi.prepare();
+ fail("Shouldn't have matched without argument conversion");
+ }
+ catch (NoSuchMethodException ex) {
+ // expected
+ }
+ }
+
+ public void testStringWithMethodInvoker() throws Exception {
+ try {
+ MethodInvoker methodInvoker = new MethodInvoker();
+ methodInvoker.setTargetObject(new Greeter());
+ methodInvoker.setTargetMethod("greet");
+ methodInvoker.setArguments(new Object[] {new String("no match")});
+ methodInvoker.prepare();
+ fail("Should have thrown a NoSuchMethodException");
+ }
+ catch (NoSuchMethodException e) {
+ // expected
+ }
+ }
+
+ public void testPurchaserWithMethodInvoker() throws Exception {
+ MethodInvoker methodInvoker = new MethodInvoker();
+ methodInvoker.setTargetObject(new Greeter());
+ methodInvoker.setTargetMethod("greet");
+ methodInvoker.setArguments(new Object[] {new Purchaser()});
+ methodInvoker.prepare();
+ String greeting = (String) methodInvoker.invoke();
+ assertEquals("purchaser: hello", greeting);
+ }
+
+ public void testShopperWithMethodInvoker() throws Exception {
+ MethodInvoker methodInvoker = new MethodInvoker();
+ methodInvoker.setTargetObject(new Greeter());
+ methodInvoker.setTargetMethod("greet");
+ methodInvoker.setArguments(new Object[] {new Shopper()});
+ methodInvoker.prepare();
+ String greeting = (String) methodInvoker.invoke();
+ assertEquals("purchaser: may I help you?", greeting);
+ }
+
+ public void testSalesmanWithMethodInvoker() throws Exception {
+ MethodInvoker methodInvoker = new MethodInvoker();
+ methodInvoker.setTargetObject(new Greeter());
+ methodInvoker.setTargetMethod("greet");
+ methodInvoker.setArguments(new Object[] {new Salesman()});
+ methodInvoker.prepare();
+ String greeting = (String) methodInvoker.invoke();
+ assertEquals("greetable: how are sales?", greeting);
+ }
+
+ public void testCustomerWithMethodInvoker() throws Exception {
+ MethodInvoker methodInvoker = new MethodInvoker();
+ methodInvoker.setTargetObject(new Greeter());
+ methodInvoker.setTargetMethod("greet");
+ methodInvoker.setArguments(new Object[] {new Customer()});
+ methodInvoker.prepare();
+ String greeting = (String) methodInvoker.invoke();
+ assertEquals("customer: good day", greeting);
+ }
+
+ public void testRegularWithMethodInvoker() throws Exception {
+ MethodInvoker methodInvoker = new MethodInvoker();
+ methodInvoker.setTargetObject(new Greeter());
+ methodInvoker.setTargetMethod("greet");
+ methodInvoker.setArguments(new Object[] {new Regular("Kotter")});
+ methodInvoker.prepare();
+ String greeting = (String) methodInvoker.invoke();
+ assertEquals("regular: welcome back Kotter", greeting);
+ }
+
+ public void testVIPWithMethodInvoker() throws Exception {
+ MethodInvoker methodInvoker = new MethodInvoker();
+ methodInvoker.setTargetObject(new Greeter());
+ methodInvoker.setTargetMethod("greet");
+ methodInvoker.setArguments(new Object[] {new VIP("Fonzie")});
+ methodInvoker.prepare();
+ String greeting = (String) methodInvoker.invoke();
+ assertEquals("regular: whassup dude?", greeting);
+ }
+
+
+ public static class TestClass1 {
+
+ public static int _staticField1;
+
+ public int _field1 = 0;
+
+ public int method1() {
+ return ++_field1;
+ }
+
+ public static int staticMethod1() {
+ return ++TestClass1._staticField1;
+ }
+
+ public static void voidRetvalMethod() {
+ }
+
+ public static void nullArgument(Object arg) {
+ }
+
+ public static void intArgument(int arg) {
+ }
+
+ public static void intArguments(int[] arg) {
+ }
+
+ public static String supertypes(Collection c, Integer i) {
+ return i.toString();
+ }
+
+ public static String supertypes(Collection c, List l, String s) {
+ return s;
+ }
+
+ public static String supertypes2(Collection c, List l, Integer i) {
+ return i.toString();
+ }
+
+ public static String supertypes2(Collection c, List l, String s, Integer i) {
+ return s;
+ }
+
+ public static String supertypes2(Collection c, List l, String s, String s2) {
+ return s;
+ }
+ }
+
+
+ public static class Greeter {
+
+ // should handle Salesman (only interface)
+ public String greet(Greetable greetable) {
+ return "greetable: " + greetable.getGreeting();
+ }
+
+ // should handle Shopper (beats Greetable since it is a class)
+ protected String greet(Purchaser purchaser) {
+ return "purchaser: " + purchaser.getGreeting();
+ }
+
+ // should handle Customer (exact match)
+ String greet(Customer customer) {
+ return "customer: " + customer.getGreeting();
+ }
+
+ // should handle Regular (exact) and VIP (closest match)
+ private String greet(Regular regular) {
+ return "regular: " + regular.getGreeting();
+ }
+ }
+
+
+ private static interface Greetable {
+
+ String getGreeting();
+ }
+
+
+ private static interface Person extends Greetable {
+ }
+
+
+ private static class Purchaser implements Greetable {
+
+ public String getGreeting() {
+ return "hello";
+ }
+ }
+
+
+ private static class Shopper extends Purchaser implements Person {
+
+ public String getGreeting() {
+ return "may I help you?";
+ }
+ }
+
+
+ private static class Salesman implements Person {
+
+ public String getGreeting() {
+ return "how are sales?";
+ }
+ }
+
+
+ private static class Customer extends Shopper {
+
+ public String getGreeting() {
+ return "good day";
+ }
+ }
+
+
+ private static class Regular extends Customer {
+
+ private String name;
+
+ public Regular(String name) {
+ this.name = name;
+ }
+
+ public String getGreeting() {
+ return "welcome back " + name ;
+ }
+ }
+
+
+ private static class VIP extends Regular {
+
+ public VIP(String name) {
+ super(name);
+ }
+
+ public String getGreeting() {
+ return "whassup dude?";
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/MockLog4jAppender.java b/org.springframework.testsuite/src/test/java/org/springframework/util/MockLog4jAppender.java
new file mode 100644
index 00000000000..18bc8b2d5b2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/MockLog4jAppender.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.AppenderSkeleton;
+import org.apache.log4j.spi.LoggingEvent;
+
+/**
+ * @author Alef Arendsen
+ */
+public class MockLog4jAppender extends AppenderSkeleton {
+
+ public static final List loggingStrings = new ArrayList();
+
+ public static boolean closeCalled = false;
+
+ /* (non-Javadoc)
+ * @see org.apache.log4j.AppenderSkeleton#append(org.apache.log4j.spi.LoggingEvent)
+ */
+ protected void append(LoggingEvent evt) {
+ //System.out.println("Adding " + evt.getMessage());
+ loggingStrings.add(evt.getMessage());
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.log4j.Appender#close()
+ */
+ public void close() {
+ closeCalled = true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.log4j.Appender#requiresLayout()
+ */
+ public boolean requiresLayout() {
+ return false;
+ }
+
+
+
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/NumberUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/util/NumberUtilsTests.java
new file mode 100644
index 00000000000..aae2b8a7d5b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/NumberUtilsTests.java
@@ -0,0 +1,348 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.util;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.text.NumberFormat;
+import java.util.Locale;
+
+import junit.framework.TestCase;
+
+import org.springframework.core.JdkVersion;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class NumberUtilsTests extends TestCase {
+
+ public void testParseNumber() {
+ String aByte = "" + Byte.MAX_VALUE;
+ String aShort = "" + Short.MAX_VALUE;
+ String anInteger = "" + Integer.MAX_VALUE;
+ String aLong = "" + Long.MAX_VALUE;
+ String aFloat = "" + Float.MAX_VALUE;
+ String aDouble = "" + Double.MAX_VALUE;
+
+ assertEquals("Byte did not parse", new Byte(Byte.MAX_VALUE), NumberUtils.parseNumber(aByte, Byte.class));
+ assertEquals("Short did not parse", new Short(Short.MAX_VALUE), NumberUtils.parseNumber(aShort, Short.class));
+ assertEquals("Integer did not parse", new Integer(Integer.MAX_VALUE), NumberUtils.parseNumber(anInteger, Integer.class));
+ assertEquals("Long did not parse", new Long(Long.MAX_VALUE), NumberUtils.parseNumber(aLong, Long.class));
+ assertEquals("Float did not parse", new Float(Float.MAX_VALUE), NumberUtils.parseNumber(aFloat, Float.class));
+ assertEquals("Double did not parse", new Double(Double.MAX_VALUE), NumberUtils.parseNumber(aDouble, Double.class));
+ }
+
+ public void testParseNumberUsingNumberFormat() {
+ NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
+ String aByte = "" + Byte.MAX_VALUE;
+ String aShort = "" + Short.MAX_VALUE;
+ String anInteger = "" + Integer.MAX_VALUE;
+ String aLong = "" + Long.MAX_VALUE;
+ String aFloat = "" + Float.MAX_VALUE;
+ String aDouble = "" + Double.MAX_VALUE;
+
+ assertEquals("Byte did not parse", new Byte(Byte.MAX_VALUE), NumberUtils.parseNumber(aByte, Byte.class, nf));
+ assertEquals("Short did not parse", new Short(Short.MAX_VALUE), NumberUtils.parseNumber(aShort, Short.class, nf));
+ assertEquals("Integer did not parse", new Integer(Integer.MAX_VALUE), NumberUtils.parseNumber(anInteger, Integer.class, nf));
+ assertEquals("Long did not parse", new Long(Long.MAX_VALUE), NumberUtils.parseNumber(aLong, Long.class, nf));
+ assertEquals("Float did not parse", new Float(Float.MAX_VALUE), NumberUtils.parseNumber(aFloat, Float.class, nf));
+ assertEquals("Double did not parse", new Double(Double.MAX_VALUE), NumberUtils.parseNumber(aDouble, Double.class, nf));
+ }
+
+ public void testParseWithTrim() {
+ String aByte = " " + Byte.MAX_VALUE + " ";
+ String aShort = " " + Short.MAX_VALUE + " ";
+ String anInteger = " " + Integer.MAX_VALUE + " ";
+ String aLong = " " + Long.MAX_VALUE + " ";
+ String aFloat = " " + Float.MAX_VALUE + " ";
+ String aDouble = " " + Double.MAX_VALUE + " ";
+
+ assertEquals("Byte did not parse", new Byte(Byte.MAX_VALUE), NumberUtils.parseNumber(aByte, Byte.class));
+ assertEquals("Short did not parse", new Short(Short.MAX_VALUE), NumberUtils.parseNumber(aShort, Short.class));
+ assertEquals("Integer did not parse", new Integer(Integer.MAX_VALUE), NumberUtils.parseNumber(anInteger, Integer.class));
+ assertEquals("Long did not parse", new Long(Long.MAX_VALUE), NumberUtils.parseNumber(aLong, Long.class));
+ assertEquals("Float did not parse", new Float(Float.MAX_VALUE), NumberUtils.parseNumber(aFloat, Float.class));
+ assertEquals("Double did not parse", new Double(Double.MAX_VALUE), NumberUtils.parseNumber(aDouble, Double.class));
+ }
+
+ public void testParseWithTrimUsingNumberFormat() {
+ NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
+ String aByte = " " + Byte.MAX_VALUE + " ";
+ String aShort = " " + Short.MAX_VALUE + " ";
+ String anInteger = " " + Integer.MAX_VALUE + " ";
+ String aLong = " " + Long.MAX_VALUE + " ";
+ String aFloat = " " + Float.MAX_VALUE + " ";
+ String aDouble = " " + Double.MAX_VALUE + " ";
+
+ assertEquals("Byte did not parse", new Byte(Byte.MAX_VALUE), NumberUtils.parseNumber(aByte, Byte.class, nf));
+ assertEquals("Short did not parse", new Short(Short.MAX_VALUE), NumberUtils.parseNumber(aShort, Short.class, nf));
+ assertEquals("Integer did not parse", new Integer(Integer.MAX_VALUE), NumberUtils.parseNumber(anInteger, Integer.class, nf));
+ assertEquals("Long did not parse", new Long(Long.MAX_VALUE), NumberUtils.parseNumber(aLong, Long.class, nf));
+ assertEquals("Float did not parse", new Float(Float.MAX_VALUE), NumberUtils.parseNumber(aFloat, Float.class, nf));
+ assertEquals("Double did not parse", new Double(Double.MAX_VALUE), NumberUtils.parseNumber(aDouble, Double.class, nf));
+ }
+
+ public void testParseAsHex() {
+ String aByte = "0x" + Integer.toHexString(new Byte(Byte.MAX_VALUE).intValue());
+ String aShort = "0x" + Integer.toHexString(new Short(Short.MAX_VALUE).intValue());
+ String anInteger = "0x" + Integer.toHexString(Integer.MAX_VALUE);
+ String aLong = "0x" + Long.toHexString(Long.MAX_VALUE);
+ String aReallyBigInt = "FEBD4E677898DFEBFFEE44";
+
+ assertByteEquals(aByte);
+ assertShortEquals(aShort);
+ assertIntegerEquals(anInteger);
+ assertLongEquals(aLong);
+ assertEquals("BigInteger did not parse",
+ new BigInteger(aReallyBigInt, 16), NumberUtils.parseNumber("0x" + aReallyBigInt, BigInteger.class));
+ }
+
+ public void testParseNegativeHex() {
+ String aByte = "-0x80";
+ String aShort = "-0x8000";
+ String anInteger = "-0x80000000";
+ String aLong = "-0x8000000000000000";
+ String aReallyBigInt = "FEBD4E677898DFEBFFEE44";
+
+ assertNegativeByteEquals(aByte);
+ assertNegativeShortEquals(aShort);
+ assertNegativeIntegerEquals(anInteger);
+ assertNegativeLongEquals(aLong);
+ assertEquals("BigInteger did not parse",
+ new BigInteger(aReallyBigInt, 16).negate(), NumberUtils.parseNumber("-0x" + aReallyBigInt, BigInteger.class));
+ }
+
+ public void testDoubleToBigInteger() {
+ Double decimal = new Double(3.14d);
+ assertEquals(new BigInteger("3"), NumberUtils.convertNumberToTargetClass(decimal, BigInteger.class));
+ }
+
+ public void testBigDecimalToBigInteger() {
+ String number = "987459837583750387355346";
+ BigDecimal decimal = new BigDecimal(number);
+ assertEquals(new BigInteger(number), NumberUtils.convertNumberToTargetClass(decimal, BigInteger.class));
+ }
+
+ public void testNonExactBigDecimalToBigInteger() {
+ BigDecimal decimal = new BigDecimal("987459837583750387355346.14");
+ assertEquals(new BigInteger("987459837583750387355346"), NumberUtils.convertNumberToTargetClass(decimal, BigInteger.class));
+ }
+
+ public void testParseBigDecimalNumber1() {
+ String bigDecimalAsString = "0.10";
+ Number bigDecimal = NumberUtils.parseNumber(bigDecimalAsString, BigDecimal.class);
+ assertEquals(new BigDecimal(bigDecimalAsString), bigDecimal);
+ }
+
+ public void testParseBigDecimalNumber2() {
+ String bigDecimalAsString = "0.001";
+ Number bigDecimal = NumberUtils.parseNumber(bigDecimalAsString, BigDecimal.class);
+ assertEquals(new BigDecimal(bigDecimalAsString), bigDecimal);
+ }
+
+ public void testParseBigDecimalNumber3() {
+ String bigDecimalAsString = "3.14159265358979323846";
+ Number bigDecimal = NumberUtils.parseNumber(bigDecimalAsString, BigDecimal.class);
+ assertEquals(new BigDecimal(bigDecimalAsString), bigDecimal);
+ }
+
+ public void testParseLocalizedBigDecimalNumber1() {
+ if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_15) {
+ return;
+ }
+ String bigDecimalAsString = "0.10";
+ NumberFormat numberFormat = NumberFormat.getInstance(Locale.ENGLISH);
+ Number bigDecimal = NumberUtils.parseNumber(bigDecimalAsString, BigDecimal.class, numberFormat);
+ assertEquals(new BigDecimal(bigDecimalAsString), bigDecimal);
+ }
+
+ public void testParseLocalizedBigDecimalNumber2() {
+ if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_15) {
+ return;
+ }
+ String bigDecimalAsString = "0.001";
+ NumberFormat numberFormat = NumberFormat.getInstance(Locale.ENGLISH);
+ Number bigDecimal = NumberUtils.parseNumber(bigDecimalAsString, BigDecimal.class, numberFormat);
+ assertEquals(new BigDecimal(bigDecimalAsString), bigDecimal);
+ }
+
+ public void testParseLocalizedBigDecimalNumber3() {
+ if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_15) {
+ return;
+ }
+ String bigDecimalAsString = "3.14159265358979323846";
+ NumberFormat numberFormat = NumberFormat.getInstance(Locale.ENGLISH);
+ Number bigDecimal = NumberUtils.parseNumber(bigDecimalAsString, BigDecimal.class, numberFormat);
+ assertEquals(new BigDecimal(bigDecimalAsString), bigDecimal);
+ }
+
+ public void testParseOverflow() {
+ String aLong = "" + Long.MAX_VALUE;
+ String aDouble = "" + Double.MAX_VALUE;
+
+ try {
+ NumberUtils.parseNumber(aLong, Byte.class);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ NumberUtils.parseNumber(aLong, Short.class);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ NumberUtils.parseNumber(aLong, Integer.class);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ assertEquals(new Long(Long.MAX_VALUE), NumberUtils.parseNumber(aLong, Long.class));
+
+ assertEquals(new Double(Double.MAX_VALUE), NumberUtils.parseNumber(aDouble, Double.class));
+ }
+
+ public void testParseNegativeOverflow() {
+ String aLong = "" + Long.MIN_VALUE;
+ String aDouble = "" + Double.MIN_VALUE;
+
+ try {
+ NumberUtils.parseNumber(aLong, Byte.class);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ NumberUtils.parseNumber(aLong, Short.class);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ NumberUtils.parseNumber(aLong, Integer.class);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ assertEquals(new Long(Long.MIN_VALUE), NumberUtils.parseNumber(aLong, Long.class));
+
+ assertEquals(new Double(Double.MIN_VALUE), NumberUtils.parseNumber(aDouble, Double.class));
+ }
+
+ public void testParseOverflowUsingNumberFormat() {
+ NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
+ String aLong = "" + Long.MAX_VALUE;
+ String aDouble = "" + Double.MAX_VALUE;
+
+ try {
+ NumberUtils.parseNumber(aLong, Byte.class, nf);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ NumberUtils.parseNumber(aLong, Short.class, nf);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ NumberUtils.parseNumber(aLong, Integer.class, nf);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ assertEquals(new Long(Long.MAX_VALUE), NumberUtils.parseNumber(aLong, Long.class, nf));
+
+ assertEquals(new Double(Double.MAX_VALUE), NumberUtils.parseNumber(aDouble, Double.class, nf));
+ }
+
+ public void testParseNegativeOverflowUsingNumberFormat() {
+ NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
+ String aLong = "" + Long.MIN_VALUE;
+ String aDouble = "" + Double.MIN_VALUE;
+
+ try {
+ NumberUtils.parseNumber(aLong, Byte.class, nf);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ NumberUtils.parseNumber(aLong, Short.class, nf);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ NumberUtils.parseNumber(aLong, Integer.class, nf);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+
+ assertEquals(new Long(Long.MIN_VALUE), NumberUtils.parseNumber(aLong, Long.class, nf));
+
+ assertEquals(new Double(Double.MIN_VALUE), NumberUtils.parseNumber(aDouble, Double.class, nf));
+ }
+
+ private void assertLongEquals(String aLong) {
+ assertEquals("Long did not parse", Long.MAX_VALUE, NumberUtils.parseNumber(aLong, Long.class).longValue());
+ }
+
+ private void assertIntegerEquals(String anInteger) {
+ assertEquals("Integer did not parse", Integer.MAX_VALUE, NumberUtils.parseNumber(anInteger, Integer.class).intValue());
+ }
+
+ private void assertShortEquals(String aShort) {
+ assertEquals("Short did not parse", Short.MAX_VALUE, NumberUtils.parseNumber(aShort, Short.class).shortValue());
+ }
+
+ private void assertByteEquals(String aByte) {
+ assertEquals("Byte did not parse", Byte.MAX_VALUE, NumberUtils.parseNumber(aByte, Byte.class).byteValue());
+ }
+
+ private void assertNegativeLongEquals(String aLong) {
+ assertEquals("Long did not parse", Long.MIN_VALUE, NumberUtils.parseNumber(aLong, Long.class).longValue());
+ }
+
+ private void assertNegativeIntegerEquals(String anInteger) {
+ assertEquals("Integer did not parse", Integer.MIN_VALUE, NumberUtils.parseNumber(anInteger, Integer.class).intValue());
+ }
+
+ private void assertNegativeShortEquals(String aShort) {
+ assertEquals("Short did not parse", Short.MIN_VALUE, NumberUtils.parseNumber(aShort, Short.class).shortValue());
+ }
+
+ private void assertNegativeByteEquals(String aByte) {
+ assertEquals("Byte did not parse", Byte.MIN_VALUE, NumberUtils.parseNumber(aByte, Byte.class).byteValue());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/ObjectUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/util/ObjectUtilsTests.java
new file mode 100644
index 00000000000..a963e17258b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/ObjectUtilsTests.java
@@ -0,0 +1,627 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.util;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.FatalBeanException;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ */
+public final class ObjectUtilsTests extends TestCase {
+
+ public void testIsCheckedException() {
+ assertTrue(ObjectUtils.isCheckedException(new Exception()));
+ assertTrue(ObjectUtils.isCheckedException(new ServletException()));
+
+ assertFalse(ObjectUtils.isCheckedException(new RuntimeException()));
+ assertFalse(ObjectUtils.isCheckedException(new FatalBeanException("")));
+
+ // Any Throwable other than RuntimeException and Error
+ // has to be considered checked according to the JLS.
+ assertTrue(ObjectUtils.isCheckedException(new Throwable()));
+ }
+
+ public void testIsCompatibleWithThrowsClause() {
+ Class[] empty = new Class[0];
+ Class[] exception = new Class[] {Exception.class};
+ Class[] servletAndIO = new Class[] {ServletException.class, IOException.class};
+ Class[] throwable = new Class[] {Throwable.class};
+
+ assertTrue(ObjectUtils.isCompatibleWithThrowsClause(new RuntimeException(), null));
+ assertTrue(ObjectUtils.isCompatibleWithThrowsClause(new RuntimeException(), empty));
+ assertTrue(ObjectUtils.isCompatibleWithThrowsClause(new RuntimeException(), exception));
+ assertTrue(ObjectUtils.isCompatibleWithThrowsClause(new RuntimeException(), servletAndIO));
+ assertTrue(ObjectUtils.isCompatibleWithThrowsClause(new RuntimeException(), throwable));
+
+ assertFalse(ObjectUtils.isCompatibleWithThrowsClause(new Exception(), null));
+ assertFalse(ObjectUtils.isCompatibleWithThrowsClause(new Exception(), empty));
+ assertTrue(ObjectUtils.isCompatibleWithThrowsClause(new Exception(), exception));
+ assertFalse(ObjectUtils.isCompatibleWithThrowsClause(new Exception(), servletAndIO));
+ assertTrue(ObjectUtils.isCompatibleWithThrowsClause(new Exception(), throwable));
+
+ assertFalse(ObjectUtils.isCompatibleWithThrowsClause(new ServletException(), null));
+ assertFalse(ObjectUtils.isCompatibleWithThrowsClause(new ServletException(), empty));
+ assertTrue(ObjectUtils.isCompatibleWithThrowsClause(new ServletException(), exception));
+ assertTrue(ObjectUtils.isCompatibleWithThrowsClause(new ServletException(), servletAndIO));
+ assertTrue(ObjectUtils.isCompatibleWithThrowsClause(new ServletException(), throwable));
+
+ assertFalse(ObjectUtils.isCompatibleWithThrowsClause(new Throwable(), null));
+ assertFalse(ObjectUtils.isCompatibleWithThrowsClause(new Throwable(), empty));
+ assertFalse(ObjectUtils.isCompatibleWithThrowsClause(new Throwable(), exception));
+ assertFalse(ObjectUtils.isCompatibleWithThrowsClause(new Throwable(), servletAndIO));
+ assertTrue(ObjectUtils.isCompatibleWithThrowsClause(new Throwable(), throwable));
+ }
+
+ public void testToObjectArray() {
+ int[] a = new int[] {1, 2, 3, 4, 5};
+ Integer[] wrapper = (Integer[]) ObjectUtils.toObjectArray(a);
+ assertTrue(wrapper.length == 5);
+ for (int i = 0; i < wrapper.length; i++) {
+ assertEquals(a[i], wrapper[i].intValue());
+ }
+ }
+
+ public void testToObjectArrayWithNull() {
+ Object[] objects = ObjectUtils.toObjectArray(null);
+ assertNotNull(objects);
+ assertEquals(0, objects.length);
+ }
+
+ public void testToObjectArrayWithEmptyPrimitiveArray() {
+ Object[] objects = ObjectUtils.toObjectArray(new byte[] {});
+ assertNotNull(objects);
+ assertEquals(0, objects.length);
+ }
+
+ public void testToObjectArrayWithNonArrayType() {
+ try {
+ ObjectUtils.toObjectArray("Not an []");
+ fail("Must have thrown an IllegalArgumentException by this point.");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testToObjectArrayWithNonPrimitiveArray() {
+ String[] source = new String[] {"Bingo"};
+ assertEquals(source, ObjectUtils.toObjectArray(source));
+ }
+
+ public void testAddObjectToArraySunnyDay() {
+ String[] array = new String[] {"foo", "bar"};
+ String newElement = "baz";
+ Object[] newArray = ObjectUtils.addObjectToArray(array, newElement);
+ assertEquals(3, newArray.length);
+ assertEquals(newElement, newArray[2]);
+ }
+
+ public void testAddObjectToArrayWhenEmpty() {
+ String[] array = new String[0];
+ String newElement = "foo";
+ Object[] newArray = ObjectUtils.addObjectToArray(array, newElement);
+ assertEquals(1, newArray.length);
+ assertEquals(newElement, newArray[0]);
+ }
+
+ public void testAddObjectToSingleNonNullElementArray() {
+ String existingElement = "foo";
+ String[] array = new String[] {existingElement};
+ String newElement = "bar";
+ Object[] newArray = ObjectUtils.addObjectToArray(array, newElement);
+ assertEquals(2, newArray.length);
+ assertEquals(existingElement, newArray[0]);
+ assertEquals(newElement, newArray[1]);
+ }
+
+ public void testAddObjectToSingleNullElementArray() {
+ String[] array = new String[] {null};
+ String newElement = "bar";
+ Object[] newArray = ObjectUtils.addObjectToArray(array, newElement);
+ assertEquals(2, newArray.length);
+ assertEquals(null, newArray[0]);
+ assertEquals(newElement, newArray[1]);
+ }
+
+ public void testAddObjectToNullArray() throws Exception {
+ String newElement = "foo";
+ Object[] newArray = ObjectUtils.addObjectToArray(null, newElement);
+ assertEquals(1, newArray.length);
+ assertEquals(newElement, newArray[0]);
+ }
+
+ public void testAddNullObjectToNullArray() throws Exception {
+ Object[] newArray = ObjectUtils.addObjectToArray(null, null);
+ assertEquals(1, newArray.length);
+ assertEquals(null, newArray[0]);
+ }
+
+ public void testNullSafeEqualsWithArrays() throws Exception {
+ assertTrue(ObjectUtils.nullSafeEquals(new String[] {"a", "b", "c"}, new String[] {"a", "b", "c"}));
+ assertTrue(ObjectUtils.nullSafeEquals(new int[] {1, 2, 3}, new int[] {1, 2, 3}));
+ }
+
+ public void testHashCodeWithBooleanFalse() {
+ int expected = Boolean.FALSE.hashCode();
+ assertEquals(expected, ObjectUtils.hashCode(false));
+ }
+
+ public void testHashCodeWithBooleanTrue() {
+ int expected = Boolean.TRUE.hashCode();
+ assertEquals(expected, ObjectUtils.hashCode(true));
+ }
+
+ public void testHashCodeWithDouble() {
+ double dbl = 9830.43;
+ int expected = (new Double(dbl)).hashCode();
+ assertEquals(expected, ObjectUtils.hashCode(dbl));
+ }
+
+ public void testHashCodeWithFloat() {
+ float flt = 34.8f;
+ int expected = (new Float(flt)).hashCode();
+ assertEquals(expected, ObjectUtils.hashCode(flt));
+ }
+
+ public void testHashCodeWithLong() {
+ long lng = 883l;
+ int expected = (new Long(lng)).hashCode();
+ assertEquals(expected, ObjectUtils.hashCode(lng));
+ }
+
+ public void testIdentityToString() {
+ Object obj = new Object();
+ String expected = obj.getClass().getName() + "@" + ObjectUtils.getIdentityHexString(obj);
+ String actual = ObjectUtils.identityToString(obj);
+ assertEquals(expected.toString(), actual);
+ }
+
+ public void testIdentityToStringWithNullObject() {
+ assertEquals("", ObjectUtils.identityToString(null));
+ }
+
+ public void testIsArrayOfPrimitivesWithBooleanArray() {
+ assertTrue(ClassUtils.isPrimitiveArray(boolean[].class));
+ }
+
+ public void testIsArrayOfPrimitivesWithObjectArray() {
+ assertFalse(ClassUtils.isPrimitiveArray(Object[].class));
+ }
+
+ public void testIsArrayOfPrimitivesWithNonArray() {
+ assertFalse(ClassUtils.isPrimitiveArray(String.class));
+ }
+
+ public void testIsPrimitiveOrWrapperWithBooleanPrimitiveClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(boolean.class));
+ }
+
+ public void testIsPrimitiveOrWrapperWithBooleanWrapperClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(Boolean.class));
+ }
+
+ public void testIsPrimitiveOrWrapperWithBytePrimitiveClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(byte.class));
+ }
+
+ public void testIsPrimitiveOrWrapperWithByteWrapperClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(Byte.class));
+ }
+
+ public void testIsPrimitiveOrWrapperWithCharacterClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(Character.class));
+ }
+
+ public void testIsPrimitiveOrWrapperWithCharClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(char.class));
+ }
+
+ public void testIsPrimitiveOrWrapperWithDoublePrimitiveClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(double.class));
+ }
+
+ public void testIsPrimitiveOrWrapperWithDoubleWrapperClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(Double.class));
+ }
+
+ public void testIsPrimitiveOrWrapperWithFloatPrimitiveClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(float.class));
+ }
+
+ public void testIsPrimitiveOrWrapperWithFloatWrapperClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(Float.class));
+ }
+
+ public void testIsPrimitiveOrWrapperWithIntClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(int.class));
+ }
+
+ public void testIsPrimitiveOrWrapperWithIntegerClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(Integer.class));
+ }
+
+ public void testIsPrimitiveOrWrapperWithLongPrimitiveClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(long.class));
+ }
+
+ public void testIsPrimitiveOrWrapperWithLongWrapperClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(Long.class));
+ }
+
+ public void testIsPrimitiveOrWrapperWithNonPrimitiveOrWrapperClass() {
+ assertFalse(ClassUtils.isPrimitiveOrWrapper(Object.class));
+ }
+
+ public void testIsPrimitiveOrWrapperWithShortPrimitiveClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(short.class));
+ }
+
+ public void testIsPrimitiveOrWrapperWithShortWrapperClass() {
+ assertTrue(ClassUtils.isPrimitiveOrWrapper(Short.class));
+ }
+
+ public void testNullSafeHashCodeWithBooleanArray() {
+ int expected = 31 * 7 + Boolean.TRUE.hashCode();
+ expected = 31 * expected + Boolean.FALSE.hashCode();
+
+ boolean[] array = {true, false};
+ int actual = ObjectUtils.nullSafeHashCode(array);
+
+ assertEquals(expected, actual);
+ }
+
+ public void testNullSafeHashCodeWithBooleanArrayEqualToNull() {
+ assertEquals(0, ObjectUtils.nullSafeHashCode((boolean[]) null));
+ }
+
+ public void testNullSafeHashCodeWithByteArray() {
+ int expected = 31 * 7 + 8;
+ expected = 31 * expected + 10;
+
+ byte[] array = {8, 10};
+ int actual = ObjectUtils.nullSafeHashCode(array);
+
+ assertEquals(expected, actual);
+ }
+
+ public void testNullSafeHashCodeWithByteArrayEqualToNull() {
+ assertEquals(0, ObjectUtils.nullSafeHashCode((byte[]) null));
+ }
+
+ public void testNullSafeHashCodeWithCharArray() {
+ int expected = 31 * 7 + 'a';
+ expected = 31 * expected + 'E';
+
+ char[] array = {'a', 'E'};
+ int actual = ObjectUtils.nullSafeHashCode(array);
+
+ assertEquals(expected, actual);
+ }
+
+ public void testNullSafeHashCodeWithCharArrayEqualToNull() {
+ assertEquals(0, ObjectUtils.nullSafeHashCode((char[]) null));
+ }
+
+ public void testNullSafeHashCodeWithDoubleArray() {
+ long bits = Double.doubleToLongBits(8449.65);
+ int expected = 31 * 7 + (int) (bits ^ (bits >>> 32));
+ bits = Double.doubleToLongBits(9944.923);
+ expected = 31 * expected + (int) (bits ^ (bits >>> 32));
+
+ double[] array = {8449.65, 9944.923};
+ int actual = ObjectUtils.nullSafeHashCode(array);
+
+ assertEquals(expected, actual);
+ }
+
+ public void testNullSafeHashCodeWithDoubleArrayEqualToNull() {
+ assertEquals(0, ObjectUtils.nullSafeHashCode((double[]) null));
+ }
+
+ public void testNullSafeHashCodeWithFloatArray() {
+ int expected = 31 * 7 + Float.floatToIntBits(9.6f);
+ expected = 31 * expected + Float.floatToIntBits(7.4f);
+
+ float[] array = {9.6f, 7.4f};
+ int actual = ObjectUtils.nullSafeHashCode(array);
+
+ assertEquals(expected, actual);
+ }
+
+ public void testNullSafeHashCodeWithFloatArrayEqualToNull() {
+ assertEquals(0, ObjectUtils.nullSafeHashCode((float[]) null));
+ }
+
+ public void testNullSafeHashCodeWithIntArray() {
+ int expected = 31 * 7 + 884;
+ expected = 31 * expected + 340;
+
+ int[] array = {884, 340};
+ int actual = ObjectUtils.nullSafeHashCode(array);
+
+ assertEquals(expected, actual);
+ }
+
+ public void testNullSafeHashCodeWithIntArrayEqualToNull() {
+ assertEquals(0, ObjectUtils.nullSafeHashCode((int[]) null));
+ }
+
+ public void testNullSafeHashCodeWithLongArray() {
+ long lng = 7993l;
+ int expected = 31 * 7 + (int) (lng ^ (lng >>> 32));
+ lng = 84320l;
+ expected = 31 * expected + (int) (lng ^ (lng >>> 32));
+
+ long[] array = {7993l, 84320l};
+ int actual = ObjectUtils.nullSafeHashCode(array);
+
+ assertEquals(expected, actual);
+ }
+
+ public void testNullSafeHashCodeWithLongArrayEqualToNull() {
+ assertEquals(0, ObjectUtils.nullSafeHashCode((long[]) null));
+ }
+
+ public void testNullSafeHashCodeWithObject() {
+ String str = "Luke";
+ assertEquals(str.hashCode(), ObjectUtils.nullSafeHashCode(str));
+ }
+
+ public void testNullSafeHashCodeWithObjectArray() {
+ int expected = 31 * 7 + "Leia".hashCode();
+ expected = 31 * expected + "Han".hashCode();
+
+ Object[] array = {"Leia", "Han"};
+ int actual = ObjectUtils.nullSafeHashCode(array);
+
+ assertEquals(expected, actual);
+ }
+
+ public void testNullSafeHashCodeWithObjectArrayEqualToNull() {
+ assertEquals(0, ObjectUtils.nullSafeHashCode((Object[]) null));
+ }
+
+ public void testNullSafeHashCodeWithObjectBeingBooleanArray() {
+ Object array = new boolean[] {true, false};
+ int expected = ObjectUtils.nullSafeHashCode((boolean[]) array);
+ assertEqualHashCodes(expected, array);
+ }
+
+ public void testNullSafeHashCodeWithObjectBeingByteArray() {
+ Object array = new byte[] {6, 39};
+ int expected = ObjectUtils.nullSafeHashCode((byte[]) array);
+ assertEqualHashCodes(expected, array);
+ }
+
+ public void testNullSafeHashCodeWithObjectBeingCharArray() {
+ Object array = new char[] {'l', 'M'};
+ int expected = ObjectUtils.nullSafeHashCode((char[]) array);
+ assertEqualHashCodes(expected, array);
+ }
+
+ public void testNullSafeHashCodeWithObjectBeingDoubleArray() {
+ Object array = new double[] {68930.993, 9022.009};
+ int expected = ObjectUtils.nullSafeHashCode((double[]) array);
+ assertEqualHashCodes(expected, array);
+ }
+
+ public void testNullSafeHashCodeWithObjectBeingFloatArray() {
+ Object array = new float[] {9.9f, 9.54f};
+ int expected = ObjectUtils.nullSafeHashCode((float[]) array);
+ assertEqualHashCodes(expected, array);
+ }
+
+ public void testNullSafeHashCodeWithObjectBeingIntArray() {
+ Object array = new int[] {89, 32};
+ int expected = ObjectUtils.nullSafeHashCode((int[]) array);
+ assertEqualHashCodes(expected, array);
+ }
+
+ public void testNullSafeHashCodeWithObjectBeingLongArray() {
+ Object array = new long[] {4389, 320};
+ int expected = ObjectUtils.nullSafeHashCode((long[]) array);
+ assertEqualHashCodes(expected, array);
+ }
+
+ public void testNullSafeHashCodeWithObjectBeingObjectArray() {
+ Object array = new Object[] {"Luke", "Anakin"};
+ int expected = ObjectUtils.nullSafeHashCode((Object[]) array);
+ assertEqualHashCodes(expected, array);
+ }
+
+ public void testNullSafeHashCodeWithObjectBeingShortArray() {
+ Object array = new short[] {5, 3};
+ int expected = ObjectUtils.nullSafeHashCode((short[]) array);
+ assertEqualHashCodes(expected, array);
+ }
+
+ public void testNullSafeHashCodeWithObjectEqualToNull() {
+ assertEquals(0, ObjectUtils.nullSafeHashCode((Object) null));
+ }
+
+ public void testNullSafeHashCodeWithShortArray() {
+ int expected = 31 * 7 + 70;
+ expected = 31 * expected + 8;
+
+ short[] array = {70, 8};
+ int actual = ObjectUtils.nullSafeHashCode(array);
+
+ assertEquals(expected, actual);
+ }
+
+ public void testNullSafeHashCodeWithShortArrayEqualToNull() {
+ assertEquals(0, ObjectUtils.nullSafeHashCode((short[]) null));
+ }
+
+ public void testNullSafeToStringWithBooleanArray() {
+ boolean[] array = {true, false};
+ assertEquals("{true, false}", ObjectUtils.nullSafeToString(array));
+ }
+
+ public void testNullSafeToStringWithBooleanArrayBeingEmpty() {
+ boolean[] array = {};
+ assertEquals("{}", ObjectUtils.nullSafeToString(array));
+ }
+
+ public void testNullSafeToStringWithBooleanArrayEqualToNull() {
+ assertEquals("null", ObjectUtils.nullSafeToString((boolean[]) null));
+ }
+
+ public void testNullSafeToStringWithByteArray() {
+ byte[] array = {5, 8};
+ assertEquals("{5, 8}", ObjectUtils.nullSafeToString(array));
+ }
+
+ public void testNullSafeToStringWithByteArrayBeingEmpty() {
+ byte[] array = {};
+ assertEquals("{}", ObjectUtils.nullSafeToString(array));
+ }
+
+ public void testNullSafeToStringWithByteArrayEqualToNull() {
+ assertEquals("null", ObjectUtils.nullSafeToString((byte[]) null));
+ }
+
+ public void testNullSafeToStringWithCharArray() {
+ char[] array = {'A', 'B'};
+ assertEquals("{'A', 'B'}", ObjectUtils.nullSafeToString(array));
+ }
+
+ public void testNullSafeToStringWithCharArrayBeingEmpty() {
+ char[] array = {};
+ assertEquals("{}", ObjectUtils.nullSafeToString(array));
+ }
+
+ public void testNullSafeToStringWithCharArrayEqualToNull() {
+ assertEquals("null", ObjectUtils.nullSafeToString((char[]) null));
+ }
+
+ public void testNullSafeToStringWithDoubleArray() {
+ double[] array = {8594.93, 8594023.95};
+ assertEquals("{8594.93, 8594023.95}", ObjectUtils.nullSafeToString(array));
+ }
+
+ public void testNullSafeToStringWithDoubleArrayBeingEmpty() {
+ double[] array = {};
+ assertEquals("{}", ObjectUtils.nullSafeToString(array));
+ }
+
+ public void testNullSafeToStringWithDoubleArrayEqualToNull() {
+ assertEquals("null", ObjectUtils.nullSafeToString((double[]) null));
+ }
+
+ public void testNullSafeToStringWithFloatArray() {
+ float[] array = {8.6f, 43.8f};
+ assertEquals("{8.6, 43.8}", ObjectUtils.nullSafeToString(array));
+ }
+
+ public void testNullSafeToStringWithFloatArrayBeingEmpty() {
+ float[] array = {};
+ assertEquals("{}", ObjectUtils.nullSafeToString(array));
+ }
+
+ public void testNullSafeToStringWithFloatArrayEqualToNull() {
+ assertEquals("null", ObjectUtils.nullSafeToString((float[]) null));
+ }
+
+ public void testNullSafeToStringWithIntArray() {
+ int[] array = {9, 64};
+ assertEquals("{9, 64}", ObjectUtils.nullSafeToString(array));
+ }
+
+ public void testNullSafeToStringWithIntArrayBeingEmpty() {
+ int[] array = {};
+ assertEquals("{}", ObjectUtils.nullSafeToString(array));
+ }
+
+ public void testNullSafeToStringWithIntArrayEqualToNull() {
+ assertEquals("null", ObjectUtils.nullSafeToString((int[]) null));
+ }
+
+ public void testNullSafeToStringWithLongArray() {
+ long[] array = {434l, 23423l};
+ assertEquals("{434, 23423}", ObjectUtils.nullSafeToString(array));
+ }
+
+ public void testNullSafeToStringWithLongArrayBeingEmpty() {
+ long[] array = {};
+ assertEquals("{}", ObjectUtils.nullSafeToString(array));
+ }
+
+ public void testNullSafeToStringWithLongArrayEqualToNull() {
+ assertEquals("null", ObjectUtils.nullSafeToString((long[]) null));
+ }
+
+ public void testNullSafeToStringWithPlainOldString() {
+ assertEquals("I shoh love tha taste of mangoes", ObjectUtils.nullSafeToString("I shoh love tha taste of mangoes"));
+ }
+
+ public void testNullSafeToStringWithObjectArray() {
+ Object[] array = {"Han", new Long(43)};
+ assertEquals("{Han, 43}", ObjectUtils.nullSafeToString(array));
+ }
+
+ public void testNullSafeToStringWithObjectArrayBeingEmpty() {
+ Object[] array = {};
+ assertEquals("{}", ObjectUtils.nullSafeToString(array));
+ }
+
+ public void testNullSafeToStringWithObjectArrayEqualToNull() {
+ assertEquals("null", ObjectUtils.nullSafeToString((Object[]) null));
+ }
+
+ public void testNullSafeToStringWithShortArray() {
+ short[] array = {7, 9};
+ assertEquals("{7, 9}", ObjectUtils.nullSafeToString(array));
+ }
+
+ public void testNullSafeToStringWithShortArrayBeingEmpty() {
+ short[] array = {};
+ assertEquals("{}", ObjectUtils.nullSafeToString(array));
+ }
+
+ public void testNullSafeToStringWithShortArrayEqualToNull() {
+ assertEquals("null", ObjectUtils.nullSafeToString((short[]) null));
+ }
+
+ public void testNullSafeToStringWithStringArray() {
+ String[] array = {"Luke", "Anakin"};
+ assertEquals("{Luke, Anakin}", ObjectUtils.nullSafeToString(array));
+ }
+
+ public void testNullSafeToStringWithStringArrayBeingEmpty() {
+ String[] array = {};
+ assertEquals("{}", ObjectUtils.nullSafeToString(array));
+ }
+
+ public void testNullSafeToStringWithStringArrayEqualToNull() {
+ assertEquals("null", ObjectUtils.nullSafeToString((String[]) null));
+ }
+
+ private void assertEqualHashCodes(int expected, Object array) {
+ int actual = ObjectUtils.nullSafeHashCode(array);
+ assertEquals(expected, actual);
+ assertTrue(array.hashCode() != actual);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/PathMatcherTests.java b/org.springframework.testsuite/src/test/java/org/springframework/util/PathMatcherTests.java
new file mode 100644
index 00000000000..8ac4e00801c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/PathMatcherTests.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.util;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Alef Arendsen
+ * @author Seth Ladd
+ * @author Juergen Hoeller
+ */
+public class PathMatcherTests extends TestCase {
+
+ public void testAntPathMatcher() {
+ PathMatcher pathMatcher = new AntPathMatcher();
+
+ // test exact matching
+ assertTrue(pathMatcher.match("test", "test"));
+ assertTrue(pathMatcher.match("/test", "/test"));
+ assertFalse(pathMatcher.match("/test.jpg", "test.jpg"));
+ assertFalse(pathMatcher.match("test", "/test"));
+ assertFalse(pathMatcher.match("/test", "test"));
+
+ // test matching with ?'s
+ assertTrue(pathMatcher.match("t?st", "test"));
+ assertTrue(pathMatcher.match("??st", "test"));
+ assertTrue(pathMatcher.match("tes?", "test"));
+ assertTrue(pathMatcher.match("te??", "test"));
+ assertTrue(pathMatcher.match("?es?", "test"));
+ assertFalse(pathMatcher.match("tes?", "tes"));
+ assertFalse(pathMatcher.match("tes?", "testt"));
+ assertFalse(pathMatcher.match("tes?", "tsst"));
+
+ // test matchin with *'s
+ assertTrue(pathMatcher.match("*", "test"));
+ assertTrue(pathMatcher.match("test*", "test"));
+ assertTrue(pathMatcher.match("test*", "testTest"));
+ assertTrue(pathMatcher.match("test/*", "test/Test"));
+ assertTrue(pathMatcher.match("test/*", "test/t"));
+ assertTrue(pathMatcher.match("test/*", "test/"));
+ assertTrue(pathMatcher.match("*test*", "AnothertestTest"));
+ assertTrue(pathMatcher.match("*test", "Anothertest"));
+ assertTrue(pathMatcher.match("*.*", "test."));
+ assertTrue(pathMatcher.match("*.*", "test.test"));
+ assertTrue(pathMatcher.match("*.*", "test.test.test"));
+ assertTrue(pathMatcher.match("test*aaa", "testblaaaa"));
+ assertFalse(pathMatcher.match("test*", "tst"));
+ assertFalse(pathMatcher.match("test*", "tsttest"));
+ assertFalse(pathMatcher.match("test*", "test/"));
+ assertFalse(pathMatcher.match("test*", "test/t"));
+ assertFalse(pathMatcher.match("test/*", "test"));
+ assertFalse(pathMatcher.match("*test*", "tsttst"));
+ assertFalse(pathMatcher.match("*test", "tsttst"));
+ assertFalse(pathMatcher.match("*.*", "tsttst"));
+ assertFalse(pathMatcher.match("test*aaa", "test"));
+ assertFalse(pathMatcher.match("test*aaa", "testblaaab"));
+
+ // test matching with ?'s and /'s
+ assertTrue(pathMatcher.match("/?", "/a"));
+ assertTrue(pathMatcher.match("/?/a", "/a/a"));
+ assertTrue(pathMatcher.match("/a/?", "/a/b"));
+ assertTrue(pathMatcher.match("/??/a", "/aa/a"));
+ assertTrue(pathMatcher.match("/a/??", "/a/bb"));
+ assertTrue(pathMatcher.match("/?", "/a"));
+
+ // test matching with **'s
+ assertTrue(pathMatcher.match("/**", "/testing/testing"));
+ assertTrue(pathMatcher.match("/*/**", "/testing/testing"));
+ assertTrue(pathMatcher.match("/**/*", "/testing/testing"));
+ assertTrue(pathMatcher.match("/bla/**/bla", "/bla/testing/testing/bla"));
+ assertTrue(pathMatcher.match("/bla/**/bla", "/bla/testing/testing/bla/bla"));
+ assertTrue(pathMatcher.match("/**/test", "/bla/bla/test"));
+ assertTrue(pathMatcher.match("/bla/**/**/bla", "/bla/bla/bla/bla/bla/bla"));
+ assertTrue(pathMatcher.match("/bla*bla/test", "/blaXXXbla/test"));
+ assertTrue(pathMatcher.match("/*bla/test", "/XXXbla/test"));
+ assertFalse(pathMatcher.match("/bla*bla/test", "/blaXXXbl/test"));
+ assertFalse(pathMatcher.match("/*bla/test", "XXXblab/test"));
+ assertFalse(pathMatcher.match("/*bla/test", "XXXbl/test"));
+
+ assertFalse(pathMatcher.match("/????", "/bala/bla"));
+ assertFalse(pathMatcher.match("/**/*bla", "/bla/bla/bla/bbb"));
+
+ assertTrue(pathMatcher.match("/*bla*/**/bla/**", "/XXXblaXXXX/testing/testing/bla/testing/testing/"));
+ assertTrue(pathMatcher.match("/*bla*/**/bla/*", "/XXXblaXXXX/testing/testing/bla/testing"));
+ assertTrue(pathMatcher.match("/*bla*/**/bla/**", "/XXXblaXXXX/testing/testing/bla/testing/testing"));
+ assertTrue(pathMatcher.match("/*bla*/**/bla/**", "/XXXblaXXXX/testing/testing/bla/testing/testing.jpg"));
+
+ assertTrue(pathMatcher.match("*bla*/**/bla/**", "XXXblaXXXX/testing/testing/bla/testing/testing/"));
+ assertTrue(pathMatcher.match("*bla*/**/bla/*", "XXXblaXXXX/testing/testing/bla/testing"));
+ assertTrue(pathMatcher.match("*bla*/**/bla/**", "XXXblaXXXX/testing/testing/bla/testing/testing"));
+ assertFalse(pathMatcher.match("*bla*/**/bla/*", "XXXblaXXXX/testing/testing/bla/testing/testing"));
+
+ assertFalse(pathMatcher.match("/x/x/**/bla", "/x/x/x/"));
+
+ assertTrue(pathMatcher.match("", ""));
+ }
+
+ public void testAntPathMatcherWithMatchStart() {
+ PathMatcher pathMatcher = new AntPathMatcher();
+
+ // test exact matching
+ assertTrue(pathMatcher.matchStart("test", "test"));
+ assertTrue(pathMatcher.matchStart("/test", "/test"));
+ assertFalse(pathMatcher.matchStart("/test.jpg", "test.jpg"));
+ assertFalse(pathMatcher.matchStart("test", "/test"));
+ assertFalse(pathMatcher.matchStart("/test", "test"));
+
+ // test matching with ?'s
+ assertTrue(pathMatcher.matchStart("t?st", "test"));
+ assertTrue(pathMatcher.matchStart("??st", "test"));
+ assertTrue(pathMatcher.matchStart("tes?", "test"));
+ assertTrue(pathMatcher.matchStart("te??", "test"));
+ assertTrue(pathMatcher.matchStart("?es?", "test"));
+ assertFalse(pathMatcher.matchStart("tes?", "tes"));
+ assertFalse(pathMatcher.matchStart("tes?", "testt"));
+ assertFalse(pathMatcher.matchStart("tes?", "tsst"));
+
+ // test matchin with *'s
+ assertTrue(pathMatcher.matchStart("*", "test"));
+ assertTrue(pathMatcher.matchStart("test*", "test"));
+ assertTrue(pathMatcher.matchStart("test*", "testTest"));
+ assertTrue(pathMatcher.matchStart("test/*", "test/Test"));
+ assertTrue(pathMatcher.matchStart("test/*", "test/t"));
+ assertTrue(pathMatcher.matchStart("test/*", "test/"));
+ assertTrue(pathMatcher.matchStart("*test*", "AnothertestTest"));
+ assertTrue(pathMatcher.matchStart("*test", "Anothertest"));
+ assertTrue(pathMatcher.matchStart("*.*", "test."));
+ assertTrue(pathMatcher.matchStart("*.*", "test.test"));
+ assertTrue(pathMatcher.matchStart("*.*", "test.test.test"));
+ assertTrue(pathMatcher.matchStart("test*aaa", "testblaaaa"));
+ assertFalse(pathMatcher.matchStart("test*", "tst"));
+ assertFalse(pathMatcher.matchStart("test*", "test/"));
+ assertFalse(pathMatcher.matchStart("test*", "tsttest"));
+ assertFalse(pathMatcher.matchStart("test*", "test/"));
+ assertFalse(pathMatcher.matchStart("test*", "test/t"));
+ assertTrue(pathMatcher.matchStart("test/*", "test"));
+ assertTrue(pathMatcher.matchStart("test/t*.txt", "test"));
+ assertFalse(pathMatcher.matchStart("*test*", "tsttst"));
+ assertFalse(pathMatcher.matchStart("*test", "tsttst"));
+ assertFalse(pathMatcher.matchStart("*.*", "tsttst"));
+ assertFalse(pathMatcher.matchStart("test*aaa", "test"));
+ assertFalse(pathMatcher.matchStart("test*aaa", "testblaaab"));
+
+ // test matching with ?'s and /'s
+ assertTrue(pathMatcher.matchStart("/?", "/a"));
+ assertTrue(pathMatcher.matchStart("/?/a", "/a/a"));
+ assertTrue(pathMatcher.matchStart("/a/?", "/a/b"));
+ assertTrue(pathMatcher.matchStart("/??/a", "/aa/a"));
+ assertTrue(pathMatcher.matchStart("/a/??", "/a/bb"));
+ assertTrue(pathMatcher.matchStart("/?", "/a"));
+
+ // test matching with **'s
+ assertTrue(pathMatcher.matchStart("/**", "/testing/testing"));
+ assertTrue(pathMatcher.matchStart("/*/**", "/testing/testing"));
+ assertTrue(pathMatcher.matchStart("/**/*", "/testing/testing"));
+ assertTrue(pathMatcher.matchStart("test*/**", "test/"));
+ assertTrue(pathMatcher.matchStart("test*/**", "test/t"));
+ assertTrue(pathMatcher.matchStart("/bla/**/bla", "/bla/testing/testing/bla"));
+ assertTrue(pathMatcher.matchStart("/bla/**/bla", "/bla/testing/testing/bla/bla"));
+ assertTrue(pathMatcher.matchStart("/**/test", "/bla/bla/test"));
+ assertTrue(pathMatcher.matchStart("/bla/**/**/bla", "/bla/bla/bla/bla/bla/bla"));
+ assertTrue(pathMatcher.matchStart("/bla*bla/test", "/blaXXXbla/test"));
+ assertTrue(pathMatcher.matchStart("/*bla/test", "/XXXbla/test"));
+ assertFalse(pathMatcher.matchStart("/bla*bla/test", "/blaXXXbl/test"));
+ assertFalse(pathMatcher.matchStart("/*bla/test", "XXXblab/test"));
+ assertFalse(pathMatcher.matchStart("/*bla/test", "XXXbl/test"));
+
+ assertFalse(pathMatcher.matchStart("/????", "/bala/bla"));
+ assertTrue(pathMatcher.matchStart("/**/*bla", "/bla/bla/bla/bbb"));
+
+ assertTrue(pathMatcher.matchStart("/*bla*/**/bla/**", "/XXXblaXXXX/testing/testing/bla/testing/testing/"));
+ assertTrue(pathMatcher.matchStart("/*bla*/**/bla/*", "/XXXblaXXXX/testing/testing/bla/testing"));
+ assertTrue(pathMatcher.matchStart("/*bla*/**/bla/**", "/XXXblaXXXX/testing/testing/bla/testing/testing"));
+ assertTrue(pathMatcher.matchStart("/*bla*/**/bla/**", "/XXXblaXXXX/testing/testing/bla/testing/testing.jpg"));
+
+ assertTrue(pathMatcher.matchStart("*bla*/**/bla/**", "XXXblaXXXX/testing/testing/bla/testing/testing/"));
+ assertTrue(pathMatcher.matchStart("*bla*/**/bla/*", "XXXblaXXXX/testing/testing/bla/testing"));
+ assertTrue(pathMatcher.matchStart("*bla*/**/bla/**", "XXXblaXXXX/testing/testing/bla/testing/testing"));
+ assertTrue(pathMatcher.matchStart("*bla*/**/bla/*", "XXXblaXXXX/testing/testing/bla/testing/testing"));
+
+ assertTrue(pathMatcher.matchStart("/x/x/**/bla", "/x/x/x/"));
+
+ assertTrue(pathMatcher.matchStart("", ""));
+ }
+
+ public void testAntPathMatcherWithUniqueDeliminator() {
+ AntPathMatcher pathMatcher = new AntPathMatcher();
+ pathMatcher.setPathSeparator(".");
+
+ // test exact matching
+ assertTrue(pathMatcher.match("test", "test"));
+ assertTrue(pathMatcher.match(".test", ".test"));
+ assertFalse(pathMatcher.match(".test/jpg", "test/jpg"));
+ assertFalse(pathMatcher.match("test", ".test"));
+ assertFalse(pathMatcher.match(".test", "test"));
+
+ // test matching with ?'s
+ assertTrue(pathMatcher.match("t?st", "test"));
+ assertTrue(pathMatcher.match("??st", "test"));
+ assertTrue(pathMatcher.match("tes?", "test"));
+ assertTrue(pathMatcher.match("te??", "test"));
+ assertTrue(pathMatcher.match("?es?", "test"));
+ assertFalse(pathMatcher.match("tes?", "tes"));
+ assertFalse(pathMatcher.match("tes?", "testt"));
+ assertFalse(pathMatcher.match("tes?", "tsst"));
+
+ // test matchin with *'s
+ assertTrue(pathMatcher.match("*", "test"));
+ assertTrue(pathMatcher.match("test*", "test"));
+ assertTrue(pathMatcher.match("test*", "testTest"));
+ assertTrue(pathMatcher.match("*test*", "AnothertestTest"));
+ assertTrue(pathMatcher.match("*test", "Anothertest"));
+ assertTrue(pathMatcher.match("*/*", "test/"));
+ assertTrue(pathMatcher.match("*/*", "test/test"));
+ assertTrue(pathMatcher.match("*/*", "test/test/test"));
+ assertTrue(pathMatcher.match("test*aaa", "testblaaaa"));
+ assertFalse(pathMatcher.match("test*", "tst"));
+ assertFalse(pathMatcher.match("test*", "tsttest"));
+ assertFalse(pathMatcher.match("*test*", "tsttst"));
+ assertFalse(pathMatcher.match("*test", "tsttst"));
+ assertFalse(pathMatcher.match("*/*", "tsttst"));
+ assertFalse(pathMatcher.match("test*aaa", "test"));
+ assertFalse(pathMatcher.match("test*aaa", "testblaaab"));
+
+ // test matching with ?'s and .'s
+ assertTrue(pathMatcher.match(".?", ".a"));
+ assertTrue(pathMatcher.match(".?.a", ".a.a"));
+ assertTrue(pathMatcher.match(".a.?", ".a.b"));
+ assertTrue(pathMatcher.match(".??.a", ".aa.a"));
+ assertTrue(pathMatcher.match(".a.??", ".a.bb"));
+ assertTrue(pathMatcher.match(".?", ".a"));
+
+ // test matching with **'s
+ assertTrue(pathMatcher.match(".**", ".testing.testing"));
+ assertTrue(pathMatcher.match(".*.**", ".testing.testing"));
+ assertTrue(pathMatcher.match(".**.*", ".testing.testing"));
+ assertTrue(pathMatcher.match(".bla.**.bla", ".bla.testing.testing.bla"));
+ assertTrue(pathMatcher.match(".bla.**.bla", ".bla.testing.testing.bla.bla"));
+ assertTrue(pathMatcher.match(".**.test", ".bla.bla.test"));
+ assertTrue(pathMatcher.match(".bla.**.**.bla", ".bla.bla.bla.bla.bla.bla"));
+ assertTrue(pathMatcher.match(".bla*bla.test", ".blaXXXbla.test"));
+ assertTrue(pathMatcher.match(".*bla.test", ".XXXbla.test"));
+ assertFalse(pathMatcher.match(".bla*bla.test", ".blaXXXbl.test"));
+ assertFalse(pathMatcher.match(".*bla.test", "XXXblab.test"));
+ assertFalse(pathMatcher.match(".*bla.test", "XXXbl.test"));
+ }
+
+ public void testAntPathMatcherExtractPathWithinPattern() throws Exception {
+ PathMatcher pathMatcher = new AntPathMatcher();
+
+ assertEquals("", pathMatcher.extractPathWithinPattern("/docs/commit.html", "/docs/commit.html"));
+
+ assertEquals("cvs/commit", pathMatcher.extractPathWithinPattern("/docs/*", "/docs/cvs/commit"));
+ assertEquals("commit.html", pathMatcher.extractPathWithinPattern("/docs/cvs/*.html", "/docs/cvs/commit.html"));
+ assertEquals("cvs/commit", pathMatcher.extractPathWithinPattern("/docs/**", "/docs/cvs/commit"));
+ assertEquals("cvs/commit.html", pathMatcher.extractPathWithinPattern("/docs/**/*.html", "/docs/cvs/commit.html"));
+ assertEquals("commit.html", pathMatcher.extractPathWithinPattern("/docs/**/*.html", "/docs/commit.html"));
+ assertEquals("commit.html", pathMatcher.extractPathWithinPattern("/*.html", "/commit.html"));
+ assertEquals("docs/commit.html", pathMatcher.extractPathWithinPattern("/*.html", "/docs/commit.html"));
+ assertEquals("/commit.html", pathMatcher.extractPathWithinPattern("*.html", "/commit.html"));
+ assertEquals("/docs/commit.html", pathMatcher.extractPathWithinPattern("*.html", "/docs/commit.html"));
+ assertEquals("/docs/commit.html", pathMatcher.extractPathWithinPattern("**/*.*", "/docs/commit.html"));
+ assertEquals("/docs/commit.html", pathMatcher.extractPathWithinPattern("*", "/docs/commit.html"));
+
+ assertEquals("docs/cvs/commit", pathMatcher.extractPathWithinPattern("/d?cs/*", "/docs/cvs/commit"));
+ assertEquals("cvs/commit.html", pathMatcher.extractPathWithinPattern("/docs/c?s/*.html", "/docs/cvs/commit.html"));
+ assertEquals("docs/cvs/commit", pathMatcher.extractPathWithinPattern("/d?cs/**", "/docs/cvs/commit"));
+ assertEquals("docs/cvs/commit.html", pathMatcher.extractPathWithinPattern("/d?cs/**/*.html", "/docs/cvs/commit.html"));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/PatternMatchUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/util/PatternMatchUtilsTests.java
new file mode 100644
index 00000000000..8128cee620a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/PatternMatchUtilsTests.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.util;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Juergen Hoeller
+ * @author Johan Gorter
+ */
+public class PatternMatchUtilsTests extends TestCase {
+
+ public void testTrivial() {
+ assertEquals(false, PatternMatchUtils.simpleMatch((String) null, ""));
+ assertEquals(false, PatternMatchUtils.simpleMatch("1", null));
+ doTest("*", "123", true);
+ doTest("123", "123", true);
+ }
+
+ public void testStartsWith() {
+ doTest("get*", "getMe", true);
+ doTest("get*", "setMe", false);
+ }
+
+ public void testEndsWith() {
+ doTest("*Test", "getMeTest", true);
+ doTest("*Test", "setMe", false);
+ }
+
+ public void testBetween() {
+ doTest("*stuff*", "getMeTest", false);
+ doTest("*stuff*", "getstuffTest", true);
+ doTest("*stuff*", "stuffTest", true);
+ doTest("*stuff*", "getstuff", true);
+ doTest("*stuff*", "stuff", true);
+ }
+
+ public void testStartsEnds() {
+ doTest("on*Event", "onMyEvent", true);
+ doTest("on*Event", "onEvent", true);
+ doTest("3*3", "3", false);
+ doTest("3*3", "33", true);
+ }
+
+ public void testStartsEndsBetween() {
+ doTest("12*45*78", "12345678", true);
+ doTest("12*45*78", "123456789", false);
+ doTest("12*45*78", "012345678", false);
+ doTest("12*45*78", "124578", true);
+ doTest("12*45*78", "1245457878", true);
+ doTest("3*3*3", "33", false);
+ doTest("3*3*3", "333", true);
+ }
+
+ public void testRidiculous() {
+ doTest("*1*2*3*", "0011002001010030020201030", true);
+ doTest("1*2*3*4", "10300204", false);
+ doTest("1*2*3*3", "10300203", false);
+ doTest("*1*2*3*", "123", true);
+ doTest("*1*2*3*", "132", false);
+ }
+
+ private void doTest(String pattern, String str, boolean shouldMatch) {
+ assertEquals(shouldMatch, PatternMatchUtils.simpleMatch(pattern, str));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/PropertiesPersisterTests.java b/org.springframework.testsuite/src/test/java/org/springframework/util/PropertiesPersisterTests.java
new file mode 100644
index 00000000000..0fcc4238ae5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/PropertiesPersisterTests.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Juergen Hoeller
+ * @since 11.01.2005
+ */
+public class PropertiesPersisterTests extends TestCase {
+
+ public void testPropertiesPersister() throws IOException {
+ String propString = "code1=message1\ncode2:message2";
+ Properties props = loadProperties(propString, false);
+ String propCopy = storeProperties(props, null, false);
+ loadProperties(propCopy, false);
+ }
+
+ public void testPropertiesPersisterWithWhitespace() throws IOException {
+ String propString = " code1\t= \tmessage1\n code2 \t :\t mess\\\n \t age2";
+ Properties props = loadProperties(propString, false);
+ String propCopy = storeProperties(props, null, false);
+ loadProperties(propCopy, false);
+ }
+
+ public void testPropertiesPersisterWithHeader() throws IOException {
+ String propString = "code1=message1\ncode2:message2";
+ Properties props = loadProperties(propString, false);
+ String propCopy = storeProperties(props, "myHeader", false);
+ loadProperties(propCopy, false);
+ }
+
+ public void testPropertiesPersisterWithEmptyValue() throws IOException {
+ String propString = "code1=message1\ncode2:message2\ncode3=";
+ Properties props = loadProperties(propString, false);
+ String propCopy = storeProperties(props, null, false);
+ loadProperties(propCopy, false);
+ }
+
+ public void testPropertiesPersisterWithReader() throws IOException {
+ String propString = "code1=message1\ncode2:message2";
+ Properties props = loadProperties(propString, true);
+ String propCopy = storeProperties(props, null, true);
+ loadProperties(propCopy, false);
+ }
+
+ public void testPropertiesPersisterWithReaderAndWhitespace() throws IOException {
+ String propString = " code1\t= \tmessage1\n code2 \t :\t mess\\\n \t age2";
+ Properties props = loadProperties(propString, true);
+ String propCopy = storeProperties(props, null, true);
+ loadProperties(propCopy, false);
+ }
+
+ public void testPropertiesPersisterWithReaderAndHeader() throws IOException {
+ String propString = "code1\t=\tmessage1\n code2 \t : \t message2";
+ Properties props = loadProperties(propString, true);
+ String propCopy = storeProperties(props, "myHeader", true);
+ loadProperties(propCopy, false);
+ }
+
+ public void testPropertiesPersisterWithReaderAndEmptyValue() throws IOException {
+ String propString = "code1=message1\ncode2:message2\ncode3=";
+ Properties props = loadProperties(propString, true);
+ String propCopy = storeProperties(props, null, true);
+ loadProperties(propCopy, false);
+ }
+
+ private Properties loadProperties(String propString, boolean useReader) throws IOException {
+ DefaultPropertiesPersister persister = new DefaultPropertiesPersister();
+ Properties props = new Properties();
+ if (useReader) {
+ persister.load(props, new StringReader(propString));
+ }
+ else {
+ persister.load(props, new ByteArrayInputStream(propString.getBytes()));
+ }
+ assertEquals("message1", props.getProperty("code1"));
+ assertEquals("message2", props.getProperty("code2"));
+ return props;
+ }
+
+ private String storeProperties(Properties props, String header, boolean useWriter) throws IOException {
+ DefaultPropertiesPersister persister = new DefaultPropertiesPersister();
+ String propCopy = null;
+ if (useWriter) {
+ StringWriter propWriter = new StringWriter();
+ persister.store(props, propWriter, header);
+ propCopy = propWriter.toString();
+ }
+ else {
+ ByteArrayOutputStream propOut = new ByteArrayOutputStream();
+ persister.store(props, propOut, header);
+ propCopy = new String(propOut.toByteArray());
+ }
+ if (header != null) {
+ assertTrue(propCopy.indexOf(header) != -1);
+ }
+ assertTrue(propCopy.indexOf("\ncode1=message1") != -1);
+ assertTrue(propCopy.indexOf("\ncode2=message2") != -1);
+ return propCopy;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/ReflectionUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/util/ReflectionUtilsTests.java
new file mode 100644
index 00000000000..474cbd64424
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/ReflectionUtilsTests.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.rmi.ConnectException;
+import java.rmi.RemoteException;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+import org.springframework.test.AssertThrows;
+
+/**
+ *
+ * JUnit 3.8 based unit tests for {@link ReflectionUtils}.
+ *
+ *
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ * @author Sam Brannen
+ */
+public class ReflectionUtilsTests extends TestCase {
+
+ public void testFindField() {
+ Field field;
+
+ field = ReflectionUtils.findField(TestBeanSubclassWithPublicField.class, "publicField", String.class);
+ assertNotNull(field);
+ assertEquals("publicField", field.getName());
+ assertEquals(String.class, field.getType());
+ assertTrue("Field should be public.", Modifier.isPublic(field.getModifiers()));
+
+ field = ReflectionUtils.findField(TestBeanSubclassWithNewField.class, "prot", String.class);
+ assertNotNull(field);
+ assertEquals("prot", field.getName());
+ assertEquals(String.class, field.getType());
+ assertTrue("Field should be protected.", Modifier.isProtected(field.getModifiers()));
+
+ field = ReflectionUtils.findField(TestBeanSubclassWithNewField.class, "name", String.class);
+ assertNotNull(field);
+ assertEquals("name", field.getName());
+ assertEquals(String.class, field.getType());
+ assertTrue("Field should be private.", Modifier.isPrivate(field.getModifiers()));
+ }
+
+ public void testSetField() {
+ final TestBeanSubclassWithNewField testBean = new TestBeanSubclassWithNewField();
+ final Field field = ReflectionUtils.findField(TestBeanSubclassWithNewField.class, "name", String.class);
+
+ new AssertThrows(IllegalStateException.class,
+ "Calling setField() with on a private field without making it accessible should throw an IllegalStateException.") {
+
+ public void test() throws Exception {
+ ReflectionUtils.setField(field, testBean, "FooBar");
+ }
+ }.runTest();
+
+ ReflectionUtils.makeAccessible(field);
+
+ ReflectionUtils.setField(field, testBean, "FooBar");
+ assertNotNull(testBean.getName());
+ assertEquals("FooBar", testBean.getName());
+
+ ReflectionUtils.setField(field, testBean, null);
+ assertNull(testBean.getName());
+ }
+
+
+ public void testInvokeMethod() throws Exception {
+ String rob = "Rob Harrop";
+ String juergen = "Juergen Hoeller";
+
+ TestBean bean = new TestBean();
+ bean.setName(rob);
+
+ Method getName = TestBean.class.getMethod("getName", (Class[]) null);
+ Method setName = TestBean.class.getMethod("setName", new Class[] { String.class });
+
+ Object name = ReflectionUtils.invokeMethod(getName, bean);
+ assertEquals("Incorrect name returned", rob, name);
+
+ ReflectionUtils.invokeMethod(setName, bean, new Object[] { juergen });
+ assertEquals("Incorrect name set", juergen, bean.getName());
+ }
+
+ public void testDeclaresException() throws Exception {
+ Method remoteExMethod = A.class.getDeclaredMethod("foo", new Class[] {Integer.class});
+ assertTrue(ReflectionUtils.declaresException(remoteExMethod, RemoteException.class));
+ assertTrue(ReflectionUtils.declaresException(remoteExMethod, ConnectException.class));
+ assertFalse(ReflectionUtils.declaresException(remoteExMethod, NoSuchMethodException.class));
+ assertFalse(ReflectionUtils.declaresException(remoteExMethod, Exception.class));
+
+ Method illegalExMethod = B.class.getDeclaredMethod("bar", new Class[] {String.class});
+ assertTrue(ReflectionUtils.declaresException(illegalExMethod, IllegalArgumentException.class));
+ assertTrue(ReflectionUtils.declaresException(illegalExMethod, NumberFormatException.class));
+ assertFalse(ReflectionUtils.declaresException(illegalExMethod, IllegalStateException.class));
+ assertFalse(ReflectionUtils.declaresException(illegalExMethod, Exception.class));
+ }
+
+ public void testCopySrcToDestinationOfIncorrectClass() {
+ TestBean src = new TestBean();
+ String dest = new String();
+ try {
+ ReflectionUtils.shallowCopyFieldState(src, dest);
+ fail();
+ }
+ catch (IllegalArgumentException ex) {
+ // Ok
+ }
+ }
+
+ public void testRejectsNullSrc() {
+ TestBean src = null;
+ String dest = new String();
+ try {
+ ReflectionUtils.shallowCopyFieldState(src, dest);
+ fail();
+ }
+ catch (IllegalArgumentException ex) {
+ // Ok
+ }
+ }
+
+ public void testRejectsNullDest() {
+ TestBean src = new TestBean();
+ String dest = null;
+ try {
+ ReflectionUtils.shallowCopyFieldState(src, dest);
+ fail();
+ }
+ catch (IllegalArgumentException ex) {
+ // Ok
+ }
+ }
+
+ public void testValidCopy() {
+ TestBean src = new TestBean();
+ TestBean dest = new TestBean();
+ testValidCopy(src, dest);
+ }
+
+ public void testValidCopyOnSubTypeWithNewField() {
+ TestBeanSubclassWithNewField src = new TestBeanSubclassWithNewField();
+ TestBeanSubclassWithNewField dest = new TestBeanSubclassWithNewField();
+ src.magic = 11;
+
+ // Will check inherited fields are copied
+ testValidCopy(src, dest);
+
+ // Check subclass fields were copied
+ assertEquals(src.magic, dest.magic);
+ assertEquals(src.prot, dest.prot);
+ }
+
+ public void testValidCopyToSubType() {
+ TestBean src = new TestBean();
+ TestBeanSubclassWithNewField dest = new TestBeanSubclassWithNewField();
+ dest.magic = 11;
+ testValidCopy(src, dest);
+ // Should have left this one alone
+ assertEquals(11, dest.magic);
+ }
+
+ public void testValidCopyToSubTypeWithFinalField() {
+ TestBeanSubclassWithFinalField src = new TestBeanSubclassWithFinalField();
+ TestBeanSubclassWithFinalField dest = new TestBeanSubclassWithFinalField();
+ // Check that this doesn't fail due to attempt to assign final
+ testValidCopy(src, dest);
+ }
+
+ private void testValidCopy(TestBean src, TestBean dest) {
+ src.setName("freddie");
+ src.setAge(15);
+ src.setSpouse(new TestBean());
+ assertFalse(src.getAge() == dest.getAge());
+
+ ReflectionUtils.shallowCopyFieldState(src, dest);
+ assertEquals(src.getAge(), dest.getAge());
+ assertEquals(src.getSpouse(), dest.getSpouse());
+ assertEquals(src.getDoctor(), dest.getDoctor());
+ }
+
+ static class ListSavingMethodCallback implements ReflectionUtils.MethodCallback {
+ private List methodNames = new LinkedList();
+
+ private List methods = new LinkedList();
+
+ public void doWith(Method m) throws IllegalArgumentException, IllegalAccessException {
+ this.methodNames.add(m.getName());
+ this.methods.add(m);
+ }
+
+ public List getMethodNames() {
+ return this.methodNames;
+ }
+
+ public List getMethods() {
+ return this.methods;
+ }
+ };
+
+ public void testDoWithProtectedMethods() {
+ ListSavingMethodCallback mc = new ListSavingMethodCallback();
+ ReflectionUtils.doWithMethods(TestBean.class, mc, new ReflectionUtils.MethodFilter() {
+ public boolean matches(Method m) {
+ return Modifier.isProtected(m.getModifiers());
+ }
+ });
+ assertFalse(mc.getMethodNames().isEmpty());
+ assertTrue("Must find protected method on Object", mc.getMethodNames().contains("clone"));
+ assertTrue("Must find protected method on Object", mc.getMethodNames().contains("finalize"));
+ assertFalse("Public, not protected", mc.getMethodNames().contains("hashCode"));
+ assertFalse("Public, not protected", mc.getMethodNames().contains("absquatulate"));
+ }
+
+ public static class TestBeanSubclass extends TestBean {
+ public void absquatulate() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ public void testDuplicatesFound() {
+ ListSavingMethodCallback mc = new ListSavingMethodCallback();
+ ReflectionUtils.doWithMethods(TestBeanSubclass.class, mc);
+ int absquatulateCount = 0;
+ for (Iterator it = mc.getMethodNames().iterator(); it.hasNext();) {
+ String name = (String) it.next();
+ if (name.equals("absquatulate")) {
+ ++absquatulateCount;
+ }
+ }
+ assertEquals("Found 2 absquatulates", 2, absquatulateCount);
+ }
+
+ public void testFindMethod() throws Exception {
+ assertNotNull(ReflectionUtils.findMethod(B.class, "bar", new Class[]{String.class}));
+ assertNotNull(ReflectionUtils.findMethod(B.class, "foo", new Class[]{Integer.class}));
+ }
+
+
+ public static class TestBeanSubclassWithPublicField extends TestBean {
+ public String publicField = "foo";
+ }
+
+ public static class TestBeanSubclassWithNewField extends TestBean {
+ private int magic;
+ protected String prot = "foo";
+ }
+
+
+ public static class TestBeanSubclassWithFinalField extends TestBean {
+ private final String foo = "will break naive copy that doesn't exclude statics";
+ }
+
+
+ private static class A {
+ private void foo(Integer i) throws RemoteException {}
+ }
+
+
+ private static class B extends A {
+ void bar(String s) throws IllegalArgumentException {}
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/ResourceUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/util/ResourceUtilsTests.java
new file mode 100644
index 00000000000..9baaf384a00
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/ResourceUtilsTests.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.util;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class ResourceUtilsTests extends TestCase {
+
+ public void testIsJarURL() throws Exception {
+ assertTrue(ResourceUtils.isJarURL(new URL("jar:file:myjar.jar!/mypath")));
+ assertTrue(ResourceUtils.isJarURL(new URL(null, "zip:file:myjar.jar!/mypath", new DummyURLStreamHandler())));
+ assertTrue(ResourceUtils.isJarURL(new URL(null, "wsjar:file:myjar.jar!/mypath", new DummyURLStreamHandler())));
+ assertFalse(ResourceUtils.isJarURL(new URL("file:myjar.jar")));
+ assertFalse(ResourceUtils.isJarURL(new URL("http:myserver/myjar.jar")));
+ }
+
+ public void testExtractJarFileURL() throws Exception {
+ assertEquals(new URL("file:myjar.jar"),
+ ResourceUtils.extractJarFileURL(new URL("jar:file:myjar.jar!/mypath")));
+ assertEquals(new URL("file:/myjar.jar"),
+ ResourceUtils.extractJarFileURL(new URL(null, "jar:myjar.jar!/mypath", new DummyURLStreamHandler())));
+ assertEquals(new URL("file:myjar.jar"),
+ ResourceUtils.extractJarFileURL(new URL(null, "zip:file:myjar.jar!/mypath", new DummyURLStreamHandler())));
+ assertEquals(new URL("file:myjar.jar"),
+ ResourceUtils.extractJarFileURL(new URL(null, "wsjar:file:myjar.jar!/mypath", new DummyURLStreamHandler())));
+ assertEquals(new URL("file:myjar.jar"),
+ ResourceUtils.extractJarFileURL(new URL("jar:file:myjar.jar!/")));
+ assertEquals(new URL("file:myjar.jar"),
+ ResourceUtils.extractJarFileURL(new URL(null, "zip:file:myjar.jar!/", new DummyURLStreamHandler())));
+ assertEquals(new URL("file:myjar.jar"),
+ ResourceUtils.extractJarFileURL(new URL(null, "wsjar:file:myjar.jar!/", new DummyURLStreamHandler())));
+ assertEquals(new URL("file:myjar.jar"),
+ ResourceUtils.extractJarFileURL(new URL("file:myjar.jar")));
+ }
+
+
+ /**
+ * Dummy URLStreamHandler that's just specified to suppress the standard
+ * java.net.URL URLStreamHandler lookup, to be able to
+ * use the standard URL class for parsing "rmi:..." URLs.
+ */
+ private static class DummyURLStreamHandler extends URLStreamHandler {
+
+ protected URLConnection openConnection(URL url) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/SerializationTestUtils.java b/org.springframework.testsuite/src/test/java/org/springframework/util/SerializationTestUtils.java
new file mode 100644
index 00000000000..bdffe7578da
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/SerializationTestUtils.java
@@ -0,0 +1,97 @@
+/*
+ * The Spring Framework is published under the terms
+ * of the Apache Software License.
+ */
+
+package org.springframework.util;
+
+import java.awt.Point;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+
+/**
+ * Utilities for testing serializability of objects.
+ * Exposes static methods for use in other test cases.
+ * Extends TestCase only to test itself.
+ *
+ * @author Rod Johnson
+ */
+public class SerializationTestUtils extends TestCase {
+
+ public static void testSerialization(Object o) throws IOException {
+ OutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(o);
+ }
+
+ public static boolean isSerializable(Object o) throws IOException {
+ try {
+ testSerialization(o);
+ return true;
+ }
+ catch (NotSerializableException ex) {
+ return false;
+ }
+ }
+
+ public static Object serializeAndDeserialize(Object o) throws IOException, ClassNotFoundException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(o);
+ oos.flush();
+ baos.flush();
+ byte[] bytes = baos.toByteArray();
+
+ ByteArrayInputStream is = new ByteArrayInputStream(bytes);
+ ObjectInputStream ois = new ObjectInputStream(is);
+ Object o2 = ois.readObject();
+
+ return o2;
+ }
+
+ public SerializationTestUtils(String s) {
+ super(s);
+ }
+
+ public void testWithNonSerializableObject() throws IOException {
+ TestBean o = new TestBean();
+ assertFalse(o instanceof Serializable);
+
+ assertFalse(isSerializable(o));
+
+ try {
+ testSerialization(o);
+ fail();
+ }
+ catch (NotSerializableException ex) {
+ // Ok
+ }
+ }
+
+ public void testWithSerializableObject() throws Exception {
+ int x = 5;
+ int y = 10;
+ Point p = new Point(x, y);
+ assertTrue(p instanceof Serializable);
+
+ testSerialization(p);
+
+ assertTrue(isSerializable(p));
+
+ Point p2 = (Point) serializeAndDeserialize(p);
+ assertNotSame(p, p2);
+ assertEquals(x, (int) p2.getX());
+ assertEquals(y, (int) p2.getY());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/StopWatchTests.java b/org.springframework.testsuite/src/test/java/org/springframework/util/StopWatchTests.java
new file mode 100644
index 00000000000..a066318ebf8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/StopWatchTests.java
@@ -0,0 +1,144 @@
+
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.util;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rod Johnson
+ */
+public class StopWatchTests extends TestCase {
+
+ /**
+ * Are timings off in JUnit?
+ */
+ public void testValidUsage() throws Exception {
+ StopWatch sw = new StopWatch();
+ long int1 = 166L;
+ long int2 = 45L;
+ String name1 = "Task 1";
+ String name2 = "Task 2";
+
+ long fudgeFactor = 5L;
+ assertFalse(sw.isRunning());
+ sw.start(name1);
+ Thread.sleep(int1);
+ assertTrue(sw.isRunning());
+ sw.stop();
+
+ // TODO are timings off in JUnit? Why do these assertions sometimes fail
+ // under both Ant and Eclipse?
+
+ //assertTrue("Unexpected timing " + sw.getTotalTime(), sw.getTotalTime() >= int1);
+ //assertTrue("Unexpected timing " + sw.getTotalTime(), sw.getTotalTime() <= int1 + fudgeFactor);
+ sw.start(name2);
+ Thread.sleep(int2);
+ sw.stop();
+ //assertTrue("Unexpected timing " + sw.getTotalTime(), sw.getTotalTime() >= int1 + int2);
+ //assertTrue("Unexpected timing " + sw.getTotalTime(), sw.getTotalTime() <= int1 + int2 + fudgeFactor);
+
+ assertTrue(sw.getTaskCount() == 2);
+ String pp = sw.prettyPrint();
+ assertTrue(pp.indexOf(name1) != -1);
+ assertTrue(pp.indexOf(name2) != -1);
+
+ StopWatch.TaskInfo[] tasks = sw.getTaskInfo();
+ assertTrue(tasks.length == 2);
+ assertTrue(tasks[0].getTaskName().equals(name1));
+ assertTrue(tasks[1].getTaskName().equals(name2));
+ sw.toString();
+ }
+
+ public void testValidUsageNotKeepingTaskList() throws Exception {
+ StopWatch sw = new StopWatch();
+ sw.setKeepTaskList(false);
+ long int1 = 166L;
+ long int2 = 45L;
+ String name1 = "Task 1";
+ String name2 = "Task 2";
+
+ long fudgeFactor = 5L;
+ assertFalse(sw.isRunning());
+ sw.start(name1);
+ Thread.sleep(int1);
+ assertTrue(sw.isRunning());
+ sw.stop();
+
+ // TODO are timings off in JUnit? Why do these assertions sometimes fail
+ // under both Ant and Eclipse?
+
+ //assertTrue("Unexpected timing " + sw.getTotalTime(), sw.getTotalTime() >= int1);
+ //assertTrue("Unexpected timing " + sw.getTotalTime(), sw.getTotalTime() <= int1 + fudgeFactor);
+ sw.start(name2);
+ Thread.sleep(int2);
+ sw.stop();
+ //assertTrue("Unexpected timing " + sw.getTotalTime(), sw.getTotalTime() >= int1 + int2);
+ //assertTrue("Unexpected timing " + sw.getTotalTime(), sw.getTotalTime() <= int1 + int2 + fudgeFactor);
+
+ assertTrue(sw.getTaskCount() == 2);
+ String pp = sw.prettyPrint();
+ assertTrue(pp.indexOf("kept") != -1);
+ sw.toString();
+
+ try {
+ sw.getTaskInfo();
+ fail();
+ }
+ catch (UnsupportedOperationException ex) {
+ // Ok
+ }
+ }
+
+ public void testFailureToStartBeforeGettingTimings() {
+ StopWatch sw = new StopWatch();
+ try {
+ sw.getLastTaskTimeMillis();
+ fail("Can't get last interval if no tests run");
+ }
+ catch (IllegalStateException ex) {
+ // Ok
+ }
+ }
+
+ public void testFailureToStartBeforeStop() {
+ StopWatch sw = new StopWatch();
+ try {
+ sw.stop();
+ fail("Can't stop without starting");
+ }
+ catch (IllegalStateException ex) {
+ // Ok
+ }
+ }
+
+ public void testRejectsStartTwice() {
+ StopWatch sw = new StopWatch();
+ try {
+ sw.start("");
+ sw.stop();
+ sw.start("");
+ assertTrue(sw.isRunning());
+ sw.start("");
+ fail("Can't start twice");
+ }
+ catch (IllegalStateException ex) {
+ // Ok
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/StringUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/util/StringUtilsTests.java
new file mode 100644
index 00000000000..320b7363c61
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/StringUtilsTests.java
@@ -0,0 +1,614 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.util;
+
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ */
+public class StringUtilsTests extends TestCase {
+
+ public void testHasTextBlank() throws Exception {
+ String blank = " ";
+ assertEquals(false, StringUtils.hasText(blank));
+ }
+
+ public void testHasTextNullEmpty() throws Exception {
+ assertEquals(false, StringUtils.hasText(null));
+ assertEquals(false, StringUtils.hasText(""));
+ }
+
+ public void testHasTextValid() throws Exception {
+ assertEquals(true, StringUtils.hasText("t"));
+ }
+
+ public void testContainsWhitespace() throws Exception {
+ assertFalse(StringUtils.containsWhitespace(null));
+ assertFalse(StringUtils.containsWhitespace(""));
+ assertFalse(StringUtils.containsWhitespace("a"));
+ assertFalse(StringUtils.containsWhitespace("abc"));
+ assertTrue(StringUtils.containsWhitespace(" "));
+ assertTrue(StringUtils.containsWhitespace(" a"));
+ assertTrue(StringUtils.containsWhitespace("abc "));
+ assertTrue(StringUtils.containsWhitespace("a b"));
+ assertTrue(StringUtils.containsWhitespace("a b"));
+ }
+
+ public void testTrimWhitespace() throws Exception {
+ assertEquals(null, StringUtils.trimWhitespace(null));
+ assertEquals("", StringUtils.trimWhitespace(""));
+ assertEquals("", StringUtils.trimWhitespace(" "));
+ assertEquals("", StringUtils.trimWhitespace("\t"));
+ assertEquals("a", StringUtils.trimWhitespace(" a"));
+ assertEquals("a", StringUtils.trimWhitespace("a "));
+ assertEquals("a", StringUtils.trimWhitespace(" a "));
+ assertEquals("a b", StringUtils.trimWhitespace(" a b "));
+ assertEquals("a b c", StringUtils.trimWhitespace(" a b c "));
+ }
+
+ public void testTrimAllWhitespace() throws Exception {
+ assertEquals("", StringUtils.trimAllWhitespace(""));
+ assertEquals("", StringUtils.trimAllWhitespace(" "));
+ assertEquals("", StringUtils.trimAllWhitespace("\t"));
+ assertEquals("a", StringUtils.trimAllWhitespace(" a"));
+ assertEquals("a", StringUtils.trimAllWhitespace("a "));
+ assertEquals("a", StringUtils.trimAllWhitespace(" a "));
+ assertEquals("ab", StringUtils.trimAllWhitespace(" a b "));
+ assertEquals("abc", StringUtils.trimAllWhitespace(" a b c "));
+ }
+
+ public void testTrimLeadingWhitespace() throws Exception {
+ assertEquals(null, StringUtils.trimLeadingWhitespace(null));
+ assertEquals("", StringUtils.trimLeadingWhitespace(""));
+ assertEquals("", StringUtils.trimLeadingWhitespace(" "));
+ assertEquals("", StringUtils.trimLeadingWhitespace("\t"));
+ assertEquals("a", StringUtils.trimLeadingWhitespace(" a"));
+ assertEquals("a ", StringUtils.trimLeadingWhitespace("a "));
+ assertEquals("a ", StringUtils.trimLeadingWhitespace(" a "));
+ assertEquals("a b ", StringUtils.trimLeadingWhitespace(" a b "));
+ assertEquals("a b c ", StringUtils.trimLeadingWhitespace(" a b c "));
+ }
+
+ public void testTrimTrailingWhitespace() throws Exception {
+ assertEquals(null, StringUtils.trimTrailingWhitespace(null));
+ assertEquals("", StringUtils.trimTrailingWhitespace(""));
+ assertEquals("", StringUtils.trimTrailingWhitespace(" "));
+ assertEquals("", StringUtils.trimTrailingWhitespace("\t"));
+ assertEquals("a", StringUtils.trimTrailingWhitespace("a "));
+ assertEquals(" a", StringUtils.trimTrailingWhitespace(" a"));
+ assertEquals(" a", StringUtils.trimTrailingWhitespace(" a "));
+ assertEquals(" a b", StringUtils.trimTrailingWhitespace(" a b "));
+ assertEquals(" a b c", StringUtils.trimTrailingWhitespace(" a b c "));
+ }
+
+ public void testTrimLeadingCharacter() throws Exception {
+ assertEquals(null, StringUtils.trimLeadingCharacter(null, ' '));
+ assertEquals("", StringUtils.trimLeadingCharacter("", ' '));
+ assertEquals("", StringUtils.trimLeadingCharacter(" ", ' '));
+ assertEquals("\t", StringUtils.trimLeadingCharacter("\t", ' '));
+ assertEquals("a", StringUtils.trimLeadingCharacter(" a", ' '));
+ assertEquals("a ", StringUtils.trimLeadingCharacter("a ", ' '));
+ assertEquals("a ", StringUtils.trimLeadingCharacter(" a ", ' '));
+ assertEquals("a b ", StringUtils.trimLeadingCharacter(" a b ", ' '));
+ assertEquals("a b c ", StringUtils.trimLeadingCharacter(" a b c ", ' '));
+ }
+
+ public void testTrimTrailingCharacter() throws Exception {
+ assertEquals(null, StringUtils.trimTrailingCharacter(null, ' '));
+ assertEquals("", StringUtils.trimTrailingCharacter("", ' '));
+ assertEquals("", StringUtils.trimTrailingCharacter(" ", ' '));
+ assertEquals("\t", StringUtils.trimTrailingCharacter("\t", ' '));
+ assertEquals("a", StringUtils.trimTrailingCharacter("a ", ' '));
+ assertEquals(" a", StringUtils.trimTrailingCharacter(" a", ' '));
+ assertEquals(" a", StringUtils.trimTrailingCharacter(" a ", ' '));
+ assertEquals(" a b", StringUtils.trimTrailingCharacter(" a b ", ' '));
+ assertEquals(" a b c", StringUtils.trimTrailingCharacter(" a b c ", ' '));
+ }
+
+ public void testCountOccurrencesOf() {
+ assertTrue("nullx2 = 0",
+ StringUtils.countOccurrencesOf(null, null) == 0);
+ assertTrue("null string = 0",
+ StringUtils.countOccurrencesOf("s", null) == 0);
+ assertTrue("null substring = 0",
+ StringUtils.countOccurrencesOf(null, "s") == 0);
+ String s = "erowoiueoiur";
+ assertTrue("not found = 0",
+ StringUtils.countOccurrencesOf(s, "WERWER") == 0);
+ assertTrue("not found char = 0",
+ StringUtils.countOccurrencesOf(s, "x") == 0);
+ assertTrue("not found ws = 0",
+ StringUtils.countOccurrencesOf(s, " ") == 0);
+ assertTrue("not found empty string = 0",
+ StringUtils.countOccurrencesOf(s, "") == 0);
+ assertTrue("found char=2", StringUtils.countOccurrencesOf(s, "e") == 2);
+ assertTrue("found substring=2",
+ StringUtils.countOccurrencesOf(s, "oi") == 2);
+ assertTrue("found substring=2",
+ StringUtils.countOccurrencesOf(s, "oiu") == 2);
+ assertTrue("found substring=3",
+ StringUtils.countOccurrencesOf(s, "oiur") == 1);
+ assertTrue("test last", StringUtils.countOccurrencesOf(s, "r") == 2);
+ }
+
+ public void testReplace() throws Exception {
+ String inString = "a6AazAaa77abaa";
+ String oldPattern = "aa";
+ String newPattern = "foo";
+
+ // Simple replace
+ String s = StringUtils.replace(inString, oldPattern, newPattern);
+ assertTrue("Replace 1 worked", s.equals("a6AazAfoo77abfoo"));
+
+ // Non match: no change
+ s = StringUtils.replace(inString, "qwoeiruqopwieurpoqwieur", newPattern);
+ assertTrue("Replace non matched is equal", s.equals(inString));
+
+ // Null new pattern: should ignore
+ s = StringUtils.replace(inString, oldPattern, null);
+ assertTrue("Replace non matched is equal", s.equals(inString));
+
+ // Null old pattern: should ignore
+ s = StringUtils.replace(inString, null, newPattern);
+ assertTrue("Replace non matched is equal", s.equals(inString));
+ }
+
+ public void testDelete() throws Exception {
+ String inString = "The quick brown fox jumped over the lazy dog";
+
+ String noThe = StringUtils.delete(inString, "the");
+ assertTrue("Result has no the [" + noThe + "]",
+ noThe.equals("The quick brown fox jumped over lazy dog"));
+
+ String nohe = StringUtils.delete(inString, "he");
+ assertTrue("Result has no he [" + nohe + "]",
+ nohe.equals("T quick brown fox jumped over t lazy dog"));
+
+ String nosp = StringUtils.delete(inString, " ");
+ assertTrue("Result has no spaces",
+ nosp.equals("Thequickbrownfoxjumpedoverthelazydog"));
+
+ String killEnd = StringUtils.delete(inString, "dog");
+ assertTrue("Result has no dog",
+ killEnd.equals("The quick brown fox jumped over the lazy "));
+
+ String mismatch = StringUtils.delete(inString, "dxxcxcxog");
+ assertTrue("Result is unchanged", mismatch.equals(inString));
+
+ String nochange = StringUtils.delete(inString, "");
+ assertTrue("Result is unchanged", nochange.equals(inString));
+ }
+
+ public void testDeleteAny() throws Exception {
+ String inString = "Able was I ere I saw Elba";
+
+ String res = StringUtils.deleteAny(inString, "I");
+ assertTrue("Result has no Is [" + res + "]", res.equals("Able was ere saw Elba"));
+
+ res = StringUtils.deleteAny(inString, "AeEba!");
+ assertTrue("Result has no Is [" + res + "]", res.equals("l ws I r I sw l"));
+
+ String mismatch = StringUtils.deleteAny(inString, "#@$#$^");
+ assertTrue("Result is unchanged", mismatch.equals(inString));
+
+ String whitespace = "This is\n\n\n \t a messagy string with whitespace\n";
+ assertTrue("Has CR", whitespace.indexOf("\n") != -1);
+ assertTrue("Has tab", whitespace.indexOf("\t") != -1);
+ assertTrue("Has sp", whitespace.indexOf(" ") != -1);
+ String cleaned = StringUtils.deleteAny(whitespace, "\n\t ");
+ assertTrue("Has no CR", cleaned.indexOf("\n") == -1);
+ assertTrue("Has no tab", cleaned.indexOf("\t") == -1);
+ assertTrue("Has no sp", cleaned.indexOf(" ") == -1);
+ assertTrue("Still has chars", cleaned.length() > 10);
+ }
+
+
+ public void testQuote() {
+ assertEquals("'myString'", StringUtils.quote("myString"));
+ assertEquals("''", StringUtils.quote(""));
+ assertNull(StringUtils.quote(null));
+ }
+
+ public void testQuoteIfString() {
+ assertEquals("'myString'", StringUtils.quoteIfString("myString"));
+ assertEquals("''", StringUtils.quoteIfString(""));
+ assertEquals(new Integer(5), StringUtils.quoteIfString(new Integer(5)));
+ assertNull(StringUtils.quoteIfString(null));
+ }
+
+ public void testUnqualify() {
+ String qualified = "i.am.not.unqualified";
+ assertEquals("unqualified", StringUtils.unqualify(qualified));
+ }
+
+ public void testCapitalize() {
+ String capitalized = "i am not capitalized";
+ assertEquals("I am not capitalized", StringUtils.capitalize(capitalized));
+ }
+
+ public void testUncapitalize() {
+ String capitalized = "I am capitalized";
+ assertEquals("i am capitalized", StringUtils.uncapitalize(capitalized));
+ }
+
+ public void testGetFilename() {
+ assertEquals(null, StringUtils.getFilename(null));
+ assertEquals("", StringUtils.getFilename(""));
+ assertEquals("myfile", StringUtils.getFilename("myfile"));
+ assertEquals("myfile", StringUtils.getFilename("mypath/myfile"));
+ assertEquals("myfile.", StringUtils.getFilename("myfile."));
+ assertEquals("myfile.", StringUtils.getFilename("mypath/myfile."));
+ assertEquals("myfile.txt", StringUtils.getFilename("myfile.txt"));
+ assertEquals("myfile.txt", StringUtils.getFilename("mypath/myfile.txt"));
+ }
+
+ public void testGetFilenameExtension() {
+ assertEquals(null, StringUtils.getFilenameExtension(null));
+ assertEquals(null, StringUtils.getFilenameExtension(""));
+ assertEquals(null, StringUtils.getFilenameExtension("myfile"));
+ assertEquals(null, StringUtils.getFilenameExtension("myPath/myfile"));
+ assertEquals("", StringUtils.getFilenameExtension("myfile."));
+ assertEquals("", StringUtils.getFilenameExtension("myPath/myfile."));
+ assertEquals("txt", StringUtils.getFilenameExtension("myfile.txt"));
+ assertEquals("txt", StringUtils.getFilenameExtension("mypath/myfile.txt"));
+ }
+
+ public void testStripFilenameExtension() {
+ assertEquals(null, StringUtils.stripFilenameExtension(null));
+ assertEquals("", StringUtils.stripFilenameExtension(""));
+ assertEquals("myfile", StringUtils.stripFilenameExtension("myfile"));
+ assertEquals("mypath/myfile", StringUtils.stripFilenameExtension("mypath/myfile"));
+ assertEquals("myfile", StringUtils.stripFilenameExtension("myfile."));
+ assertEquals("mypath/myfile", StringUtils.stripFilenameExtension("mypath/myfile."));
+ assertEquals("myfile", StringUtils.stripFilenameExtension("myfile.txt"));
+ assertEquals("mypath/myfile", StringUtils.stripFilenameExtension("mypath/myfile.txt"));
+ }
+
+ public void testCleanPath() {
+ assertEquals("mypath/myfile", StringUtils.cleanPath("mypath/myfile"));
+ assertEquals("mypath/myfile", StringUtils.cleanPath("mypath\\myfile"));
+ assertEquals("mypath/myfile", StringUtils.cleanPath("mypath/../mypath/myfile"));
+ assertEquals("mypath/myfile", StringUtils.cleanPath("mypath/myfile/../../mypath/myfile"));
+ assertEquals("../mypath/myfile", StringUtils.cleanPath("../mypath/myfile"));
+ assertEquals("../mypath/myfile", StringUtils.cleanPath("../mypath/../mypath/myfile"));
+ assertEquals("../mypath/myfile", StringUtils.cleanPath("mypath/../../mypath/myfile"));
+ assertEquals("/../mypath/myfile", StringUtils.cleanPath("/../mypath/myfile"));
+ }
+
+ public void testPathEquals() {
+ assertTrue("Must be true for the same strings",
+ StringUtils.pathEquals("/dummy1/dummy2/dummy3",
+ "/dummy1/dummy2/dummy3"));
+ assertTrue("Must be true for the same win strings",
+ StringUtils.pathEquals("C:\\dummy1\\dummy2\\dummy3",
+ "C:\\dummy1\\dummy2\\dummy3"));
+ assertTrue("Must be true for one top path on 1",
+ StringUtils.pathEquals("/dummy1/bin/../dummy2/dummy3",
+ "/dummy1/dummy2/dummy3"));
+ assertTrue("Must be true for one win top path on 2",
+ StringUtils.pathEquals("C:\\dummy1\\dummy2\\dummy3",
+ "C:\\dummy1\\bin\\..\\dummy2\\dummy3"));
+ assertTrue("Must be true for two top paths on 1",
+ StringUtils.pathEquals("/dummy1/bin/../dummy2/bin/../dummy3",
+ "/dummy1/dummy2/dummy3"));
+ assertTrue("Must be true for two win top paths on 2",
+ StringUtils.pathEquals("C:\\dummy1\\dummy2\\dummy3",
+ "C:\\dummy1\\bin\\..\\dummy2\\bin\\..\\dummy3"));
+ assertTrue("Must be true for double top paths on 1",
+ StringUtils.pathEquals("/dummy1/bin/tmp/../../dummy2/dummy3",
+ "/dummy1/dummy2/dummy3"));
+ assertTrue("Must be true for double top paths on 2 with similarity",
+ StringUtils.pathEquals("/dummy1/dummy2/dummy3",
+ "/dummy1/dum/dum/../../dummy2/dummy3"));
+ assertTrue("Must be true for current paths",
+ StringUtils.pathEquals("./dummy1/dummy2/dummy3",
+ "dummy1/dum/./dum/../../dummy2/dummy3"));
+ assertFalse("Must be false for relative/absolute paths",
+ StringUtils.pathEquals("./dummy1/dummy2/dummy3",
+ "/dummy1/dum/./dum/../../dummy2/dummy3"));
+ assertFalse("Must be false for different strings",
+ StringUtils.pathEquals("/dummy1/dummy2/dummy3",
+ "/dummy1/dummy4/dummy3"));
+ assertFalse("Must be false for one false path on 1",
+ StringUtils.pathEquals("/dummy1/bin/tmp/../dummy2/dummy3",
+ "/dummy1/dummy2/dummy3"));
+ assertFalse("Must be false for one false win top path on 2",
+ StringUtils.pathEquals("C:\\dummy1\\dummy2\\dummy3",
+ "C:\\dummy1\\bin\\tmp\\..\\dummy2\\dummy3"));
+ assertFalse("Must be false for top path on 1 + difference",
+ StringUtils.pathEquals("/dummy1/bin/../dummy2/dummy3",
+ "/dummy1/dummy2/dummy4"));
+ }
+
+ public void testConcatenateStringArrays() {
+ String[] input1 = new String[] {"myString2"};
+ String[] input2 = new String[] {"myString1", "myString2"};
+ String[] result = StringUtils.concatenateStringArrays(input1, input2);
+ assertEquals(3, result.length);
+ assertEquals("myString2", result[0]);
+ assertEquals("myString1", result[1]);
+ assertEquals("myString2", result[2]);
+
+ assertEquals(input1, StringUtils.concatenateStringArrays(input1, null));
+ assertEquals(input2, StringUtils.concatenateStringArrays(null, input2));
+ assertNull(StringUtils.concatenateStringArrays(null, null));
+ }
+
+ public void testMergeStringArrays() {
+ String[] input1 = new String[] {"myString2"};
+ String[] input2 = new String[] {"myString1", "myString2"};
+ String[] result = StringUtils.mergeStringArrays(input1, input2);
+ assertEquals(2, result.length);
+ assertEquals("myString2", result[0]);
+ assertEquals("myString1", result[1]);
+
+ assertEquals(input1, StringUtils.mergeStringArrays(input1, null));
+ assertEquals(input2, StringUtils.mergeStringArrays(null, input2));
+ assertNull(StringUtils.mergeStringArrays(null, null));
+ }
+
+ public void testSortStringArray() {
+ String[] input = new String[] {"myString2"};
+ input = StringUtils.addStringToArray(input, "myString1");
+ assertEquals("myString2", input[0]);
+ assertEquals("myString1", input[1]);
+
+ StringUtils.sortStringArray(input);
+ assertEquals("myString1", input[0]);
+ assertEquals("myString2", input[1]);
+ }
+
+ public void testRemoveDuplicateStrings() {
+ String[] input = new String[] {"myString2", "myString1", "myString2"};
+ input = StringUtils.removeDuplicateStrings(input);
+ assertEquals("myString1", input[0]);
+ assertEquals("myString2", input[1]);
+ }
+
+ public void testSplitArrayElementsIntoProperties() {
+ String[] input = new String[] {"key1=value1 ", "key2 =\"value2\""};
+ Properties result = StringUtils.splitArrayElementsIntoProperties(input, "=");
+ assertEquals("value1", result.getProperty("key1"));
+ assertEquals("\"value2\"", result.getProperty("key2"));
+ }
+
+ public void testSplitArrayElementsIntoPropertiesAndDeletedChars() {
+ String[] input = new String[] {"key1=value1 ", "key2 =\"value2\""};
+ Properties result = StringUtils.splitArrayElementsIntoProperties(input, "=", "\"");
+ assertEquals("value1", result.getProperty("key1"));
+ assertEquals("value2", result.getProperty("key2"));
+ }
+
+ public void testTokenizeToStringArray() {
+ String[] sa = StringUtils.tokenizeToStringArray("a,b , ,c", ",");
+ assertEquals(3, sa.length);
+ assertTrue("components are correct",
+ sa[0].equals("a") && sa[1].equals("b") && sa[2].equals("c"));
+ }
+
+ public void testTokenizeToStringArrayWithNotIgnoreEmptyTokens() {
+ String[] sa = StringUtils.tokenizeToStringArray("a,b , ,c", ",", true, false);
+ assertEquals(4, sa.length);
+ assertTrue("components are correct",
+ sa[0].equals("a") && sa[1].equals("b") && sa[2].equals("") && sa[3].equals("c"));
+ }
+
+ public void testTokenizeToStringArrayWithNotTrimTokens() {
+ String[] sa = StringUtils.tokenizeToStringArray("a,b ,c", ",", false, true);
+ assertEquals(3, sa.length);
+ assertTrue("components are correct",
+ sa[0].equals("a") && sa[1].equals("b ") && sa[2].equals("c"));
+ }
+
+ public void testCommaDelimitedListToStringArrayWithNullProducesEmptyArray() {
+ String[] sa = StringUtils.commaDelimitedListToStringArray(null);
+ assertTrue("String array isn't null with null input", sa != null);
+ assertTrue("String array length == 0 with null input", sa.length == 0);
+ }
+
+ public void testCommaDelimitedListToStringArrayWithEmptyStringProducesEmptyArray() {
+ String[] sa = StringUtils.commaDelimitedListToStringArray("");
+ assertTrue("String array isn't null with null input", sa != null);
+ assertTrue("String array length == 0 with null input", sa.length == 0);
+ }
+
+ private void testStringArrayReverseTransformationMatches(String[] sa) {
+ String[] reverse =
+ StringUtils.commaDelimitedListToStringArray(StringUtils.arrayToCommaDelimitedString(sa));
+ assertEquals("Reverse transformation is equal",
+ Arrays.asList(sa),
+ Arrays.asList(reverse));
+ }
+
+ public void testDelimitedListToStringArrayWithComma() {
+ String[] sa = StringUtils.delimitedListToStringArray("a,b", ",");
+ assertEquals(2, sa.length);
+ assertEquals("a", sa[0]);
+ assertEquals("b", sa[1]);
+ }
+
+ public void testDelimitedListToStringArrayWithSemicolon() {
+ String[] sa = StringUtils.delimitedListToStringArray("a;b", ";");
+ assertEquals(2, sa.length);
+ assertEquals("a", sa[0]);
+ assertEquals("b", sa[1]);
+ }
+
+ public void testDelimitedListToStringArrayWithEmptyString() {
+ String[] sa = StringUtils.delimitedListToStringArray("a,b", "");
+ assertEquals(3, sa.length);
+ assertEquals("a", sa[0]);
+ assertEquals(",", sa[1]);
+ assertEquals("b", sa[2]);
+ }
+
+ public void testDelimitedListToStringArrayWithNullDelimiter() {
+ String[] sa = StringUtils.delimitedListToStringArray("a,b", null);
+ assertEquals(1, sa.length);
+ assertEquals("a,b", sa[0]);
+ }
+
+ public void testCommaDelimitedListToStringArrayMatchWords() {
+ // Could read these from files
+ String[] sa = new String[] {"foo", "bar", "big"};
+ doTestCommaDelimitedListToStringArrayLegalMatch(sa);
+ testStringArrayReverseTransformationMatches(sa);
+
+ sa = new String[] {"a", "b", "c"};
+ doTestCommaDelimitedListToStringArrayLegalMatch(sa);
+ testStringArrayReverseTransformationMatches(sa);
+
+ // Test same words
+ sa = new String[] {"AA", "AA", "AA", "AA", "AA"};
+ doTestCommaDelimitedListToStringArrayLegalMatch(sa);
+ testStringArrayReverseTransformationMatches(sa);
+ }
+
+ public void testCommaDelimitedListToStringArraySingleString() {
+ // Could read these from files
+ String s = "woeirqupoiewuropqiewuorpqiwueopriquwopeiurqopwieur";
+ String[] sa = StringUtils.commaDelimitedListToStringArray(s);
+ assertTrue("Found one String with no delimiters", sa.length == 1);
+ assertTrue("Single array entry matches input String with no delimiters",
+ sa[0].equals(s));
+ }
+
+ public void testCommaDelimitedListToStringArrayWithOtherPunctuation() {
+ // Could read these from files
+ String[] sa = new String[] {"xcvwert4456346&*.", "///", ".!", ".", ";"};
+ doTestCommaDelimitedListToStringArrayLegalMatch(sa);
+ }
+
+ /**
+ * We expect to see the empty Strings in the output.
+ */
+ public void testCommaDelimitedListToStringArrayEmptyStrings() {
+ // Could read these from files
+ String[] sa = StringUtils.commaDelimitedListToStringArray("a,,b");
+ assertEquals("a,,b produces array length 3", 3, sa.length);
+ assertTrue("components are correct",
+ sa[0].equals("a") && sa[1].equals("") && sa[2].equals("b"));
+
+ sa = new String[] {"", "", "a", ""};
+ doTestCommaDelimitedListToStringArrayLegalMatch(sa);
+ }
+
+ private void doTestCommaDelimitedListToStringArrayLegalMatch(String[] components) {
+ StringBuffer sbuf = new StringBuffer();
+ for (int i = 0; i < components.length; i++) {
+ if (i != 0) {
+ sbuf.append(",");
+ }
+ sbuf.append(components[i]);
+ }
+ String[] sa = StringUtils.commaDelimitedListToStringArray(sbuf.toString());
+ assertTrue("String array isn't null with legal match", sa != null);
+ assertEquals("String array length is correct with legal match", components.length, sa.length);
+ assertTrue("Output equals input", Arrays.equals(sa, components));
+ }
+
+ public void testEndsWithIgnoreCase() {
+ String suffix = "fOo";
+ assertTrue(StringUtils.endsWithIgnoreCase("foo", suffix));
+ assertTrue(StringUtils.endsWithIgnoreCase("Foo", suffix));
+ assertTrue(StringUtils.endsWithIgnoreCase("barfoo", suffix));
+ assertTrue(StringUtils.endsWithIgnoreCase("barbarfoo", suffix));
+ assertTrue(StringUtils.endsWithIgnoreCase("barFoo", suffix));
+ assertTrue(StringUtils.endsWithIgnoreCase("barBarFoo", suffix));
+ assertTrue(StringUtils.endsWithIgnoreCase("barfoO", suffix));
+ assertTrue(StringUtils.endsWithIgnoreCase("barFOO", suffix));
+ assertTrue(StringUtils.endsWithIgnoreCase("barfOo", suffix));
+ assertFalse(StringUtils.endsWithIgnoreCase(null, suffix));
+ assertFalse(StringUtils.endsWithIgnoreCase("barfOo", null));
+ assertFalse(StringUtils.endsWithIgnoreCase("b", suffix));
+ }
+
+ public void testParseLocaleStringSunnyDay() throws Exception {
+ Locale expectedLocale = Locale.UK;
+ Locale locale = StringUtils.parseLocaleString(expectedLocale.toString());
+ assertNotNull("When given a bona-fide Locale string, must not return null.", locale);
+ assertEquals(expectedLocale, locale);
+ }
+
+ public void testParseLocaleStringWithMalformedLocaleString() throws Exception {
+ Locale locale = StringUtils.parseLocaleString("_banjo_on_my_knee");
+ assertNotNull("When given a malformed Locale string, must not return null.", locale);
+ }
+
+ public void testParseLocaleStringWithEmptyLocaleStringYieldsNullLocale() throws Exception {
+ Locale locale = StringUtils.parseLocaleString("");
+ assertNull("When given an empty Locale string, must return null.", locale);
+ }
+
+ /**
+ * See SPR-3671.
+ */
+ public void testParseLocaleWithMultiValuedVariant() throws Exception {
+ final String variant = "proper_northern";
+ final String localeString = "en_GB_" + variant;
+ Locale locale = StringUtils.parseLocaleString(localeString);
+ assertEquals("Multi-valued variant portion of the Locale not extracted correctly.", variant, locale.getVariant());
+ }
+
+ /**
+ * See SPR-3671.
+ */
+ public void testParseLocaleWithMultiValuedVariantUsingSpacesAsSeparators() throws Exception {
+ final String variant = "proper northern";
+ final String localeString = "en GB " + variant;
+ Locale locale = StringUtils.parseLocaleString(localeString);
+ assertEquals("Multi-valued variant portion of the Locale not extracted correctly.", variant, locale.getVariant());
+ }
+
+ /**
+ * See SPR-3671.
+ */
+ public void testParseLocaleWithMultiValuedVariantUsingMixtureOfUnderscoresAndSpacesAsSeparators() throws Exception {
+ final String variant = "proper northern";
+ final String localeString = "en_GB_" + variant;
+ Locale locale = StringUtils.parseLocaleString(localeString);
+ assertEquals("Multi-valued variant portion of the Locale not extracted correctly.", variant, locale.getVariant());
+ }
+
+ /**
+ * See SPR-3671.
+ */
+ public void testParseLocaleWithMultiValuedVariantUsingSpacesAsSeparatorsWithLotsOfLeadingWhitespace() throws Exception {
+ final String variant = "proper northern";
+ final String localeString = "en GB " + variant; // lots of whitespace
+ Locale locale = StringUtils.parseLocaleString(localeString);
+ assertEquals("Multi-valued variant portion of the Locale not extracted correctly.", variant, locale.getVariant());
+ }
+
+ /**
+ * See SPR-3671.
+ */
+ public void testParseLocaleWithMultiValuedVariantUsingUnderscoresAsSeparatorsWithLotsOfLeadingWhitespace() throws Exception {
+ final String variant = "proper_northern";
+ final String localeString = "en_GB_____" + variant; // lots of underscores
+ Locale locale = StringUtils.parseLocaleString(localeString);
+ assertEquals("Multi-valued variant portion of the Locale not extracted correctly.", variant, locale.getVariant());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/comparator/ComparatorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/util/comparator/ComparatorTests.java
new file mode 100644
index 00000000000..94cb6433b04
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/comparator/ComparatorTests.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.util.comparator;
+
+import java.util.Comparator;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.support.PropertyComparator;
+
+/**
+ * @author Keith Donald
+ */
+public class ComparatorTests extends TestCase {
+
+ public void testComparableComparator() {
+ Comparator c = new ComparableComparator();
+ String s1 = "abc";
+ String s2 = "cde";
+ assertTrue(c.compare(s1, s2) < 0);
+ }
+
+ public void testComparableComparatorIllegalArgs() {
+ Comparator c = new ComparableComparator();
+ Object o1 = new Object();
+ Object o2 = new Object();
+ try {
+ c.compare(o1, o2);
+ }
+ catch (IllegalArgumentException e) {
+ return;
+ }
+ fail("Comparator should have thrown a cce");
+ }
+
+ public void testBooleanComparatorTrueLow() {
+ Comparator c = BooleanComparator.TRUE_LOW;
+ assertTrue(c.compare(new Boolean(true), new Boolean(false)) < 0);
+ }
+
+ public void testBooleanComparatorTrueHigh() {
+ Comparator c = BooleanComparator.TRUE_HIGH;
+ assertTrue(c.compare(new Boolean(true), new Boolean(false)) > 0);
+ assertTrue(c.compare(Boolean.TRUE, Boolean.TRUE) == 0);
+ }
+
+ public void testPropertyComparator() {
+ Dog dog = new Dog();
+ dog.setNickName("mace");
+
+ Dog dog2 = new Dog();
+ dog2.setNickName("biscy");
+
+ PropertyComparator c = new PropertyComparator("nickName", false, true);
+ assertTrue(c.compare(dog, dog2) > 0);
+ assertTrue(c.compare(dog, dog) == 0);
+ assertTrue(c.compare(dog2, dog) < 0);
+ }
+
+ public void testPropertyComparatorNulls() {
+ Dog dog = new Dog();
+ Dog dog2 = new Dog();
+ PropertyComparator c = new PropertyComparator("nickName", false, true);
+ assertTrue(c.compare(dog, dog2) == 0);
+ }
+
+ public void testNullSafeComparatorNullsLow() {
+ Comparator c = NullSafeComparator.NULLS_LOW;
+ assertTrue(c.compare(null, "boo") < 0);
+ }
+
+ public void testNullSafeComparatorNullsHigh() {
+ Comparator c = NullSafeComparator.NULLS_HIGH;
+ assertTrue(c.compare(null, "boo") > 0);
+ assertTrue(c.compare(null, null) == 0);
+ }
+
+ public void testCompoundComparatorEmpty() {
+ Comparator c = new CompoundComparator();
+ try {
+ c.compare("foo", "bar");
+ }
+ catch (IllegalStateException e) {
+ return;
+ }
+ fail("illegal state should've been thrown on empty list");
+ }
+
+ public void testCompoundComparator() {
+ CompoundComparator c = new CompoundComparator();
+ c.addComparator(new PropertyComparator("lastName", false, true));
+
+ Dog dog1 = new Dog();
+ dog1.setFirstName("macy");
+ dog1.setLastName("grayspots");
+
+ Dog dog2 = new Dog();
+ dog2.setFirstName("biscuit");
+ dog2.setLastName("grayspots");
+
+ assertTrue(c.compare(dog1, dog2) == 0);
+
+ c.addComparator(new PropertyComparator("firstName", false, true));
+ assertTrue(c.compare(dog1, dog2) > 0);
+
+ dog2.setLastName("konikk dog");
+ assertTrue(c.compare(dog2, dog1) > 0);
+ }
+
+ public void testCompoundComparatorInvert() {
+ CompoundComparator c = new CompoundComparator();
+ c.addComparator(new PropertyComparator("lastName", false, true));
+ c.addComparator(new PropertyComparator("firstName", false, true));
+ Dog dog1 = new Dog();
+ dog1.setFirstName("macy");
+ dog1.setLastName("grayspots");
+
+ Dog dog2 = new Dog();
+ dog2.setFirstName("biscuit");
+ dog2.setLastName("grayspots");
+
+ assertTrue(c.compare(dog1, dog2) > 0);
+ c.invertOrder();
+ assertTrue(c.compare(dog1, dog2) < 0);
+ }
+
+
+ private static class Dog implements Comparable {
+
+ private String nickName;
+
+ private String firstName;
+
+ private String lastName;
+
+ public int compareTo(Object o) {
+ return nickName.compareTo(((Dog)o).nickName);
+ }
+
+ public String getNickName() {
+ return nickName;
+ }
+
+ public void setNickName(String nickName) {
+ this.nickName = nickName;
+ }
+
+ 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;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/testlog4j.properties b/org.springframework.testsuite/src/test/java/org/springframework/util/testlog4j.properties
new file mode 100644
index 00000000000..15d9af5a58b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/testlog4j.properties
@@ -0,0 +1,2 @@
+log4j.rootCategory=DEBUG, mock
+log4j.appender.mock=org.springframework.util.MockLog4jAppender
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/util/xml/TransformerUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/util/xml/TransformerUtilsTests.java
new file mode 100644
index 00000000000..caf687537d1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/util/xml/TransformerUtilsTests.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.util.xml;
+
+import java.util.Properties;
+
+import javax.xml.transform.ErrorListener;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.URIResolver;
+
+import junit.framework.TestCase;
+
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Rick Evans
+ */
+public class TransformerUtilsTests extends TestCase {
+
+ public void testEnableIndentingSunnyDay() throws Exception {
+ Transformer transformer = new StubTransformer();
+ TransformerUtils.enableIndenting(transformer);
+ String indent = transformer.getOutputProperty(OutputKeys.INDENT);
+ assertNotNull(indent);
+ assertEquals("yes", indent);
+ String indentAmount = transformer.getOutputProperty("{http://xml.apache.org/xslt}indent-amount");
+ assertNotNull(indentAmount);
+ assertEquals(String.valueOf(TransformerUtils.DEFAULT_INDENT_AMOUNT), indentAmount);
+ }
+
+ public void testEnableIndentingSunnyDayWithCustomKosherIndentAmount() throws Exception {
+ final String indentAmountProperty = "10";
+ Transformer transformer = new StubTransformer();
+ TransformerUtils.enableIndenting(transformer, Integer.valueOf(indentAmountProperty).intValue());
+ String indent = transformer.getOutputProperty(OutputKeys.INDENT);
+ assertNotNull(indent);
+ assertEquals("yes", indent);
+ String indentAmount = transformer.getOutputProperty("{http://xml.apache.org/xslt}indent-amount");
+ assertNotNull(indentAmount);
+ assertEquals(indentAmountProperty, indentAmount);
+ }
+
+ public void testDisableIndentingSunnyDay() throws Exception {
+ Transformer transformer = new StubTransformer();
+ TransformerUtils.disableIndenting(transformer);
+ String indent = transformer.getOutputProperty(OutputKeys.INDENT);
+ assertNotNull(indent);
+ assertEquals("no", indent);
+ }
+
+ public void testEnableIndentingWithNullTransformer() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ TransformerUtils.enableIndenting(null);
+ }
+ }.runTest();
+ }
+
+ public void testDisableIndentingWithNullTransformer() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ TransformerUtils.disableIndenting(null);
+ }
+ }.runTest();
+ }
+
+ public void testEnableIndentingWithNegativeIndentAmount() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ TransformerUtils.enableIndenting(new StubTransformer(), -21938);
+ }
+ }.runTest();
+ }
+
+ public void testEnableIndentingWithZeroIndentAmount() throws Exception {
+ TransformerUtils.enableIndenting(new StubTransformer(), 0);
+ }
+
+
+ private static class StubTransformer extends Transformer {
+
+ private Properties outputProperties = new Properties();
+
+ public void transform(Source xmlSource, Result outputTarget) throws TransformerException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setParameter(String name, Object value) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object getParameter(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void clearParameters() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setURIResolver(URIResolver resolver) {
+ throw new UnsupportedOperationException();
+ }
+
+ public URIResolver getURIResolver() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setOutputProperties(Properties oformat) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Properties getOutputProperties() {
+ return this.outputProperties;
+ }
+
+ public void setOutputProperty(String name, String value) throws IllegalArgumentException {
+ this.outputProperties.setProperty(name, value);
+ }
+
+ public String getOutputProperty(String name) throws IllegalArgumentException {
+ return this.outputProperties.getProperty(name);
+ }
+
+ public void setErrorListener(ErrorListener listener) throws IllegalArgumentException {
+ throw new UnsupportedOperationException();
+ }
+
+ public ErrorListener getErrorListener() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/validation/DataBinderFieldAccessTests.java b/org.springframework.testsuite/src/test/java/org/springframework/validation/DataBinderFieldAccessTests.java
new file mode 100644
index 00000000000..4eceff3d8a7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/validation/DataBinderFieldAccessTests.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.validation;
+
+import java.beans.PropertyEditorSupport;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.FieldAccessBean;
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.NotWritablePropertyException;
+import org.springframework.beans.PropertyValue;
+import org.springframework.beans.TestBean;
+
+/**
+ * @author Juergen Hoeller
+ * @since 07.03.2006
+ */
+public class DataBinderFieldAccessTests extends TestCase {
+
+ public void testBindingNoErrors() throws Exception {
+ FieldAccessBean rod = new FieldAccessBean();
+ DataBinder binder = new DataBinder(rod, "person");
+ assertTrue(binder.isIgnoreUnknownFields());
+ binder.initDirectFieldAccess();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue(new PropertyValue("name", "Rod"));
+ pvs.addPropertyValue(new PropertyValue("age", new Integer(32)));
+ pvs.addPropertyValue(new PropertyValue("nonExisting", "someValue"));
+
+ binder.bind(pvs);
+ binder.close();
+
+ assertTrue("changed name correctly", rod.getName().equals("Rod"));
+ assertTrue("changed age correctly", rod.getAge() == 32);
+
+ Map m = binder.getBindingResult().getModel();
+ assertTrue("There is one element in map", m.size() == 2);
+ FieldAccessBean tb = (FieldAccessBean) m.get("person");
+ assertTrue("Same object", tb.equals(rod));
+ }
+
+ public void testBindingNoErrorsNotIgnoreUnknown() throws Exception {
+ FieldAccessBean rod = new FieldAccessBean();
+ DataBinder binder = new DataBinder(rod, "person");
+ binder.initDirectFieldAccess();
+ binder.setIgnoreUnknownFields(false);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue(new PropertyValue("name", "Rod"));
+ pvs.addPropertyValue(new PropertyValue("age", new Integer(32)));
+ pvs.addPropertyValue(new PropertyValue("nonExisting", "someValue"));
+
+ try {
+ binder.bind(pvs);
+ fail("Should have thrown NotWritablePropertyException");
+ }
+ catch (NotWritablePropertyException ex) {
+ // expected
+ }
+ }
+
+ public void testBindingWithErrors() throws Exception {
+ FieldAccessBean rod = new FieldAccessBean();
+ DataBinder binder = new DataBinder(rod, "person");
+ binder.initDirectFieldAccess();
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue(new PropertyValue("name", "Rod"));
+ pvs.addPropertyValue(new PropertyValue("age", "32x"));
+ binder.bind(pvs);
+
+ try {
+ binder.close();
+ fail("Should have thrown BindException");
+ }
+ catch (BindException ex) {
+ assertTrue("changed name correctly", rod.getName().equals("Rod"));
+ //assertTrue("changed age correctly", rod.getAge() == 32);
+
+ Map map = binder.getBindingResult().getModel();
+ //assertTrue("There are 3 element in map", m.size() == 1);
+ FieldAccessBean tb = (FieldAccessBean) map.get("person");
+ assertTrue("Same object", tb.equals(rod));
+
+ BindingResult br = (BindingResult) map.get(BindingResult.MODEL_KEY_PREFIX + "person");
+ assertTrue("Added itself to map", br == binder.getBindingResult());
+ assertTrue(br.hasErrors());
+ assertTrue("Correct number of errors", br.getErrorCount() == 1);
+
+ assertTrue("Has age errors", br.hasFieldErrors("age"));
+ assertTrue("Correct number of age errors", br.getFieldErrorCount("age") == 1);
+ assertEquals("32x", binder.getBindingResult().getFieldValue("age"));
+ assertEquals("32x", binder.getBindingResult().getFieldError("age").getRejectedValue());
+ assertEquals(0, tb.getAge());
+ }
+ }
+
+ public void testBindingWithErrorsAndCustomEditors() throws Exception {
+ FieldAccessBean rod = new FieldAccessBean();
+ DataBinder binder = new DataBinder(rod, "person");
+ binder.initDirectFieldAccess();
+ binder.registerCustomEditor(TestBean.class, "spouse", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue(new TestBean(text, 0));
+ }
+ public String getAsText() {
+ return ((TestBean) getValue()).getName();
+ }
+ });
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue(new PropertyValue("name", "Rod"));
+ pvs.addPropertyValue(new PropertyValue("age", "32x"));
+ pvs.addPropertyValue(new PropertyValue("spouse", "Kerry"));
+ binder.bind(pvs);
+
+ try {
+ binder.close();
+ fail("Should have thrown BindException");
+ }
+ catch (BindException ex) {
+ assertTrue("changed name correctly", rod.getName().equals("Rod"));
+ //assertTrue("changed age correctly", rod.getAge() == 32);
+
+ Map model = binder.getBindingResult().getModel();
+ //assertTrue("There are 3 element in map", m.size() == 1);
+ FieldAccessBean tb = (FieldAccessBean) model.get("person");
+ assertTrue("Same object", tb.equals(rod));
+
+ BindingResult br = (BindingResult) model.get(BindingResult.MODEL_KEY_PREFIX + "person");
+ assertTrue("Added itself to map", br == binder.getBindingResult());
+ assertTrue(br.hasErrors());
+ assertTrue("Correct number of errors", br.getErrorCount() == 1);
+
+ assertTrue("Has age errors", br.hasFieldErrors("age"));
+ assertTrue("Correct number of age errors", br.getFieldErrorCount("age") == 1);
+ assertEquals("32x", binder.getBindingResult().getFieldValue("age"));
+ assertEquals("32x", binder.getBindingResult().getFieldError("age").getRejectedValue());
+ assertEquals(0, tb.getAge());
+
+ assertTrue("Does not have spouse errors", !br.hasFieldErrors("spouse"));
+ assertEquals("Kerry", binder.getBindingResult().getFieldValue("spouse"));
+ assertNotNull(tb.getSpouse());
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/validation/DataBinderTests.java b/org.springframework.testsuite/src/test/java/org/springframework/validation/DataBinderTests.java
new file mode 100644
index 00000000000..099810ea02b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/validation/DataBinderTests.java
@@ -0,0 +1,1348 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.validation;
+
+import java.beans.PropertyEditorSupport;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.BeanWithObjectProperty;
+import org.springframework.beans.DerivedTestBean;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.IndexedTestBean;
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.NotWritablePropertyException;
+import org.springframework.beans.NullValueInNestedPathException;
+import org.springframework.beans.SerializablePerson;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.propertyeditors.CustomCollectionEditor;
+import org.springframework.beans.propertyeditors.CustomNumberEditor;
+import org.springframework.context.support.ResourceBundleMessageSource;
+import org.springframework.context.support.StaticMessageSource;
+import org.springframework.util.StringUtils;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @author Rob Harrop
+ */
+public class DataBinderTests extends TestCase {
+
+ public void testBindingNoErrors() throws Exception {
+ TestBean rod = new TestBean();
+ DataBinder binder = new DataBinder(rod, "person");
+ assertTrue(binder.isIgnoreUnknownFields());
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "Rod");
+ pvs.addPropertyValue("age", "032");
+ pvs.addPropertyValue("nonExisting", "someValue");
+
+ binder.bind(pvs);
+ binder.close();
+
+ assertTrue("changed name correctly", rod.getName().equals("Rod"));
+ assertTrue("changed age correctly", rod.getAge() == 32);
+
+ Map map = binder.getBindingResult().getModel();
+ assertTrue("There is one element in map", map.size() == 2);
+ TestBean tb = (TestBean) map.get("person");
+ assertTrue("Same object", tb.equals(rod));
+
+ BindingResult other = new BeanPropertyBindingResult(rod, "person");
+ assertEquals(other, binder.getBindingResult());
+ assertEquals(binder.getBindingResult(), other);
+ BindException ex = new BindException(other);
+ assertEquals(ex, other);
+ assertEquals(other, ex);
+ assertEquals(ex, binder.getBindingResult());
+ assertEquals(binder.getBindingResult(), ex);
+
+ other.reject("xxx");
+ assertTrue(!other.equals(binder.getBindingResult()));
+ }
+
+ public void testedBindingWithDefaultConversionNoErrors() throws Exception {
+ TestBean rod = new TestBean();
+ DataBinder binder = new DataBinder(rod, "person");
+ assertTrue(binder.isIgnoreUnknownFields());
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "Rod");
+ pvs.addPropertyValue("jedi", "on");
+
+ binder.bind(pvs);
+ binder.close();
+
+ assertEquals("Rod", rod.getName());
+ assertTrue(rod.isJedi());
+ }
+
+ public void testedNestedBindingWithDefaultConversionNoErrors() throws Exception {
+ TestBean rod = new TestBean(new TestBean());
+ DataBinder binder = new DataBinder(rod, "person");
+ assertTrue(binder.isIgnoreUnknownFields());
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("spouse.name", "Kerry");
+ pvs.addPropertyValue("spouse.jedi", "on");
+
+ binder.bind(pvs);
+ binder.close();
+
+ assertEquals("Kerry", rod.getSpouse().getName());
+ assertTrue(((TestBean) rod.getSpouse()).isJedi());
+ }
+
+ public void testBindingNoErrorsNotIgnoreUnknown() throws Exception {
+ TestBean rod = new TestBean();
+ DataBinder binder = new DataBinder(rod, "person");
+ binder.setIgnoreUnknownFields(false);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "Rod");
+ pvs.addPropertyValue("age", new Integer(32));
+ pvs.addPropertyValue("nonExisting", "someValue");
+
+ try {
+ binder.bind(pvs);
+ fail("Should have thrown NotWritablePropertyException");
+ }
+ catch (NotWritablePropertyException ex) {
+ // expected
+ }
+ }
+
+ public void testBindingNoErrorsWithInvalidField() throws Exception {
+ TestBean rod = new TestBean();
+ DataBinder binder = new DataBinder(rod, "person");
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "Rod");
+ pvs.addPropertyValue("spouse.age", new Integer(32));
+
+ try {
+ binder.bind(pvs);
+ fail("Should have thrown NullValueInNestedPathException");
+ }
+ catch (NullValueInNestedPathException ex) {
+ // expected
+ }
+ }
+
+ public void testBindingNoErrorsWithIgnoreInvalid() throws Exception {
+ TestBean rod = new TestBean();
+ DataBinder binder = new DataBinder(rod, "person");
+ binder.setIgnoreInvalidFields(true);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "Rod");
+ pvs.addPropertyValue("spouse.age", new Integer(32));
+
+ binder.bind(pvs);
+ }
+
+ public void testBindingWithErrors() throws Exception {
+ TestBean rod = new TestBean();
+ DataBinder binder = new DataBinder(rod, "person");
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "Rod");
+ pvs.addPropertyValue("age", "32x");
+ pvs.addPropertyValue("touchy", "m.y");
+ binder.bind(pvs);
+
+ try {
+ binder.close();
+ fail("Should have thrown BindException");
+ }
+ catch (BindException ex) {
+ assertTrue("changed name correctly", rod.getName().equals("Rod"));
+ //assertTrue("changed age correctly", rod.getAge() == 32);
+
+ Map map = binder.getBindingResult().getModel();
+ //assertTrue("There are 3 element in map", m.size() == 1);
+ TestBean tb = (TestBean) map.get("person");
+ assertTrue("Same object", tb.equals(rod));
+
+ BindingResult br = (BindingResult) map.get(BindingResult.MODEL_KEY_PREFIX + "person");
+ assertSame(br, BindingResultUtils.getBindingResult(map, "person"));
+ assertSame(br, BindingResultUtils.getRequiredBindingResult(map, "person"));
+
+ assertNull(BindingResultUtils.getBindingResult(map, "someOtherName"));
+ try {
+ BindingResultUtils.getRequiredBindingResult(map, "someOtherName");
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException expected) {
+ }
+
+ assertTrue("Added itself to map", br == binder.getBindingResult());
+ assertTrue(br.hasErrors());
+ assertTrue("Correct number of errors", br.getErrorCount() == 2);
+
+ assertTrue("Has age errors", br.hasFieldErrors("age"));
+ assertTrue("Correct number of age errors", br.getFieldErrorCount("age") == 1);
+ assertEquals("32x", binder.getBindingResult().getFieldValue("age"));
+ assertEquals("32x", binder.getBindingResult().getFieldError("age").getRejectedValue());
+ assertEquals(0, tb.getAge());
+
+ assertTrue("Has touchy errors", br.hasFieldErrors("touchy"));
+ assertTrue("Correct number of touchy errors", br.getFieldErrorCount("touchy") == 1);
+ assertEquals("m.y", binder.getBindingResult().getFieldValue("touchy"));
+ assertEquals("m.y", binder.getBindingResult().getFieldError("touchy").getRejectedValue());
+ assertNull(tb.getTouchy());
+
+ rod = new TestBean();
+ binder = new DataBinder(rod, "person");
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "Rod");
+ pvs.addPropertyValue("age", "32x");
+ pvs.addPropertyValue("touchy", "m.y");
+ binder.bind(pvs);
+ assertEquals(binder.getBindingResult(), ex.getBindingResult());
+ }
+ }
+
+ public void testBindingWithErrorsAndCustomEditors() throws Exception {
+ TestBean rod = new TestBean();
+ DataBinder binder = new DataBinder(rod, "person");
+ binder.registerCustomEditor(String.class, "touchy", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("prefix_" + text);
+ }
+ public String getAsText() {
+ return getValue().toString().substring(7);
+ }
+ });
+ binder.registerCustomEditor(TestBean.class, "spouse", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue(new TestBean(text, 0));
+ }
+ public String getAsText() {
+ return ((TestBean) getValue()).getName();
+ }
+ });
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "Rod");
+ pvs.addPropertyValue("age", "32x");
+ pvs.addPropertyValue("touchy", "m.y");
+ pvs.addPropertyValue("spouse", "Kerry");
+ binder.bind(pvs);
+
+ try {
+ binder.close();
+ fail("Should have thrown BindException");
+ }
+ catch (BindException ex) {
+ assertTrue("changed name correctly", rod.getName().equals("Rod"));
+ //assertTrue("changed age correctly", rod.getAge() == 32);
+
+ Map model = binder.getBindingResult().getModel();
+ //assertTrue("There are 3 element in map", m.size() == 1);
+ TestBean tb = (TestBean) model.get("person");
+ assertTrue("Same object", tb.equals(rod));
+
+ BindingResult br = (BindingResult) model.get(BindingResult.MODEL_KEY_PREFIX + "person");
+ assertTrue("Added itself to map", br == binder.getBindingResult());
+ assertTrue(br.hasErrors());
+ assertTrue("Correct number of errors", br.getErrorCount() == 2);
+
+ assertTrue("Has age errors", br.hasFieldErrors("age"));
+ assertTrue("Correct number of age errors", br.getFieldErrorCount("age") == 1);
+ assertEquals("32x", binder.getBindingResult().getFieldValue("age"));
+ assertEquals("32x", binder.getBindingResult().getFieldError("age").getRejectedValue());
+ assertEquals(0, tb.getAge());
+
+ assertTrue("Has touchy errors", br.hasFieldErrors("touchy"));
+ assertTrue("Correct number of touchy errors", br.getFieldErrorCount("touchy") == 1);
+ assertEquals("m.y", binder.getBindingResult().getFieldValue("touchy"));
+ assertEquals("m.y", binder.getBindingResult().getFieldError("touchy").getRejectedValue());
+ assertNull(tb.getTouchy());
+
+ assertTrue("Does not have spouse errors", !br.hasFieldErrors("spouse"));
+ assertEquals("Kerry", binder.getBindingResult().getFieldValue("spouse"));
+ assertNotNull(tb.getSpouse());
+ }
+ }
+
+ public void testBindingWithCustomEditorOnObjectField() {
+ BeanWithObjectProperty tb = new BeanWithObjectProperty();
+ DataBinder binder = new DataBinder(tb);
+ binder.registerCustomEditor(Integer.class, "object", new CustomNumberEditor(Integer.class, true));
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("object", "1");
+ binder.bind(pvs);
+ assertEquals(new Integer(1), tb.getObject());
+ }
+
+ public void testBindingWithAllowedFields() throws Exception {
+ TestBean rod = new TestBean();
+ DataBinder binder = new DataBinder(rod);
+ binder.setAllowedFields(new String[] {"name", "myparam"});
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "Rod");
+ pvs.addPropertyValue("age", "32x");
+
+ binder.bind(pvs);
+ binder.close();
+ assertTrue("changed name correctly", rod.getName().equals("Rod"));
+ assertTrue("did not change age", rod.getAge() == 0);
+ }
+
+ public void testBindingWithDisallowedFields() throws Exception {
+ TestBean rod = new TestBean();
+ DataBinder binder = new DataBinder(rod);
+ binder.setDisallowedFields(new String[] {"age"});
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "Rod");
+ pvs.addPropertyValue("age", "32x");
+
+ binder.bind(pvs);
+ binder.close();
+ assertTrue("changed name correctly", rod.getName().equals("Rod"));
+ assertTrue("did not change age", rod.getAge() == 0);
+ String[] disallowedFields = binder.getBindingResult().getSuppressedFields();
+ assertEquals(1, disallowedFields.length);
+ assertEquals("age", disallowedFields[0]);
+ }
+
+ public void testBindingWithAllowedAndDisallowedFields() throws Exception {
+ TestBean rod = new TestBean();
+ DataBinder binder = new DataBinder(rod);
+ binder.setAllowedFields(new String[] {"name", "myparam"});
+ binder.setDisallowedFields(new String[] {"age"});
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "Rod");
+ pvs.addPropertyValue("age", "32x");
+
+ binder.bind(pvs);
+ binder.close();
+ assertTrue("changed name correctly", rod.getName().equals("Rod"));
+ assertTrue("did not change age", rod.getAge() == 0);
+ String[] disallowedFields = binder.getBindingResult().getSuppressedFields();
+ assertEquals(1, disallowedFields.length);
+ assertEquals("age", disallowedFields[0]);
+ }
+
+ public void testBindingWithOverlappingAllowedAndDisallowedFields() throws Exception {
+ TestBean rod = new TestBean();
+ DataBinder binder = new DataBinder(rod);
+ binder.setAllowedFields(new String[] {"name", "age"});
+ binder.setDisallowedFields(new String[] {"age"});
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "Rod");
+ pvs.addPropertyValue("age", "32x");
+
+ binder.bind(pvs);
+ binder.close();
+ assertTrue("changed name correctly", rod.getName().equals("Rod"));
+ assertTrue("did not change age", rod.getAge() == 0);
+ String[] disallowedFields = binder.getBindingResult().getSuppressedFields();
+ assertEquals(1, disallowedFields.length);
+ assertEquals("age", disallowedFields[0]);
+ }
+
+ public void testBindingWithAllowedFieldsUsingAsterisks() throws Exception {
+ TestBean rod = new TestBean();
+ DataBinder binder = new DataBinder(rod, "person");
+ binder.setAllowedFields(new String[] {"nam*", "*ouchy"});
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "Rod");
+ pvs.addPropertyValue("touchy", "Rod");
+ pvs.addPropertyValue("age", "32x");
+
+ binder.bind(pvs);
+ binder.close();
+
+ assertTrue("changed name correctly", "Rod".equals(rod.getName()));
+ assertTrue("changed touchy correctly", "Rod".equals(rod.getTouchy()));
+ assertTrue("did not change age", rod.getAge() == 0);
+ String[] disallowedFields = binder.getBindingResult().getSuppressedFields();
+ assertEquals(1, disallowedFields.length);
+ assertEquals("age", disallowedFields[0]);
+
+ Map m = binder.getBindingResult().getModel();
+ assertTrue("There is one element in map", m.size() == 2);
+ TestBean tb = (TestBean) m.get("person");
+ assertTrue("Same object", tb.equals(rod));
+ }
+
+ public void testBindingWithAllowedAndDisallowedMapFields() throws Exception {
+ TestBean rod = new TestBean();
+ DataBinder binder = new DataBinder(rod);
+ binder.setAllowedFields(new String[] {"someMap[key1]", "someMap[key2]"});
+ binder.setDisallowedFields(new String[] {"someMap['key3']", "someMap[key4]"});
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("someMap[key1]", "value1");
+ pvs.addPropertyValue("someMap['key2']", "value2");
+ pvs.addPropertyValue("someMap[key3]", "value3");
+ pvs.addPropertyValue("someMap['key4']", "value4");
+
+ binder.bind(pvs);
+ binder.close();
+ assertEquals("value1", rod.getSomeMap().get("key1"));
+ assertEquals("value2", rod.getSomeMap().get("key2"));
+ assertNull(rod.getSomeMap().get("key3"));
+ assertNull(rod.getSomeMap().get("key4"));
+ String[] disallowedFields = binder.getBindingResult().getSuppressedFields();
+ assertEquals(2, disallowedFields.length);
+ assertEquals("someMap[key3]", disallowedFields[0]);
+ assertEquals("someMap[key4]", disallowedFields[1]);
+ }
+
+ /**
+ * Tests for required field, both null, non-existing and empty strings.
+ */
+ public void testBindingWithRequiredFields() throws Exception {
+ TestBean tb = new TestBean();
+ tb.setSpouse(new TestBean());
+
+ DataBinder binder = new DataBinder(tb, "person");
+ binder.setRequiredFields(new String[] {"touchy", "name", "age", "date", "spouse.name"});
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("touchy", "");
+ pvs.addPropertyValue("name", null);
+ pvs.addPropertyValue("age", null);
+ pvs.addPropertyValue("spouse.name", " ");
+
+ binder.bind(pvs);
+
+ BindingResult br = binder.getBindingResult();
+ assertEquals("Wrong number of errors", 5, br.getErrorCount());
+
+ assertEquals("required", br.getFieldError("touchy").getCode());
+ assertEquals("", br.getFieldValue("touchy"));
+ assertEquals("required", br.getFieldError("name").getCode());
+ assertEquals("", br.getFieldValue("name"));
+ assertEquals("required", br.getFieldError("age").getCode());
+ assertEquals("", br.getFieldValue("age"));
+ assertEquals("required", br.getFieldError("date").getCode());
+ assertEquals("", br.getFieldValue("date"));
+ assertEquals("required", br.getFieldError("spouse.name").getCode());
+ assertEquals("", br.getFieldValue("spouse.name"));
+ }
+
+ public void testBindingWithRequiredMapFields() throws Exception {
+ TestBean tb = new TestBean();
+ tb.setSpouse(new TestBean());
+
+ DataBinder binder = new DataBinder(tb, "person");
+ binder.setRequiredFields(new String[] {"someMap[key1]", "someMap[key2]", "someMap['key3']", "someMap[key4]"});
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("someMap[key1]", "value1");
+ pvs.addPropertyValue("someMap['key2']", "value2");
+ pvs.addPropertyValue("someMap[key3]", "value3");
+
+ binder.bind(pvs);
+
+ BindingResult br = binder.getBindingResult();
+ assertEquals("Wrong number of errors", 1, br.getErrorCount());
+ assertEquals("required", br.getFieldError("someMap[key4]").getCode());
+ }
+
+ public void testBindingWithNestedObjectCreation() throws Exception {
+ TestBean tb = new TestBean();
+
+ DataBinder binder = new DataBinder(tb, "person");
+ binder.registerCustomEditor(ITestBean.class, new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue(new TestBean());
+ }
+ });
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("spouse", "someValue");
+ pvs.addPropertyValue("spouse.name", "test");
+ binder.bind(pvs);
+
+ assertNotNull(tb.getSpouse());
+ assertEquals("test", tb.getSpouse().getName());
+ }
+
+ public void testCustomEditorForSingleProperty() {
+ TestBean tb = new TestBean();
+ tb.setSpouse(new TestBean());
+ DataBinder binder = new DataBinder(tb, "tb");
+
+ binder.registerCustomEditor(String.class, "name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("prefix" + text);
+ }
+ public String getAsText() {
+ return ((String) getValue()).substring(6);
+ }
+ });
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "value");
+ pvs.addPropertyValue("touchy", "value");
+ pvs.addPropertyValue("spouse.name", "sue");
+ binder.bind(pvs);
+
+ binder.getBindingResult().rejectValue("name", "someCode", "someMessage");
+ binder.getBindingResult().rejectValue("touchy", "someCode", "someMessage");
+ binder.getBindingResult().rejectValue("spouse.name", "someCode", "someMessage");
+
+ assertEquals("", binder.getBindingResult().getNestedPath());
+ assertEquals("value", binder.getBindingResult().getFieldValue("name"));
+ assertEquals("prefixvalue", binder.getBindingResult().getFieldError("name").getRejectedValue());
+ assertEquals("prefixvalue", tb.getName());
+ assertEquals("value", binder.getBindingResult().getFieldValue("touchy"));
+ assertEquals("value", binder.getBindingResult().getFieldError("touchy").getRejectedValue());
+ assertEquals("value", tb.getTouchy());
+
+ assertTrue(binder.getBindingResult().hasFieldErrors("spouse.*"));
+ assertEquals(1, binder.getBindingResult().getFieldErrorCount("spouse.*"));
+ assertEquals("spouse.name", binder.getBindingResult().getFieldError("spouse.*").getField());
+ }
+
+ public void testCustomEditorForPrimitiveProperty() {
+ TestBean tb = new TestBean();
+ DataBinder binder = new DataBinder(tb, "tb");
+
+ binder.registerCustomEditor(int.class, "age", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue(new Integer(99));
+ }
+ public String getAsText() {
+ return "argh";
+ }
+ });
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("age", "");
+ binder.bind(pvs);
+
+ assertEquals("argh", binder.getBindingResult().getFieldValue("age"));
+ assertEquals(99, tb.getAge());
+ }
+
+ public void testCustomEditorForAllStringProperties() {
+ TestBean tb = new TestBean();
+ DataBinder binder = new DataBinder(tb, "tb");
+
+ binder.registerCustomEditor(String.class, null, new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("prefix" + text);
+ }
+ public String getAsText() {
+ return ((String) getValue()).substring(6);
+ }
+ });
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "value");
+ pvs.addPropertyValue("touchy", "value");
+ binder.bind(pvs);
+
+ binder.getBindingResult().rejectValue("name", "someCode", "someMessage");
+ binder.getBindingResult().rejectValue("touchy", "someCode", "someMessage");
+
+ assertEquals("value", binder.getBindingResult().getFieldValue("name"));
+ assertEquals("prefixvalue", binder.getBindingResult().getFieldError("name").getRejectedValue());
+ assertEquals("prefixvalue", tb.getName());
+ assertEquals("value", binder.getBindingResult().getFieldValue("touchy"));
+ assertEquals("prefixvalue", binder.getBindingResult().getFieldError("touchy").getRejectedValue());
+ assertEquals("prefixvalue", tb.getTouchy());
+ }
+
+ public void testCustomEditorWithOldValueAccess() {
+ TestBean tb = new TestBean();
+ DataBinder binder = new DataBinder(tb, "tb");
+
+ binder.registerCustomEditor(String.class, null, new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ if (getValue() == null || !text.equalsIgnoreCase(getValue().toString())) {
+ setValue(text);
+ }
+ }
+ });
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "value");
+ binder.bind(pvs);
+ assertEquals("value", tb.getName());
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("name", "vaLue");
+ binder.bind(pvs);
+ assertEquals("value", tb.getName());
+ }
+
+ public void testValidatorNoErrors() {
+ TestBean tb = new TestBean();
+ tb.setAge(33);
+ tb.setName("Rod");
+ try {
+ tb.setTouchy("Rod");
+ }
+ catch (Exception e) {
+ fail("Should not throw any Exception");
+ }
+ TestBean tb2 = new TestBean();
+ tb2.setAge(34);
+ tb.setSpouse(tb2);
+ DataBinder db = new DataBinder(tb, "tb");
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("spouse.age", "argh");
+ db.bind(pvs);
+ Errors errors = db.getBindingResult();
+ Validator testValidator = new TestBeanValidator();
+ testValidator.validate(tb, errors);
+
+ errors.setNestedPath("spouse");
+ assertEquals("spouse.", errors.getNestedPath());
+ assertEquals("argh", errors.getFieldValue("age"));
+ Validator spouseValidator = new SpouseValidator();
+ spouseValidator.validate(tb.getSpouse(), errors);
+
+ errors.setNestedPath("");
+ assertEquals("", errors.getNestedPath());
+ errors.pushNestedPath("spouse");
+ assertEquals("spouse.", errors.getNestedPath());
+ errors.pushNestedPath("spouse");
+ assertEquals("spouse.spouse.", errors.getNestedPath());
+ errors.popNestedPath();
+ assertEquals("spouse.", errors.getNestedPath());
+ errors.popNestedPath();
+ assertEquals("", errors.getNestedPath());
+ try {
+ errors.popNestedPath();
+ }
+ catch (IllegalStateException ex) {
+ // expected, because stack was empty
+ }
+ errors.pushNestedPath("spouse");
+ assertEquals("spouse.", errors.getNestedPath());
+ errors.setNestedPath("");
+ assertEquals("", errors.getNestedPath());
+ try {
+ errors.popNestedPath();
+ }
+ catch (IllegalStateException ex) {
+ // expected, because stack was reset by setNestedPath
+ }
+
+ errors.pushNestedPath("spouse");
+ assertEquals("spouse.", errors.getNestedPath());
+
+ assertEquals(1, errors.getErrorCount());
+ assertTrue(!errors.hasGlobalErrors());
+ assertEquals(1, errors.getFieldErrorCount("age"));
+ assertTrue(!errors.hasFieldErrors("name"));
+ }
+
+ public void testValidatorWithErrors() {
+ TestBean tb = new TestBean();
+ tb.setSpouse(new TestBean());
+
+ Errors errors = new BeanPropertyBindingResult(tb, "tb");
+
+ Validator testValidator = new TestBeanValidator();
+ testValidator.validate(tb, errors);
+
+ errors.setNestedPath("spouse.");
+ assertEquals("spouse.", errors.getNestedPath());
+ Validator spouseValidator = new SpouseValidator();
+ spouseValidator.validate(tb.getSpouse(), errors);
+
+ errors.setNestedPath("");
+ assertTrue(errors.hasErrors());
+ assertEquals(6, errors.getErrorCount());
+
+ assertEquals(2, errors.getGlobalErrorCount());
+ assertEquals("NAME_TOUCHY_MISMATCH", errors.getGlobalError().getCode());
+ assertEquals("NAME_TOUCHY_MISMATCH", ((ObjectError) errors.getGlobalErrors().get(0)).getCode());
+ assertEquals("NAME_TOUCHY_MISMATCH.tb", ((ObjectError) errors.getGlobalErrors().get(0)).getCodes()[0]);
+ assertEquals("NAME_TOUCHY_MISMATCH", ((ObjectError) errors.getGlobalErrors().get(0)).getCodes()[1]);
+ assertEquals("tb", ((ObjectError) errors.getGlobalErrors().get(0)).getObjectName());
+ assertEquals("GENERAL_ERROR", ((ObjectError) errors.getGlobalErrors().get(1)).getCode());
+ assertEquals("GENERAL_ERROR.tb", ((ObjectError) errors.getGlobalErrors().get(1)).getCodes()[0]);
+ assertEquals("GENERAL_ERROR", ((ObjectError) errors.getGlobalErrors().get(1)).getCodes()[1]);
+ assertEquals("msg", ((ObjectError) errors.getGlobalErrors().get(1)).getDefaultMessage());
+ assertEquals("arg", ((ObjectError) errors.getGlobalErrors().get(1)).getArguments()[0]);
+
+ assertTrue(errors.hasFieldErrors());
+ assertEquals(4, errors.getFieldErrorCount());
+ assertEquals("TOO_YOUNG", errors.getFieldError().getCode());
+ assertEquals("TOO_YOUNG", ((FieldError) errors.getFieldErrors().get(0)).getCode());
+ assertEquals("age", ((FieldError) errors.getFieldErrors().get(0)).getField());
+ assertEquals("AGE_NOT_ODD", ((FieldError) errors.getFieldErrors().get(1)).getCode());
+ assertEquals("age", ((FieldError) errors.getFieldErrors().get(1)).getField());
+ assertEquals("NOT_ROD", ((FieldError) errors.getFieldErrors().get(2)).getCode());
+ assertEquals("name", ((FieldError) errors.getFieldErrors().get(2)).getField());
+ assertEquals("TOO_YOUNG", ((FieldError) errors.getFieldErrors().get(3)).getCode());
+ assertEquals("spouse.age", ((FieldError) errors.getFieldErrors().get(3)).getField());
+
+ assertTrue(errors.hasFieldErrors("age"));
+ assertEquals(2, errors.getFieldErrorCount("age"));
+ assertEquals("TOO_YOUNG", errors.getFieldError("age").getCode());
+ assertEquals("TOO_YOUNG", ((FieldError) errors.getFieldErrors("age").get(0)).getCode());
+ assertEquals("tb", ((FieldError) errors.getFieldErrors("age").get(0)).getObjectName());
+ assertEquals("age", ((FieldError) errors.getFieldErrors("age").get(0)).getField());
+ assertEquals(new Integer(0), ((FieldError) errors.getFieldErrors("age").get(0)).getRejectedValue());
+ assertEquals("AGE_NOT_ODD", ((FieldError) errors.getFieldErrors("age").get(1)).getCode());
+
+ assertTrue(errors.hasFieldErrors("name"));
+ assertEquals(1, errors.getFieldErrorCount("name"));
+ assertEquals("NOT_ROD", errors.getFieldError("name").getCode());
+ assertEquals("NOT_ROD.tb.name", errors.getFieldError("name").getCodes()[0]);
+ assertEquals("NOT_ROD.name", errors.getFieldError("name").getCodes()[1]);
+ assertEquals("NOT_ROD.java.lang.String", errors.getFieldError("name").getCodes()[2]);
+ assertEquals("NOT_ROD", errors.getFieldError("name").getCodes()[3]);
+ assertEquals("name", ((FieldError) errors.getFieldErrors("name").get(0)).getField());
+ assertEquals(null, ((FieldError) errors.getFieldErrors("name").get(0)).getRejectedValue());
+
+ assertTrue(errors.hasFieldErrors("spouse.age"));
+ assertEquals(1, errors.getFieldErrorCount("spouse.age"));
+ assertEquals("TOO_YOUNG", errors.getFieldError("spouse.age").getCode());
+ assertEquals("tb", ((FieldError) errors.getFieldErrors("spouse.age").get(0)).getObjectName());
+ assertEquals(new Integer(0), ((FieldError) errors.getFieldErrors("spouse.age").get(0)).getRejectedValue());
+ }
+
+ public void testValidatorWithErrorsAndCodesPrefix() {
+ TestBean tb = new TestBean();
+ tb.setSpouse(new TestBean());
+
+ BeanPropertyBindingResult errors = new BeanPropertyBindingResult(tb, "tb");
+ DefaultMessageCodesResolver codesResolver = new DefaultMessageCodesResolver();
+ codesResolver.setPrefix("validation.");
+ errors.setMessageCodesResolver(codesResolver);
+
+ Validator testValidator = new TestBeanValidator();
+ testValidator.validate(tb, errors);
+
+ errors.setNestedPath("spouse.");
+ assertEquals("spouse.", errors.getNestedPath());
+ Validator spouseValidator = new SpouseValidator();
+ spouseValidator.validate(tb.getSpouse(), errors);
+
+ errors.setNestedPath("");
+ assertTrue(errors.hasErrors());
+ assertEquals(6, errors.getErrorCount());
+
+ assertEquals(2, errors.getGlobalErrorCount());
+ assertEquals("validation.NAME_TOUCHY_MISMATCH", errors.getGlobalError().getCode());
+ assertEquals("validation.NAME_TOUCHY_MISMATCH", ((ObjectError) errors.getGlobalErrors().get(0)).getCode());
+ assertEquals("validation.NAME_TOUCHY_MISMATCH.tb", ((ObjectError) errors.getGlobalErrors().get(0)).getCodes()[0]);
+ assertEquals("validation.NAME_TOUCHY_MISMATCH", ((ObjectError) errors.getGlobalErrors().get(0)).getCodes()[1]);
+ assertEquals("tb", ((ObjectError) errors.getGlobalErrors().get(0)).getObjectName());
+ assertEquals("validation.GENERAL_ERROR", ((ObjectError) errors.getGlobalErrors().get(1)).getCode());
+ assertEquals("validation.GENERAL_ERROR.tb", ((ObjectError) errors.getGlobalErrors().get(1)).getCodes()[0]);
+ assertEquals("validation.GENERAL_ERROR", ((ObjectError) errors.getGlobalErrors().get(1)).getCodes()[1]);
+ assertEquals("msg", ((ObjectError) errors.getGlobalErrors().get(1)).getDefaultMessage());
+ assertEquals("arg", ((ObjectError) errors.getGlobalErrors().get(1)).getArguments()[0]);
+
+ assertTrue(errors.hasFieldErrors());
+ assertEquals(4, errors.getFieldErrorCount());
+ assertEquals("validation.TOO_YOUNG", errors.getFieldError().getCode());
+ assertEquals("validation.TOO_YOUNG", ((FieldError) errors.getFieldErrors().get(0)).getCode());
+ assertEquals("age", ((FieldError) errors.getFieldErrors().get(0)).getField());
+ assertEquals("validation.AGE_NOT_ODD", ((FieldError) errors.getFieldErrors().get(1)).getCode());
+ assertEquals("age", ((FieldError) errors.getFieldErrors().get(1)).getField());
+ assertEquals("validation.NOT_ROD", ((FieldError) errors.getFieldErrors().get(2)).getCode());
+ assertEquals("name", ((FieldError) errors.getFieldErrors().get(2)).getField());
+ assertEquals("validation.TOO_YOUNG", ((FieldError) errors.getFieldErrors().get(3)).getCode());
+ assertEquals("spouse.age", ((FieldError) errors.getFieldErrors().get(3)).getField());
+
+ assertTrue(errors.hasFieldErrors("age"));
+ assertEquals(2, errors.getFieldErrorCount("age"));
+ assertEquals("validation.TOO_YOUNG", errors.getFieldError("age").getCode());
+ assertEquals("validation.TOO_YOUNG", ((FieldError) errors.getFieldErrors("age").get(0)).getCode());
+ assertEquals("tb", ((FieldError) errors.getFieldErrors("age").get(0)).getObjectName());
+ assertEquals("age", ((FieldError) errors.getFieldErrors("age").get(0)).getField());
+ assertEquals(new Integer(0), ((FieldError) errors.getFieldErrors("age").get(0)).getRejectedValue());
+ assertEquals("validation.AGE_NOT_ODD", ((FieldError) errors.getFieldErrors("age").get(1)).getCode());
+
+ assertTrue(errors.hasFieldErrors("name"));
+ assertEquals(1, errors.getFieldErrorCount("name"));
+ assertEquals("validation.NOT_ROD", errors.getFieldError("name").getCode());
+ assertEquals("validation.NOT_ROD.tb.name", errors.getFieldError("name").getCodes()[0]);
+ assertEquals("validation.NOT_ROD.name", errors.getFieldError("name").getCodes()[1]);
+ assertEquals("validation.NOT_ROD.java.lang.String", errors.getFieldError("name").getCodes()[2]);
+ assertEquals("validation.NOT_ROD", errors.getFieldError("name").getCodes()[3]);
+ assertEquals("name", ((FieldError) errors.getFieldErrors("name").get(0)).getField());
+ assertEquals(null, ((FieldError) errors.getFieldErrors("name").get(0)).getRejectedValue());
+
+ assertTrue(errors.hasFieldErrors("spouse.age"));
+ assertEquals(1, errors.getFieldErrorCount("spouse.age"));
+ assertEquals("validation.TOO_YOUNG", errors.getFieldError("spouse.age").getCode());
+ assertEquals("tb", ((FieldError) errors.getFieldErrors("spouse.age").get(0)).getObjectName());
+ assertEquals(new Integer(0), ((FieldError) errors.getFieldErrors("spouse.age").get(0)).getRejectedValue());
+ }
+
+ public void testValidatorWithNestedObjectNull() {
+ TestBean tb = new TestBean();
+ Errors errors = new BeanPropertyBindingResult(tb, "tb");
+ Validator testValidator = new TestBeanValidator();
+ testValidator.validate(tb, errors);
+ errors.setNestedPath("spouse.");
+ assertEquals("spouse.", errors.getNestedPath());
+ Validator spouseValidator = new SpouseValidator();
+ spouseValidator.validate(tb.getSpouse(), errors);
+ errors.setNestedPath("");
+
+ assertTrue(errors.hasFieldErrors("spouse"));
+ assertEquals(1, errors.getFieldErrorCount("spouse"));
+ assertEquals("SPOUSE_NOT_AVAILABLE", errors.getFieldError("spouse").getCode());
+ assertEquals("tb", ((FieldError) errors.getFieldErrors("spouse").get(0)).getObjectName());
+ assertEquals(null, ((FieldError) errors.getFieldErrors("spouse").get(0)).getRejectedValue());
+ }
+
+ public void testNestedValidatorWithoutNestedPath() {
+ TestBean tb = new TestBean();
+ tb.setName("XXX");
+ Errors errors = new BeanPropertyBindingResult(tb, "tb");
+ Validator spouseValidator = new SpouseValidator();
+ spouseValidator.validate(tb, errors);
+
+ assertTrue(errors.hasGlobalErrors());
+ assertEquals(1, errors.getGlobalErrorCount());
+ assertEquals("SPOUSE_NOT_AVAILABLE", errors.getGlobalError().getCode());
+ assertEquals("tb", ((ObjectError) errors.getGlobalErrors().get(0)).getObjectName());
+ }
+
+ public void testBindingStringArrayToIntegerSet() {
+ IndexedTestBean tb = new IndexedTestBean();
+ DataBinder binder = new DataBinder(tb, "tb");
+ binder.registerCustomEditor(Set.class, new CustomCollectionEditor(TreeSet.class) {
+ protected Object convertElement(Object element) {
+ return new Integer(element.toString());
+ }
+ });
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("set", new String[] {"10", "20", "30"});
+ binder.bind(pvs);
+
+ assertEquals(tb.getSet(), binder.getBindingResult().getFieldValue("set"));
+ assertTrue(tb.getSet() instanceof TreeSet);
+ assertEquals(3, tb.getSet().size());
+ assertTrue(tb.getSet().contains(new Integer(10)));
+ assertTrue(tb.getSet().contains(new Integer(20)));
+ assertTrue(tb.getSet().contains(new Integer(30)));
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("set", null);
+ binder.bind(pvs);
+
+ assertNull(tb.getSet());
+ }
+
+ public void testBindingNullToEmptyCollection() {
+ IndexedTestBean tb = new IndexedTestBean();
+ DataBinder binder = new DataBinder(tb, "tb");
+ binder.registerCustomEditor(Set.class, new CustomCollectionEditor(TreeSet.class, true));
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("set", null);
+ binder.bind(pvs);
+
+ assertTrue(tb.getSet() instanceof TreeSet);
+ assertTrue(tb.getSet().isEmpty());
+ }
+
+ public void testBindingToIndexedField() {
+ IndexedTestBean tb = new IndexedTestBean();
+ DataBinder binder = new DataBinder(tb, "tb");
+ binder.registerCustomEditor(String.class, "array.name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("array" + text);
+ }
+ });
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("array[0]", "a");
+ binder.bind(pvs);
+ Errors errors = binder.getBindingResult();
+ errors.rejectValue("array[0].name", "NOT_ROD", "are you sure you're not Rod?");
+ errors.rejectValue("map[key1].name", "NOT_ROD", "are you sure you're not Rod?");
+
+ assertEquals(1, errors.getFieldErrorCount("array[0].name"));
+ assertEquals("NOT_ROD", errors.getFieldError("array[0].name").getCode());
+ assertEquals("NOT_ROD.tb.array[0].name", errors.getFieldError("array[0].name").getCodes()[0]);
+ assertEquals("NOT_ROD.tb.array.name", errors.getFieldError("array[0].name").getCodes()[1]);
+ assertEquals("NOT_ROD.array[0].name", errors.getFieldError("array[0].name").getCodes()[2]);
+ assertEquals("NOT_ROD.array.name", errors.getFieldError("array[0].name").getCodes()[3]);
+ assertEquals("NOT_ROD.name", errors.getFieldError("array[0].name").getCodes()[4]);
+ assertEquals("NOT_ROD.java.lang.String", errors.getFieldError("array[0].name").getCodes()[5]);
+ assertEquals("NOT_ROD", errors.getFieldError("array[0].name").getCodes()[6]);
+ assertEquals(1, errors.getFieldErrorCount("map[key1].name"));
+ assertEquals(1, errors.getFieldErrorCount("map['key1'].name"));
+ assertEquals(1, errors.getFieldErrorCount("map[\"key1\"].name"));
+ assertEquals("NOT_ROD", errors.getFieldError("map[key1].name").getCode());
+ assertEquals("NOT_ROD.tb.map[key1].name", errors.getFieldError("map[key1].name").getCodes()[0]);
+ assertEquals("NOT_ROD.tb.map.name", errors.getFieldError("map[key1].name").getCodes()[1]);
+ assertEquals("NOT_ROD.map[key1].name", errors.getFieldError("map[key1].name").getCodes()[2]);
+ assertEquals("NOT_ROD.map.name", errors.getFieldError("map[key1].name").getCodes()[3]);
+ assertEquals("NOT_ROD.name", errors.getFieldError("map[key1].name").getCodes()[4]);
+ assertEquals("NOT_ROD.java.lang.String", errors.getFieldError("map[key1].name").getCodes()[5]);
+ assertEquals("NOT_ROD", errors.getFieldError("map[key1].name").getCodes()[6]);
+ }
+
+ public void testBindingToNestedIndexedField() {
+ IndexedTestBean tb = new IndexedTestBean();
+ tb.getArray()[0].setNestedIndexedBean(new IndexedTestBean());
+ tb.getArray()[1].setNestedIndexedBean(new IndexedTestBean());
+ DataBinder binder = new DataBinder(tb, "tb");
+ binder.registerCustomEditor(String.class, "array.nestedIndexedBean.list.name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("list" + text);
+ }
+ });
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("array[0].nestedIndexedBean.list[0].name", "a");
+ binder.bind(pvs);
+ Errors errors = binder.getBindingResult();
+ errors.rejectValue("array[0].nestedIndexedBean.list[0].name", "NOT_ROD", "are you sure you're not Rod?");
+
+ assertEquals(1, errors.getFieldErrorCount("array[0].nestedIndexedBean.list[0].name"));
+ assertEquals("NOT_ROD", errors.getFieldError("array[0].nestedIndexedBean.list[0].name").getCode());
+ assertEquals("NOT_ROD.tb.array[0].nestedIndexedBean.list[0].name",
+ errors.getFieldError("array[0].nestedIndexedBean.list[0].name").getCodes()[0]);
+ assertEquals("NOT_ROD.tb.array[0].nestedIndexedBean.list.name",
+ errors.getFieldError("array[0].nestedIndexedBean.list[0].name").getCodes()[1]);
+ assertEquals("NOT_ROD.tb.array.nestedIndexedBean.list.name",
+ errors.getFieldError("array[0].nestedIndexedBean.list[0].name").getCodes()[2]);
+ assertEquals("NOT_ROD.array[0].nestedIndexedBean.list[0].name",
+ errors.getFieldError("array[0].nestedIndexedBean.list[0].name").getCodes()[3]);
+ assertEquals("NOT_ROD.array[0].nestedIndexedBean.list.name",
+ errors.getFieldError("array[0].nestedIndexedBean.list[0].name").getCodes()[4]);
+ assertEquals("NOT_ROD.array.nestedIndexedBean.list.name",
+ errors.getFieldError("array[0].nestedIndexedBean.list[0].name").getCodes()[5]);
+ assertEquals("NOT_ROD.name", errors.getFieldError("array[0].nestedIndexedBean.list[0].name").getCodes()[6]);
+ assertEquals("NOT_ROD.java.lang.String",
+ errors.getFieldError("array[0].nestedIndexedBean.list[0].name").getCodes()[7]);
+ assertEquals("NOT_ROD", errors.getFieldError("array[0].nestedIndexedBean.list[0].name").getCodes()[8]);
+ }
+
+ public void testEditorForNestedIndexedField() {
+ IndexedTestBean tb = new IndexedTestBean();
+ tb.getArray()[0].setNestedIndexedBean(new IndexedTestBean());
+ tb.getArray()[1].setNestedIndexedBean(new IndexedTestBean());
+ DataBinder binder = new DataBinder(tb, "tb");
+ binder.registerCustomEditor(String.class, "array.nestedIndexedBean.list.name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("list" + text);
+ }
+ public String getAsText() {
+ return ((String) getValue()).substring(4);
+ }
+ });
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("array[0].nestedIndexedBean.list[0].name", "test1");
+ pvs.addPropertyValue("array[1].nestedIndexedBean.list[1].name", "test2");
+ binder.bind(pvs);
+ assertEquals("listtest1", ((TestBean) tb.getArray()[0].getNestedIndexedBean().getList().get(0)).getName());
+ assertEquals("listtest2", ((TestBean) tb.getArray()[1].getNestedIndexedBean().getList().get(1)).getName());
+ assertEquals("test1", binder.getBindingResult().getFieldValue("array[0].nestedIndexedBean.list[0].name"));
+ assertEquals("test2", binder.getBindingResult().getFieldValue("array[1].nestedIndexedBean.list[1].name"));
+ }
+
+ public void testSpecificEditorForNestedIndexedField() {
+ IndexedTestBean tb = new IndexedTestBean();
+ tb.getArray()[0].setNestedIndexedBean(new IndexedTestBean());
+ tb.getArray()[1].setNestedIndexedBean(new IndexedTestBean());
+ DataBinder binder = new DataBinder(tb, "tb");
+ binder.registerCustomEditor(String.class, "array[0].nestedIndexedBean.list.name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("list" + text);
+ }
+ public String getAsText() {
+ return ((String) getValue()).substring(4);
+ }
+ });
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("array[0].nestedIndexedBean.list[0].name", "test1");
+ pvs.addPropertyValue("array[1].nestedIndexedBean.list[1].name", "test2");
+ binder.bind(pvs);
+ assertEquals("listtest1", ((TestBean) tb.getArray()[0].getNestedIndexedBean().getList().get(0)).getName());
+ assertEquals("test2", ((TestBean) tb.getArray()[1].getNestedIndexedBean().getList().get(1)).getName());
+ assertEquals("test1", binder.getBindingResult().getFieldValue("array[0].nestedIndexedBean.list[0].name"));
+ assertEquals("test2", binder.getBindingResult().getFieldValue("array[1].nestedIndexedBean.list[1].name"));
+ }
+
+ public void testInnerSpecificEditorForNestedIndexedField() {
+ IndexedTestBean tb = new IndexedTestBean();
+ tb.getArray()[0].setNestedIndexedBean(new IndexedTestBean());
+ tb.getArray()[1].setNestedIndexedBean(new IndexedTestBean());
+ DataBinder binder = new DataBinder(tb, "tb");
+ binder.registerCustomEditor(String.class, "array.nestedIndexedBean.list[0].name", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("list" + text);
+ }
+ public String getAsText() {
+ return ((String) getValue()).substring(4);
+ }
+ });
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("array[0].nestedIndexedBean.list[0].name", "test1");
+ pvs.addPropertyValue("array[1].nestedIndexedBean.list[1].name", "test2");
+ binder.bind(pvs);
+ assertEquals("listtest1", ((TestBean) tb.getArray()[0].getNestedIndexedBean().getList().get(0)).getName());
+ assertEquals("test2", ((TestBean) tb.getArray()[1].getNestedIndexedBean().getList().get(1)).getName());
+ assertEquals("test1", binder.getBindingResult().getFieldValue("array[0].nestedIndexedBean.list[0].name"));
+ assertEquals("test2", binder.getBindingResult().getFieldValue("array[1].nestedIndexedBean.list[1].name"));
+ }
+
+ public void testDirectBindingToIndexedField() {
+ IndexedTestBean tb = new IndexedTestBean();
+ DataBinder binder = new DataBinder(tb, "tb");
+ binder.registerCustomEditor(TestBean.class, "array", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ DerivedTestBean tb = new DerivedTestBean();
+ tb.setName("array" + text);
+ setValue(tb);
+ }
+ public String getAsText() {
+ return ((TestBean) getValue()).getName();
+ }
+ });
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("array[0]", "a");
+ binder.bind(pvs);
+ Errors errors = binder.getBindingResult();
+ errors.rejectValue("array[0]", "NOT_ROD", "are you sure you're not Rod?");
+ errors.rejectValue("map[key1]", "NOT_ROD", "are you sure you're not Rod?");
+ errors.rejectValue("map[key0]", "NOT_NULL", "should not be null");
+
+ assertEquals("arraya", errors.getFieldValue("array[0]"));
+ assertEquals(1, errors.getFieldErrorCount("array[0]"));
+ assertEquals("NOT_ROD", errors.getFieldError("array[0]").getCode());
+ assertEquals("NOT_ROD.tb.array[0]", errors.getFieldError("array[0]").getCodes()[0]);
+ assertEquals("NOT_ROD.tb.array", errors.getFieldError("array[0]").getCodes()[1]);
+ assertEquals("NOT_ROD.array[0]", errors.getFieldError("array[0]").getCodes()[2]);
+ assertEquals("NOT_ROD.array", errors.getFieldError("array[0]").getCodes()[3]);
+ assertEquals("NOT_ROD.org.springframework.beans.DerivedTestBean", errors.getFieldError("array[0]").getCodes()[4]);
+ assertEquals("NOT_ROD", errors.getFieldError("array[0]").getCodes()[5]);
+ assertEquals("arraya", errors.getFieldValue("array[0]"));
+
+ assertEquals(1, errors.getFieldErrorCount("map[key1]"));
+ assertEquals("NOT_ROD", errors.getFieldError("map[key1]").getCode());
+ assertEquals("NOT_ROD.tb.map[key1]", errors.getFieldError("map[key1]").getCodes()[0]);
+ assertEquals("NOT_ROD.tb.map", errors.getFieldError("map[key1]").getCodes()[1]);
+ assertEquals("NOT_ROD.map[key1]", errors.getFieldError("map[key1]").getCodes()[2]);
+ assertEquals("NOT_ROD.map", errors.getFieldError("map[key1]").getCodes()[3]);
+ assertEquals("NOT_ROD.org.springframework.beans.TestBean", errors.getFieldError("map[key1]").getCodes()[4]);
+ assertEquals("NOT_ROD", errors.getFieldError("map[key1]").getCodes()[5]);
+
+ assertEquals(1, errors.getFieldErrorCount("map[key0]"));
+ assertEquals("NOT_NULL", errors.getFieldError("map[key0]").getCode());
+ assertEquals("NOT_NULL.tb.map[key0]", errors.getFieldError("map[key0]").getCodes()[0]);
+ assertEquals("NOT_NULL.tb.map", errors.getFieldError("map[key0]").getCodes()[1]);
+ assertEquals("NOT_NULL.map[key0]", errors.getFieldError("map[key0]").getCodes()[2]);
+ assertEquals("NOT_NULL.map", errors.getFieldError("map[key0]").getCodes()[3]);
+ assertEquals("NOT_NULL", errors.getFieldError("map[key0]").getCodes()[4]);
+ }
+
+ public void testDirectBindingToEmptyIndexedFieldWithRegisteredSpecificEditor() {
+ IndexedTestBean tb = new IndexedTestBean();
+ DataBinder binder = new DataBinder(tb, "tb");
+ binder.registerCustomEditor(TestBean.class, "map[key0]", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ DerivedTestBean tb = new DerivedTestBean();
+ tb.setName("array" + text);
+ setValue(tb);
+ }
+ public String getAsText() {
+ return ((TestBean) getValue()).getName();
+ }
+ });
+ Errors errors = binder.getBindingResult();
+ errors.rejectValue("map[key0]", "NOT_NULL", "should not be null");
+
+ assertEquals(1, errors.getFieldErrorCount("map[key0]"));
+ assertEquals("NOT_NULL", errors.getFieldError("map[key0]").getCode());
+ assertEquals("NOT_NULL.tb.map[key0]", errors.getFieldError("map[key0]").getCodes()[0]);
+ assertEquals("NOT_NULL.tb.map", errors.getFieldError("map[key0]").getCodes()[1]);
+ assertEquals("NOT_NULL.map[key0]", errors.getFieldError("map[key0]").getCodes()[2]);
+ assertEquals("NOT_NULL.map", errors.getFieldError("map[key0]").getCodes()[3]);
+ // This next code is only generated because of the registered editor, using the
+ // registered type of the editor as guess for the content type of the collection.
+ assertEquals("NOT_NULL.org.springframework.beans.TestBean", errors.getFieldError("map[key0]").getCodes()[4]);
+ assertEquals("NOT_NULL", errors.getFieldError("map[key0]").getCodes()[5]);
+ }
+
+ public void testDirectBindingToEmptyIndexedFieldWithRegisteredGenericEditor() {
+ IndexedTestBean tb = new IndexedTestBean();
+ DataBinder binder = new DataBinder(tb, "tb");
+ binder.registerCustomEditor(TestBean.class, "map", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ DerivedTestBean tb = new DerivedTestBean();
+ tb.setName("array" + text);
+ setValue(tb);
+ }
+ public String getAsText() {
+ return ((TestBean) getValue()).getName();
+ }
+ });
+ Errors errors = binder.getBindingResult();
+ errors.rejectValue("map[key0]", "NOT_NULL", "should not be null");
+
+ assertEquals(1, errors.getFieldErrorCount("map[key0]"));
+ assertEquals("NOT_NULL", errors.getFieldError("map[key0]").getCode());
+ assertEquals("NOT_NULL.tb.map[key0]", errors.getFieldError("map[key0]").getCodes()[0]);
+ assertEquals("NOT_NULL.tb.map", errors.getFieldError("map[key0]").getCodes()[1]);
+ assertEquals("NOT_NULL.map[key0]", errors.getFieldError("map[key0]").getCodes()[2]);
+ assertEquals("NOT_NULL.map", errors.getFieldError("map[key0]").getCodes()[3]);
+ // This next code is only generated because of the registered editor, using the
+ // registered type of the editor as guess for the content type of the collection.
+ assertEquals("NOT_NULL.org.springframework.beans.TestBean", errors.getFieldError("map[key0]").getCodes()[4]);
+ assertEquals("NOT_NULL", errors.getFieldError("map[key0]").getCodes()[5]);
+ }
+
+ public void testCustomEditorWithSubclass() {
+ IndexedTestBean tb = new IndexedTestBean();
+ DataBinder binder = new DataBinder(tb, "tb");
+ binder.registerCustomEditor(TestBean.class, new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ DerivedTestBean tb = new DerivedTestBean();
+ tb.setName("array" + text);
+ setValue(tb);
+ }
+ public String getAsText() {
+ return ((TestBean) getValue()).getName();
+ }
+ });
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("array[0]", "a");
+ binder.bind(pvs);
+ Errors errors = binder.getBindingResult();
+ errors.rejectValue("array[0]", "NOT_ROD", "are you sure you're not Rod?");
+
+ assertEquals("arraya", errors.getFieldValue("array[0]"));
+ assertEquals(1, errors.getFieldErrorCount("array[0]"));
+ assertEquals("NOT_ROD", errors.getFieldError("array[0]").getCode());
+ assertEquals("NOT_ROD.tb.array[0]", errors.getFieldError("array[0]").getCodes()[0]);
+ assertEquals("NOT_ROD.tb.array", errors.getFieldError("array[0]").getCodes()[1]);
+ assertEquals("NOT_ROD.array[0]", errors.getFieldError("array[0]").getCodes()[2]);
+ assertEquals("NOT_ROD.array", errors.getFieldError("array[0]").getCodes()[3]);
+ assertEquals("NOT_ROD.org.springframework.beans.DerivedTestBean", errors.getFieldError("array[0]").getCodes()[4]);
+ assertEquals("NOT_ROD", errors.getFieldError("array[0]").getCodes()[5]);
+ assertEquals("arraya", errors.getFieldValue("array[0]"));
+ }
+
+ public void testBindToStringArrayWithArrayEditor() {
+ TestBean tb = new TestBean();
+ DataBinder binder = new DataBinder(tb, "tb");
+ binder.registerCustomEditor(String[].class, "stringArray", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue(StringUtils.delimitedListToStringArray(text, "-"));
+ }
+ });
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("stringArray", "a1-b2");
+ binder.bind(pvs);
+ assertTrue(!binder.getBindingResult().hasErrors());
+ assertEquals(2, tb.getStringArray().length);
+ assertEquals("a1", tb.getStringArray()[0]);
+ assertEquals("b2", tb.getStringArray()[1]);
+ }
+
+ public void testBindToStringArrayWithComponentEditor() {
+ TestBean tb = new TestBean();
+ DataBinder binder = new DataBinder(tb, "tb");
+ binder.registerCustomEditor(String.class, "stringArray", new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue("X" + text);
+ }
+ });
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("stringArray", new String[] {"a1", "b2"});
+ binder.bind(pvs);
+ assertTrue(!binder.getBindingResult().hasErrors());
+ assertEquals(2, tb.getStringArray().length);
+ assertEquals("Xa1", tb.getStringArray()[0]);
+ assertEquals("Xb2", tb.getStringArray()[1]);
+ }
+
+ public void testBindingErrors() {
+ TestBean rod = new TestBean();
+ DataBinder binder = new DataBinder(rod, "person");
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("age", "32x");
+ binder.bind(pvs);
+ Errors errors = binder.getBindingResult();
+ FieldError ageError = errors.getFieldError("age");
+ assertEquals("typeMismatch", ageError.getCode());
+
+ ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
+ messageSource.setBasename("org.springframework.validation.messages1");
+ String msg = messageSource.getMessage(ageError, Locale.getDefault());
+ assertEquals("Field age did not have correct type", msg);
+
+ messageSource = new ResourceBundleMessageSource();
+ messageSource.setBasename("org.springframework.validation.messages2");
+ msg = messageSource.getMessage(ageError, Locale.getDefault());
+ assertEquals("Field Age did not have correct type", msg);
+
+ messageSource = new ResourceBundleMessageSource();
+ messageSource.setBasename("org.springframework.validation.messages3");
+ msg = messageSource.getMessage(ageError, Locale.getDefault());
+ assertEquals("Field Person Age did not have correct type", msg);
+ }
+
+ public void testAddAllErrors() {
+ TestBean rod = new TestBean();
+ DataBinder binder = new DataBinder(rod, "person");
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("age", "32x");
+ binder.bind(pvs);
+ Errors errors = binder.getBindingResult();
+
+ BeanPropertyBindingResult errors2 = new BeanPropertyBindingResult(rod, "person");
+ errors.rejectValue("name", "badName");
+ errors.addAllErrors(errors2);
+
+ FieldError ageError = errors.getFieldError("age");
+ assertEquals("typeMismatch", ageError.getCode());
+ FieldError nameError = errors.getFieldError("name");
+ assertEquals("badName", nameError.getCode());
+ }
+
+ public void testBindingWithResortedList() {
+ IndexedTestBean tb = new IndexedTestBean();
+ DataBinder binder = new DataBinder(tb, "tb");
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ TestBean tb1 = new TestBean("tb1", 99);
+ TestBean tb2 = new TestBean("tb2", 99);
+ pvs.addPropertyValue("list[0]", tb1);
+ pvs.addPropertyValue("list[1]", tb2);
+ binder.bind(pvs);
+ assertEquals(tb1.getName(), binder.getBindingResult().getFieldValue("list[0].name"));
+ assertEquals(tb2.getName(), binder.getBindingResult().getFieldValue("list[1].name"));
+ tb.getList().set(0, tb2);
+ tb.getList().set(1, tb1);
+ assertEquals(tb2.getName(), binder.getBindingResult().getFieldValue("list[0].name"));
+ assertEquals(tb1.getName(), binder.getBindingResult().getFieldValue("list[1].name"));
+ }
+
+ public void testRejectWithoutDefaultMessage() throws Exception {
+ TestBean tb = new TestBean();
+ tb.setName("myName");
+ tb.setAge(99);
+
+ BeanPropertyBindingResult ex = new BeanPropertyBindingResult(tb, "tb");
+ ex.reject("invalid");
+ ex.rejectValue("age", "invalidField");
+
+ StaticMessageSource ms = new StaticMessageSource();
+ ms.addMessage("invalid", Locale.US, "general error");
+ ms.addMessage("invalidField", Locale.US, "invalid field");
+
+ assertEquals("general error", ms.getMessage(ex.getGlobalError(), Locale.US));
+ assertEquals("invalid field", ms.getMessage(ex.getFieldError("age"), Locale.US));
+ }
+
+ public void testBindExceptionSerializable() throws Exception {
+ SerializablePerson tb = new SerializablePerson();
+ tb.setName("myName");
+ tb.setAge(99);
+
+ BindException ex = new BindException(tb, "tb");
+ ex.reject("invalid", "someMessage");
+ ex.rejectValue("age", "invalidField", "someMessage");
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(ex);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ObjectInputStream ois = new ObjectInputStream(bais);
+
+ BindException ex2 = (BindException) ois.readObject();
+ assertTrue(ex2.hasGlobalErrors());
+ assertEquals("invalid", ex2.getGlobalError().getCode());
+ assertTrue(ex2.hasFieldErrors("age"));
+ assertEquals("invalidField", ex2.getFieldError("age").getCode());
+ assertEquals(new Integer(99), ex2.getFieldValue("age"));
+
+ ex2.rejectValue("name", "invalidField", "someMessage");
+ assertTrue(ex2.hasFieldErrors("name"));
+ assertEquals("invalidField", ex2.getFieldError("name").getCode());
+ assertEquals("myName", ex2.getFieldValue("name"));
+ }
+
+ public void testTrackDisallowedFields() throws Exception {
+ TestBean testBean = new TestBean();
+ DataBinder binder = new DataBinder(testBean, "testBean");
+ binder.setAllowedFields(new String[] {"name", "age"});
+
+ String name = "Rob Harrop";
+ String beanName = "foobar";
+
+ MutablePropertyValues mpvs = new MutablePropertyValues();
+ mpvs.addPropertyValue("name", name);
+ mpvs.addPropertyValue("beanName", beanName);
+
+ binder.bind(mpvs);
+
+ assertEquals(name, testBean.getName());
+ String[] disallowedFields = binder.getBindingResult().getSuppressedFields();
+ assertEquals(1, disallowedFields.length);
+ assertEquals("beanName", disallowedFields[0]);
+ }
+
+
+ private static class TestBeanValidator implements Validator {
+
+ public boolean supports(Class clazz) {
+ return TestBean.class.isAssignableFrom(clazz);
+ }
+
+ public void validate(Object obj, Errors errors) {
+ TestBean tb = (TestBean) obj;
+ if (tb.getAge() < 32) {
+ errors.rejectValue("age", "TOO_YOUNG", "simply too young");
+ }
+ if (tb.getAge() % 2 == 0) {
+ errors.rejectValue("age", "AGE_NOT_ODD", "your age isn't odd");
+ }
+ if (tb.getName() == null || !tb.getName().equals("Rod")) {
+ errors.rejectValue("name", "NOT_ROD", "are you sure you're not Rod?");
+ }
+ if (tb.getTouchy() == null || !tb.getTouchy().equals(tb.getName())) {
+ errors.reject("NAME_TOUCHY_MISMATCH", "name and touchy do not match");
+ }
+ if (tb.getAge() == 0) {
+ errors.reject("GENERAL_ERROR", new String[] {"arg"}, "msg");
+ }
+ }
+ }
+
+
+ private static class SpouseValidator implements Validator {
+
+ public boolean supports(Class clazz) {
+ return TestBean.class.isAssignableFrom(clazz);
+ }
+
+ public void validate(Object obj, Errors errors) {
+ TestBean tb = (TestBean) obj;
+ if (tb == null || "XXX".equals(tb.getName())) {
+ errors.rejectValue("", "SPOUSE_NOT_AVAILABLE");
+ return;
+ }
+ if (tb.getAge() < 32) {
+ errors.rejectValue("age", "TOO_YOUNG", "simply too young");
+ }
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/validation/ValidationUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/validation/ValidationUtilsTests.java
new file mode 100644
index 00000000000..83ad9cb58e5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/validation/ValidationUtilsTests.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.validation;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ * @since 08.10.2004
+ */
+public class ValidationUtilsTests extends TestCase {
+
+ public void testInvokeValidatorWithNullValidator() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ TestBean tb = new TestBean();
+ Errors errors = new BeanPropertyBindingResult(tb, "tb");
+ ValidationUtils.invokeValidator(null, tb, errors);
+ }
+ }.runTest();
+ }
+
+ public void testInvokeValidatorWithNullErrors() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ TestBean tb = new TestBean();
+ ValidationUtils.invokeValidator(new EmptyValidator(), tb, null);
+ }
+ }.runTest();
+ }
+
+ public void testInvokeValidatorSunnyDay() throws Exception {
+ TestBean tb = new TestBean();
+ Errors errors = new BeanPropertyBindingResult(tb, "tb");
+ ValidationUtils.invokeValidator(new EmptyValidator(), tb, errors);
+ assertTrue(errors.hasFieldErrors("name"));
+ assertEquals("EMPTY", errors.getFieldError("name").getCode());
+ }
+
+ public void testValidationUtilsSunnyDay() throws Exception {
+ TestBean tb = new TestBean("");
+
+ Validator testValidator = new EmptyValidator();
+ tb.setName(" ");
+ Errors errors = new BeanPropertyBindingResult(tb, "tb");
+ testValidator.validate(tb, errors);
+ assertFalse(errors.hasFieldErrors("name"));
+
+ tb.setName("Roddy");
+ errors = new BeanPropertyBindingResult(tb, "tb");
+ testValidator.validate(tb, errors);
+ assertFalse(errors.hasFieldErrors("name"));
+ }
+
+ public void testValidationUtilsNull() throws Exception {
+ TestBean tb = new TestBean();
+ Errors errors = new BeanPropertyBindingResult(tb, "tb");
+ Validator testValidator = new EmptyValidator();
+ testValidator.validate(tb, errors);
+ assertTrue(errors.hasFieldErrors("name"));
+ assertEquals("EMPTY", errors.getFieldError("name").getCode());
+ }
+
+ public void testValidationUtilsEmpty() throws Exception {
+ TestBean tb = new TestBean("");
+ Errors errors = new BeanPropertyBindingResult(tb, "tb");
+ Validator testValidator = new EmptyValidator();
+ testValidator.validate(tb, errors);
+ assertTrue(errors.hasFieldErrors("name"));
+ assertEquals("EMPTY", errors.getFieldError("name").getCode());
+ }
+
+ public void testValidationUtilsEmptyVariants() {
+ TestBean tb = new TestBean();
+
+ Errors errors = new BeanPropertyBindingResult(tb, "tb");
+ ValidationUtils.rejectIfEmpty(errors, "name", "EMPTY_OR_WHITESPACE", new Object[] {"arg"});
+ assertTrue(errors.hasFieldErrors("name"));
+ assertEquals("EMPTY_OR_WHITESPACE", errors.getFieldError("name").getCode());
+ assertEquals("arg", errors.getFieldError("name").getArguments()[0]);
+
+ errors = new BeanPropertyBindingResult(tb, "tb");
+ ValidationUtils.rejectIfEmpty(errors, "name", "EMPTY_OR_WHITESPACE", new Object[] {"arg"}, "msg");
+ assertTrue(errors.hasFieldErrors("name"));
+ assertEquals("EMPTY_OR_WHITESPACE", errors.getFieldError("name").getCode());
+ assertEquals("arg", errors.getFieldError("name").getArguments()[0]);
+ assertEquals("msg", errors.getFieldError("name").getDefaultMessage());
+ }
+
+ public void testValidationUtilsEmptyOrWhitespace() throws Exception {
+ TestBean tb = new TestBean();
+ Validator testValidator = new EmptyOrWhitespaceValidator();
+
+ // Test null
+ Errors errors = new BeanPropertyBindingResult(tb, "tb");
+ testValidator.validate(tb, errors);
+ assertTrue(errors.hasFieldErrors("name"));
+ assertEquals("EMPTY_OR_WHITESPACE", errors.getFieldError("name").getCode());
+
+ // Test empty String
+ tb.setName("");
+ errors = new BeanPropertyBindingResult(tb, "tb");
+ testValidator.validate(tb, errors);
+ assertTrue(errors.hasFieldErrors("name"));
+ assertEquals("EMPTY_OR_WHITESPACE", errors.getFieldError("name").getCode());
+
+ // Test whitespace String
+ tb.setName(" ");
+ errors = new BeanPropertyBindingResult(tb, "tb");
+ testValidator.validate(tb, errors);
+ assertTrue(errors.hasFieldErrors("name"));
+ assertEquals("EMPTY_OR_WHITESPACE", errors.getFieldError("name").getCode());
+
+ // Test OK
+ tb.setName("Roddy");
+ errors = new BeanPropertyBindingResult(tb, "tb");
+ testValidator.validate(tb, errors);
+ assertFalse(errors.hasFieldErrors("name"));
+ }
+
+ public void testValidationUtilsEmptyOrWhitespaceVariants() {
+ TestBean tb = new TestBean();
+ tb.setName(" ");
+
+ Errors errors = new BeanPropertyBindingResult(tb, "tb");
+ ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "EMPTY_OR_WHITESPACE", new Object[] {"arg"});
+ assertTrue(errors.hasFieldErrors("name"));
+ assertEquals("EMPTY_OR_WHITESPACE", errors.getFieldError("name").getCode());
+ assertEquals("arg", errors.getFieldError("name").getArguments()[0]);
+
+ errors = new BeanPropertyBindingResult(tb, "tb");
+ ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "EMPTY_OR_WHITESPACE", new Object[] {"arg"}, "msg");
+ assertTrue(errors.hasFieldErrors("name"));
+ assertEquals("EMPTY_OR_WHITESPACE", errors.getFieldError("name").getCode());
+ assertEquals("arg", errors.getFieldError("name").getArguments()[0]);
+ assertEquals("msg", errors.getFieldError("name").getDefaultMessage());
+ }
+
+
+ private static class EmptyValidator implements Validator {
+
+ public boolean supports(Class clazz) {
+ return TestBean.class.isAssignableFrom(clazz);
+ }
+
+ public void validate(Object obj, Errors errors) {
+ ValidationUtils.rejectIfEmpty(errors, "name", "EMPTY", "You must enter a name!");
+ }
+ }
+
+
+ private static class EmptyOrWhitespaceValidator implements Validator {
+
+ public boolean supports(Class clazz) {
+ return TestBean.class.isAssignableFrom(clazz);
+ }
+
+ public void validate(Object obj, Errors errors) {
+ ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "EMPTY_OR_WHITESPACE", "You must enter a name!");
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/validation/messages1.properties b/org.springframework.testsuite/src/test/java/org/springframework/validation/messages1.properties
new file mode 100644
index 00000000000..2b2adb247a7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/validation/messages1.properties
@@ -0,0 +1 @@
+typeMismatch=Field {0} did not have correct type
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/validation/messages2.properties b/org.springframework.testsuite/src/test/java/org/springframework/validation/messages2.properties
new file mode 100644
index 00000000000..69f01910567
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/validation/messages2.properties
@@ -0,0 +1,2 @@
+typeMismatch=Field {0} did not have correct type
+age=Age
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/validation/messages3.properties b/org.springframework.testsuite/src/test/java/org/springframework/validation/messages3.properties
new file mode 100644
index 00000000000..7b829927974
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/validation/messages3.properties
@@ -0,0 +1,2 @@
+typeMismatch=Field {0} did not have correct type
+person.age=Person Age
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/bind/EscapedErrorsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/bind/EscapedErrorsTests.java
new file mode 100644
index 00000000000..a279ceab4b2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/bind/EscapedErrorsTests.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.bind;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+import org.springframework.validation.BindException;
+import org.springframework.validation.Errors;
+import org.springframework.validation.FieldError;
+import org.springframework.validation.ObjectError;
+
+/**
+ * @author Juergen Hoeller
+ * @since 02.05.2003
+ */
+public class EscapedErrorsTests extends TestCase {
+
+ public void testEscapedErrors() {
+ TestBean tb = new TestBean();
+ tb.setName("empty &");
+
+ Errors errors = new EscapedErrors(new BindException(tb, "tb"));
+ errors.rejectValue("name", "NAME_EMPTY &", null, "message: &");
+ errors.rejectValue("age", "AGE_NOT_SET ", null, "message: ");
+ errors.rejectValue("age", "AGE_NOT_32 ", null, "message: ");
+ errors.reject("GENERAL_ERROR \" '", null, "message: \" '");
+
+ assertTrue("Correct errors flag", errors.hasErrors());
+ assertTrue("Correct number of errors", errors.getErrorCount() == 4);
+ assertTrue("Correct object name", "tb".equals(errors.getObjectName()));
+
+ assertTrue("Correct global errors flag", errors.hasGlobalErrors());
+ assertTrue("Correct number of global errors", errors.getGlobalErrorCount() == 1);
+ ObjectError globalError = errors.getGlobalError();
+ assertTrue("Global error message escaped", "message: " '".equals(globalError.getDefaultMessage()));
+ assertTrue("Global error code not escaped", "GENERAL_ERROR \" '".equals(globalError.getCode()));
+ ObjectError globalErrorInList = (ObjectError) errors.getGlobalErrors().get(0);
+ assertTrue("Same global error in list", globalError.getDefaultMessage().equals(globalErrorInList.getDefaultMessage()));
+ ObjectError globalErrorInAllList = (ObjectError) errors.getAllErrors().get(3);
+ assertTrue("Same global error in list", globalError.getDefaultMessage().equals(globalErrorInAllList.getDefaultMessage()));
+
+ assertTrue("Correct field errors flag", errors.hasFieldErrors());
+ assertTrue("Correct number of field errors", errors.getFieldErrorCount() == 3);
+ assertTrue("Correct number of field errors in list", errors.getFieldErrors().size() == 3);
+ FieldError fieldError = errors.getFieldError();
+ assertTrue("Field error code not escaped", "NAME_EMPTY &".equals(fieldError.getCode()));
+ assertTrue("Field value escaped", "empty &".equals(errors.getFieldValue("name")));
+ FieldError fieldErrorInList = (FieldError) errors.getFieldErrors().get(0);
+ assertTrue("Same field error in list", fieldError.getDefaultMessage().equals(fieldErrorInList.getDefaultMessage()));
+
+ assertTrue("Correct name errors flag", errors.hasFieldErrors("name"));
+ assertTrue("Correct number of name errors", errors.getFieldErrorCount("name") == 1);
+ assertTrue("Correct number of name errors in list", errors.getFieldErrors("name").size() == 1);
+ FieldError nameError = errors.getFieldError("name");
+ assertTrue("Name error message escaped", "message: &".equals(nameError.getDefaultMessage()));
+ assertTrue("Name error code not escaped", "NAME_EMPTY &".equals(nameError.getCode()));
+ assertTrue("Name value escaped", "empty &".equals(errors.getFieldValue("name")));
+ FieldError nameErrorInList = (FieldError) errors.getFieldErrors("name").get(0);
+ assertTrue("Same name error in list", nameError.getDefaultMessage().equals(nameErrorInList.getDefaultMessage()));
+
+ assertTrue("Correct age errors flag", errors.hasFieldErrors("age"));
+ assertTrue("Correct number of age errors", errors.getFieldErrorCount("age") == 2);
+ assertTrue("Correct number of age errors in list", errors.getFieldErrors("age").size() == 2);
+ FieldError ageError = errors.getFieldError("age");
+ assertTrue("Age error message escaped", "message: <tag>".equals(ageError.getDefaultMessage()));
+ assertTrue("Age error code not escaped", "AGE_NOT_SET ".equals(ageError.getCode()));
+ assertTrue("Age value not escaped", (new Integer(0)).equals(errors.getFieldValue("age")));
+ FieldError ageErrorInList = (FieldError) errors.getFieldErrors("age").get(0);
+ assertTrue("Same name error in list", ageError.getDefaultMessage().equals(ageErrorInList.getDefaultMessage()));
+ FieldError ageError2 = (FieldError) errors.getFieldErrors("age").get(1);
+ assertTrue("Age error 2 message escaped", "message: <tag>".equals(ageError2.getDefaultMessage()));
+ assertTrue("Age error 2 code not escaped", "AGE_NOT_32 ".equals(ageError2.getCode()));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/bind/RequestUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/bind/RequestUtilsTests.java
new file mode 100644
index 00000000000..f2569f8bea3
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/bind/RequestUtilsTests.java
@@ -0,0 +1,413 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.bind;
+
+import javax.servlet.ServletException;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.MockHttpServletRequest;
+
+/**
+ * @author Juergen Hoeller
+ * @since 06.08.2003
+ */
+public class RequestUtilsTests extends TestCase {
+
+ public void testRejectMethod() throws ServletRequestBindingException {
+ String methodGet = "GET";
+ String methodPost = "POST";
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setMethod(methodPost);
+
+ try {
+ RequestUtils.rejectRequestMethod(request, methodGet);
+ } catch (ServletException ex) {
+ fail("Shouldn't have thrown ServletException");
+ }
+ try {
+ RequestUtils.rejectRequestMethod(request, methodPost);
+ fail("Should have thrown ServletException");
+ } catch (ServletException ex) {
+ }
+ }
+
+ public void testIntParameter() throws ServletRequestBindingException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("param1", "5");
+ request.addParameter("param2", "e");
+ request.addParameter("paramEmpty", "");
+
+ assertEquals(RequestUtils.getIntParameter(request, "param1"), new Integer(5));
+ assertEquals(RequestUtils.getIntParameter(request, "param1", 6), 5);
+ assertEquals(RequestUtils.getRequiredIntParameter(request, "param1"), 5);
+
+ assertEquals(RequestUtils.getIntParameter(request, "param2", 6), 6);
+ try {
+ RequestUtils.getRequiredIntParameter(request, "param2");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ assertEquals(RequestUtils.getIntParameter(request, "param3"), null);
+ assertEquals(RequestUtils.getIntParameter(request, "param3", 6), 6);
+ try {
+ RequestUtils.getRequiredIntParameter(request, "param3");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ try {
+ RequestUtils.getRequiredIntParameter(request, "paramEmpty");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testIntParameters() throws ServletRequestBindingException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("param", new String[] {"1", "2", "3"});
+
+ request.addParameter("param2", "1");
+ request.addParameter("param2", "2");
+ request.addParameter("param2", "bogus");
+
+ int[] array = new int[] { 1, 2, 3 };
+ int[] values = RequestUtils.getRequiredIntParameters(request, "param");
+ assertEquals(3, values.length);
+ for (int i = 0; i < array.length; i++) {
+ assertEquals(array[i], values[i]);
+ }
+
+ try {
+ RequestUtils.getRequiredIntParameters(request, "param2");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ }
+
+ public void testLongParameter() throws ServletRequestBindingException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("param1", "5");
+ request.addParameter("param2", "e");
+ request.addParameter("paramEmpty", "");
+
+ assertEquals(RequestUtils.getLongParameter(request, "param1"), new Long(5L));
+ assertEquals(RequestUtils.getLongParameter(request, "param1", 6L), 5L);
+ assertEquals(RequestUtils.getRequiredIntParameter(request, "param1"), 5L);
+
+ assertEquals(RequestUtils.getLongParameter(request, "param2", 6L), 6L);
+ try {
+ RequestUtils.getRequiredLongParameter(request, "param2");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ assertEquals(RequestUtils.getLongParameter(request, "param3"), null);
+ assertEquals(RequestUtils.getLongParameter(request, "param3", 6L), 6L);
+ try {
+ RequestUtils.getRequiredLongParameter(request, "param3");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ try {
+ RequestUtils.getRequiredLongParameter(request, "paramEmpty");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testLongParameters() throws ServletRequestBindingException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setParameter("param", new String[] {"1", "2", "3"});
+
+ request.setParameter("param2", "0");
+ request.setParameter("param2", "1");
+ request.addParameter("param2", "2");
+ request.addParameter("param2", "bogus");
+
+ long[] array = new long[] { 1L, 2L, 3L };
+ long[] values = RequestUtils.getRequiredLongParameters(request, "param");
+ assertEquals(3, values.length);
+ for (int i = 0; i < array.length; i++) {
+ assertEquals(array[i], values[i]);
+ }
+
+ try {
+ RequestUtils.getRequiredLongParameters(request, "param2");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ request.setParameter("param2", new String[] {"1", "2"});
+ values = RequestUtils.getRequiredLongParameters(request, "param2");
+ assertEquals(2, values.length);
+ assertEquals(1, values[0]);
+ assertEquals(2, values[1]);
+
+ request.removeParameter("param2");
+ try {
+ RequestUtils.getRequiredLongParameters(request, "param2");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testFloatParameter() throws ServletRequestBindingException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("param1", "5.5");
+ request.addParameter("param2", "e");
+ request.addParameter("paramEmpty", "");
+
+ assertTrue(RequestUtils.getFloatParameter(request, "param1").equals(new Float(5.5f)));
+ assertTrue(RequestUtils.getFloatParameter(request, "param1", 6.5f) == 5.5f);
+ assertTrue(RequestUtils.getRequiredFloatParameter(request, "param1") == 5.5f);
+
+ assertTrue(RequestUtils.getFloatParameter(request, "param2", 6.5f) == 6.5f);
+ try {
+ RequestUtils.getRequiredFloatParameter(request, "param2");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ assertTrue(RequestUtils.getFloatParameter(request, "param3") == null);
+ assertTrue(RequestUtils.getFloatParameter(request, "param3", 6.5f) == 6.5f);
+ try {
+ RequestUtils.getRequiredFloatParameter(request, "param3");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ try {
+ RequestUtils.getRequiredFloatParameter(request, "paramEmpty");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testFloatParameters() throws ServletRequestBindingException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("param", new String[] {"1.5", "2.5", "3"});
+
+ request.addParameter("param2", "1.5");
+ request.addParameter("param2", "2");
+ request.addParameter("param2", "bogus");
+
+ float[] array = new float[] { 1.5F, 2.5F, 3 };
+ float[] values = RequestUtils.getRequiredFloatParameters(request, "param");
+ assertEquals(3, values.length);
+ for (int i = 0; i < array.length; i++) {
+ assertEquals(array[i], values[i], 0);
+ }
+
+ try {
+ RequestUtils.getRequiredFloatParameters(request, "param2");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testDoubleParameter() throws ServletRequestBindingException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("param1", "5.5");
+ request.addParameter("param2", "e");
+ request.addParameter("paramEmpty", "");
+
+ assertTrue(RequestUtils.getDoubleParameter(request, "param1").equals(new Double(5.5)));
+ assertTrue(RequestUtils.getDoubleParameter(request, "param1", 6.5) == 5.5);
+ assertTrue(RequestUtils.getRequiredDoubleParameter(request, "param1") == 5.5);
+
+ assertTrue(RequestUtils.getDoubleParameter(request, "param2", 6.5) == 6.5);
+ try {
+ RequestUtils.getRequiredDoubleParameter(request, "param2");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ assertTrue(RequestUtils.getDoubleParameter(request, "param3") == null);
+ assertTrue(RequestUtils.getDoubleParameter(request, "param3", 6.5) == 6.5);
+ try {
+ RequestUtils.getRequiredDoubleParameter(request, "param3");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ try {
+ RequestUtils.getRequiredDoubleParameter(request, "paramEmpty");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testDoubleParameters() throws ServletRequestBindingException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("param", new String[] {"1.5", "2.5", "3"});
+
+ request.addParameter("param2", "1.5");
+ request.addParameter("param2", "2");
+ request.addParameter("param2", "bogus");
+
+ double[] array = new double[] { 1.5, 2.5, 3 };
+ double[] values = RequestUtils.getRequiredDoubleParameters(request, "param");
+ assertEquals(3, values.length);
+ for (int i = 0; i < array.length; i++) {
+ assertEquals(array[i], values[i], 0);
+ }
+
+ try {
+ RequestUtils.getRequiredDoubleParameters(request, "param2");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testBooleanParameter() throws ServletRequestBindingException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("param1", "true");
+ request.addParameter("param2", "e");
+ request.addParameter("param4", "yes");
+ request.addParameter("param5", "1");
+ request.addParameter("paramEmpty", "");
+
+ assertTrue(RequestUtils.getBooleanParameter(request, "param1").equals(Boolean.TRUE));
+ assertTrue(RequestUtils.getBooleanParameter(request, "param1", false));
+ assertTrue(RequestUtils.getRequiredBooleanParameter(request, "param1"));
+
+ assertFalse(RequestUtils.getBooleanParameter(request, "param2", true));
+ assertFalse(RequestUtils.getRequiredBooleanParameter(request, "param2"));
+
+ assertTrue(RequestUtils.getBooleanParameter(request, "param3") == null);
+ assertTrue(RequestUtils.getBooleanParameter(request, "param3", true));
+ try {
+ RequestUtils.getRequiredBooleanParameter(request, "param3");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ assertTrue(RequestUtils.getBooleanParameter(request, "param4", false));
+ assertTrue(RequestUtils.getRequiredBooleanParameter(request, "param4"));
+
+ assertTrue(RequestUtils.getBooleanParameter(request, "param5", false));
+ assertTrue(RequestUtils.getRequiredBooleanParameter(request, "param5"));
+ try {
+ RequestUtils.getRequiredBooleanParameter(request, "paramEmpty");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testBooleanParameters() throws ServletRequestBindingException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("param", new String[] {"true", "yes", "off", "1", "bogus"});
+
+ request.addParameter("param2", "false");
+ request.addParameter("param2", "true");
+ request.addParameter("param2", "");
+
+ boolean[] array = new boolean[] { true, true, false, true, false };
+ boolean[] values = RequestUtils.getRequiredBooleanParameters(request, "param");
+ assertEquals(5, values.length);
+ for (int i = 0; i < array.length; i++) {
+ assertEquals(array[i], values[i]);
+ }
+
+ try {
+ RequestUtils.getRequiredBooleanParameters(request, "param2");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testStringParameter() throws ServletRequestBindingException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("param1", "str");
+ request.addParameter("paramEmpty", "");
+
+ assertEquals(RequestUtils.getStringParameter(request, "param1"), "str");
+ assertEquals(RequestUtils.getStringParameter(request, "param1", "string"), "str");
+ assertEquals(RequestUtils.getRequiredStringParameter(request, "param1"), "str");
+
+ assertEquals(RequestUtils.getStringParameter(request, "param3"), null);
+ assertEquals(RequestUtils.getStringParameter(request, "param3", "string"), "string");
+ try {
+ RequestUtils.getRequiredStringParameter(request, "param3");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ try {
+ RequestUtils.getStringParameter(request, "paramEmpty");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+ try {
+ RequestUtils.getRequiredStringParameter(request, "paramEmpty");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/bind/ServletRequestDataBinderTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/bind/ServletRequestDataBinderTests.java
new file mode 100644
index 00000000000..e347e067257
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/bind/ServletRequestDataBinderTests.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.bind;
+
+import java.beans.PropertyEditorSupport;
+import java.util.Arrays;
+
+import org.springframework.beans.AbstractPropertyValuesTests;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.mock.web.MockHttpServletRequest;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public class ServletRequestDataBinderTests extends AbstractPropertyValuesTests {
+
+ public void testBindingWithNestedObjectCreation() throws Exception {
+ TestBean tb = new TestBean();
+
+ ServletRequestDataBinder binder = new ServletRequestDataBinder(tb, "person");
+ binder.registerCustomEditor(ITestBean.class, new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue(new TestBean());
+ }
+ });
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("spouse", "someValue");
+ request.addParameter("spouse.name", "test");
+ binder.bind(request);
+
+ assertNotNull(tb.getSpouse());
+ assertEquals("test", tb.getSpouse().getName());
+ }
+
+ public void testFieldPrefixCausesFieldReset() throws Exception {
+ TestBean target = new TestBean();
+ ServletRequestDataBinder binder = new ServletRequestDataBinder(target);
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("_postProcessed", "visible");
+ request.addParameter("postProcessed", "on");
+ binder.bind(request);
+ assertTrue(target.isPostProcessed());
+
+ request.removeParameter("postProcessed");
+ binder.bind(request);
+ assertFalse(target.isPostProcessed());
+ }
+
+ public void testFieldPrefixCausesFieldResetWithIgnoreUnknownFields() throws Exception {
+ TestBean target = new TestBean();
+ ServletRequestDataBinder binder = new ServletRequestDataBinder(target);
+ binder.setIgnoreUnknownFields(false);
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("_postProcessed", "visible");
+ request.addParameter("postProcessed", "on");
+ binder.bind(request);
+ assertTrue(target.isPostProcessed());
+
+ request.removeParameter("postProcessed");
+ binder.bind(request);
+ assertFalse(target.isPostProcessed());
+ }
+
+ public void testWithCommaSeparatedStringArray() throws Exception {
+ TestBean target = new TestBean();
+ ServletRequestDataBinder binder = new ServletRequestDataBinder(target);
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("stringArray", "bar");
+ request.addParameter("stringArray", "abc");
+ request.addParameter("stringArray", "123,def");
+ binder.bind(request);
+ assertEquals("Expected all three items to be bound", 3, target.getStringArray().length);
+
+ request.removeParameter("stringArray");
+ request.addParameter("stringArray", "123,def");
+ binder.bind(request);
+ assertEquals("Expected only 1 item to be bound", 1, target.getStringArray().length);
+ }
+
+ public void testBindingWithNestedObjectCreationAndWrongOrder() throws Exception {
+ TestBean tb = new TestBean();
+
+ ServletRequestDataBinder binder = new ServletRequestDataBinder(tb, "person");
+ binder.registerCustomEditor(ITestBean.class, new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue(new TestBean());
+ }
+ });
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("spouse.name", "test");
+ request.addParameter("spouse", "someValue");
+ binder.bind(request);
+
+ assertNotNull(tb.getSpouse());
+ assertEquals("test", tb.getSpouse().getName());
+ }
+
+ public void testNoPrefix() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("forname", "Tony");
+ request.addParameter("surname", "Blair");
+ request.addParameter("age", "" + 50);
+
+ ServletRequestParameterPropertyValues pvs = new ServletRequestParameterPropertyValues(request);
+ doTestTony(pvs);
+ }
+
+ public void testPrefix() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("test_forname", "Tony");
+ request.addParameter("test_surname", "Blair");
+ request.addParameter("test_age", "" + 50);
+
+ ServletRequestParameterPropertyValues pvs = new ServletRequestParameterPropertyValues(request);
+ assertTrue("Didn't fidn normal when given prefix", !pvs.contains("forname"));
+ assertTrue("Did treat prefix as normal when not given prefix", pvs.contains("test_forname"));
+
+ pvs = new ServletRequestParameterPropertyValues(request, "test");
+ doTestTony(pvs);
+ }
+
+ public void testNoParameters() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ ServletRequestParameterPropertyValues pvs = new ServletRequestParameterPropertyValues(request);
+ assertTrue("Found no parameters", pvs.getPropertyValues().length == 0);
+ }
+
+ public void testMultipleValuesForParameter() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ String[] original = new String[] {"Tony", "Rod"};
+ request.addParameter("forname", original);
+
+ ServletRequestParameterPropertyValues pvs = new ServletRequestParameterPropertyValues(request);
+ assertTrue("Found 1 parameter", pvs.getPropertyValues().length == 1);
+ assertTrue("Found array value", pvs.getPropertyValue("forname").getValue() instanceof String[]);
+ String[] values = (String[]) pvs.getPropertyValue("forname").getValue();
+ assertEquals("Correct values", Arrays.asList(values), Arrays.asList(original));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/bind/ServletRequestUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/bind/ServletRequestUtilsTests.java
new file mode 100644
index 00000000000..7f18e0ffcf4
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/bind/ServletRequestUtilsTests.java
@@ -0,0 +1,446 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.bind;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.util.StopWatch;
+
+/**
+ * @author Juergen Hoeller
+ * @since 06.08.2003
+ */
+public class ServletRequestUtilsTests extends TestCase {
+
+ public void testIntParameter() throws ServletRequestBindingException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("param1", "5");
+ request.addParameter("param2", "e");
+ request.addParameter("paramEmpty", "");
+
+ assertEquals(ServletRequestUtils.getIntParameter(request, "param1"), new Integer(5));
+ assertEquals(ServletRequestUtils.getIntParameter(request, "param1", 6), 5);
+ assertEquals(ServletRequestUtils.getRequiredIntParameter(request, "param1"), 5);
+
+ assertEquals(ServletRequestUtils.getIntParameter(request, "param2", 6), 6);
+ try {
+ ServletRequestUtils.getRequiredIntParameter(request, "param2");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ assertEquals(ServletRequestUtils.getIntParameter(request, "param3"), null);
+ assertEquals(ServletRequestUtils.getIntParameter(request, "param3", 6), 6);
+ try {
+ ServletRequestUtils.getRequiredIntParameter(request, "param3");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ try {
+ ServletRequestUtils.getRequiredIntParameter(request, "paramEmpty");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testIntParameters() throws ServletRequestBindingException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("param", new String[] {"1", "2", "3"});
+
+ request.addParameter("param2", "1");
+ request.addParameter("param2", "2");
+ request.addParameter("param2", "bogus");
+
+ int[] array = new int[] {1, 2, 3};
+ int[] values = ServletRequestUtils.getRequiredIntParameters(request, "param");
+ assertEquals(3, values.length);
+ for (int i = 0; i < array.length; i++) {
+ assertEquals(array[i], values[i]);
+ }
+
+ try {
+ ServletRequestUtils.getRequiredIntParameters(request, "param2");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testLongParameter() throws ServletRequestBindingException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("param1", "5");
+ request.addParameter("param2", "e");
+ request.addParameter("paramEmpty", "");
+
+ assertEquals(ServletRequestUtils.getLongParameter(request, "param1"), new Long(5L));
+ assertEquals(ServletRequestUtils.getLongParameter(request, "param1", 6L), 5L);
+ assertEquals(ServletRequestUtils.getRequiredIntParameter(request, "param1"), 5L);
+
+ assertEquals(ServletRequestUtils.getLongParameter(request, "param2", 6L), 6L);
+ try {
+ ServletRequestUtils.getRequiredLongParameter(request, "param2");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ assertEquals(ServletRequestUtils.getLongParameter(request, "param3"), null);
+ assertEquals(ServletRequestUtils.getLongParameter(request, "param3", 6L), 6L);
+ try {
+ ServletRequestUtils.getRequiredLongParameter(request, "param3");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ try {
+ ServletRequestUtils.getRequiredLongParameter(request, "paramEmpty");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testLongParameters() throws ServletRequestBindingException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setParameter("param", new String[] {"1", "2", "3"});
+
+ request.setParameter("param2", "0");
+ request.setParameter("param2", "1");
+ request.addParameter("param2", "2");
+ request.addParameter("param2", "bogus");
+
+ long[] array = new long[] {1L, 2L, 3L};
+ long[] values = ServletRequestUtils.getRequiredLongParameters(request, "param");
+ assertEquals(3, values.length);
+ for (int i = 0; i < array.length; i++) {
+ assertEquals(array[i], values[i]);
+ }
+
+ try {
+ ServletRequestUtils.getRequiredLongParameters(request, "param2");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ request.setParameter("param2", new String[] {"1", "2"});
+ values = ServletRequestUtils.getRequiredLongParameters(request, "param2");
+ assertEquals(2, values.length);
+ assertEquals(1, values[0]);
+ assertEquals(2, values[1]);
+
+ request.removeParameter("param2");
+ try {
+ ServletRequestUtils.getRequiredLongParameters(request, "param2");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testFloatParameter() throws ServletRequestBindingException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("param1", "5.5");
+ request.addParameter("param2", "e");
+ request.addParameter("paramEmpty", "");
+
+ assertTrue(ServletRequestUtils.getFloatParameter(request, "param1").equals(new Float(5.5f)));
+ assertTrue(ServletRequestUtils.getFloatParameter(request, "param1", 6.5f) == 5.5f);
+ assertTrue(ServletRequestUtils.getRequiredFloatParameter(request, "param1") == 5.5f);
+
+ assertTrue(ServletRequestUtils.getFloatParameter(request, "param2", 6.5f) == 6.5f);
+ try {
+ ServletRequestUtils.getRequiredFloatParameter(request, "param2");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ assertTrue(ServletRequestUtils.getFloatParameter(request, "param3") == null);
+ assertTrue(ServletRequestUtils.getFloatParameter(request, "param3", 6.5f) == 6.5f);
+ try {
+ ServletRequestUtils.getRequiredFloatParameter(request, "param3");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ try {
+ ServletRequestUtils.getRequiredFloatParameter(request, "paramEmpty");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testFloatParameters() throws ServletRequestBindingException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("param", new String[] {"1.5", "2.5", "3"});
+
+ request.addParameter("param2", "1.5");
+ request.addParameter("param2", "2");
+ request.addParameter("param2", "bogus");
+
+ float[] array = new float[] {1.5F, 2.5F, 3};
+ float[] values = ServletRequestUtils.getRequiredFloatParameters(request, "param");
+ assertEquals(3, values.length);
+ for (int i = 0; i < array.length; i++) {
+ assertEquals(array[i], values[i], 0);
+ }
+
+ try {
+ ServletRequestUtils.getRequiredFloatParameters(request, "param2");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testDoubleParameter() throws ServletRequestBindingException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("param1", "5.5");
+ request.addParameter("param2", "e");
+ request.addParameter("paramEmpty", "");
+
+ assertTrue(ServletRequestUtils.getDoubleParameter(request, "param1").equals(new Double(5.5)));
+ assertTrue(ServletRequestUtils.getDoubleParameter(request, "param1", 6.5) == 5.5);
+ assertTrue(ServletRequestUtils.getRequiredDoubleParameter(request, "param1") == 5.5);
+
+ assertTrue(ServletRequestUtils.getDoubleParameter(request, "param2", 6.5) == 6.5);
+ try {
+ ServletRequestUtils.getRequiredDoubleParameter(request, "param2");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ assertTrue(ServletRequestUtils.getDoubleParameter(request, "param3") == null);
+ assertTrue(ServletRequestUtils.getDoubleParameter(request, "param3", 6.5) == 6.5);
+ try {
+ ServletRequestUtils.getRequiredDoubleParameter(request, "param3");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ try {
+ ServletRequestUtils.getRequiredDoubleParameter(request, "paramEmpty");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testDoubleParameters() throws ServletRequestBindingException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("param", new String[] {"1.5", "2.5", "3"});
+
+ request.addParameter("param2", "1.5");
+ request.addParameter("param2", "2");
+ request.addParameter("param2", "bogus");
+
+ double[] array = new double[] {1.5, 2.5, 3};
+ double[] values = ServletRequestUtils.getRequiredDoubleParameters(request, "param");
+ assertEquals(3, values.length);
+ for (int i = 0; i < array.length; i++) {
+ assertEquals(array[i], values[i], 0);
+ }
+
+ try {
+ ServletRequestUtils.getRequiredDoubleParameters(request, "param2");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testBooleanParameter() throws ServletRequestBindingException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("param1", "true");
+ request.addParameter("param2", "e");
+ request.addParameter("param4", "yes");
+ request.addParameter("param5", "1");
+ request.addParameter("paramEmpty", "");
+
+ assertTrue(ServletRequestUtils.getBooleanParameter(request, "param1").equals(Boolean.TRUE));
+ assertTrue(ServletRequestUtils.getBooleanParameter(request, "param1", false));
+ assertTrue(ServletRequestUtils.getRequiredBooleanParameter(request, "param1"));
+
+ assertFalse(ServletRequestUtils.getBooleanParameter(request, "param2", true));
+ assertFalse(ServletRequestUtils.getRequiredBooleanParameter(request, "param2"));
+
+ assertTrue(ServletRequestUtils.getBooleanParameter(request, "param3") == null);
+ assertTrue(ServletRequestUtils.getBooleanParameter(request, "param3", true));
+ try {
+ ServletRequestUtils.getRequiredBooleanParameter(request, "param3");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ assertTrue(ServletRequestUtils.getBooleanParameter(request, "param4", false));
+ assertTrue(ServletRequestUtils.getRequiredBooleanParameter(request, "param4"));
+
+ assertTrue(ServletRequestUtils.getBooleanParameter(request, "param5", false));
+ assertTrue(ServletRequestUtils.getRequiredBooleanParameter(request, "param5"));
+ assertFalse(ServletRequestUtils.getRequiredBooleanParameter(request, "paramEmpty"));
+ }
+
+ public void testBooleanParameters() throws ServletRequestBindingException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("param", new String[] {"true", "yes", "off", "1", "bogus"});
+
+ request.addParameter("param2", "false");
+ request.addParameter("param2", "true");
+ request.addParameter("param2", "");
+
+ boolean[] array = new boolean[] {true, true, false, true, false};
+ boolean[] values = ServletRequestUtils.getRequiredBooleanParameters(request, "param");
+ assertEquals(array.length, values.length);
+ for (int i = 0; i < array.length; i++) {
+ assertEquals(array[i], values[i]);
+ }
+
+ array = new boolean[] {false, true, false};
+ values = ServletRequestUtils.getRequiredBooleanParameters(request, "param2");
+ assertEquals(array.length, values.length);
+ for (int i = 0; i < array.length; i++) {
+ assertEquals(array[i], values[i]);
+ }
+ }
+
+ public void testStringParameter() throws ServletRequestBindingException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("param1", "str");
+ request.addParameter("paramEmpty", "");
+
+ assertEquals("str", ServletRequestUtils.getStringParameter(request, "param1"));
+ assertEquals("str", ServletRequestUtils.getStringParameter(request, "param1", "string"));
+ assertEquals("str", ServletRequestUtils.getRequiredStringParameter(request, "param1"));
+
+ assertEquals(null, ServletRequestUtils.getStringParameter(request, "param3"));
+ assertEquals("string", ServletRequestUtils.getStringParameter(request, "param3", "string"));
+ assertNull(ServletRequestUtils.getStringParameter(request, "param3", null));
+ try {
+ ServletRequestUtils.getRequiredStringParameter(request, "param3");
+ fail("Should have thrown ServletRequestBindingException");
+ }
+ catch (ServletRequestBindingException ex) {
+ // expected
+ }
+
+ assertEquals("", ServletRequestUtils.getStringParameter(request, "paramEmpty"));
+ assertEquals("", ServletRequestUtils.getRequiredStringParameter(request, "paramEmpty"));
+ }
+
+ public void testGetIntParameterWithDefaultValueHandlingIsFastEnough() {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ StopWatch sw = new StopWatch();
+ sw.start();
+ for (int i = 0; i < 1000000; i++) {
+ ServletRequestUtils.getIntParameter(request, "nonExistingParam", 0);
+ }
+ sw.stop();
+ System.out.println(sw.getTotalTimeMillis());
+ assertTrue("getStringParameter took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 250);
+ }
+
+ public void testGetLongParameterWithDefaultValueHandlingIsFastEnough() {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ StopWatch sw = new StopWatch();
+ sw.start();
+ for (int i = 0; i < 1000000; i++) {
+ ServletRequestUtils.getLongParameter(request, "nonExistingParam", 0);
+ }
+ sw.stop();
+ System.out.println(sw.getTotalTimeMillis());
+ assertTrue("getStringParameter took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 250);
+ }
+
+ public void testGetFloatParameterWithDefaultValueHandlingIsFastEnough() {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ StopWatch sw = new StopWatch();
+ sw.start();
+ for (int i = 0; i < 1000000; i++) {
+ ServletRequestUtils.getFloatParameter(request, "nonExistingParam", 0f);
+ }
+ sw.stop();
+ System.out.println(sw.getTotalTimeMillis());
+ assertTrue("getStringParameter took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 250);
+ }
+
+ public void testGetDoubleParameterWithDefaultValueHandlingIsFastEnough() {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ StopWatch sw = new StopWatch();
+ sw.start();
+ for (int i = 0; i < 1000000; i++) {
+ ServletRequestUtils.getDoubleParameter(request, "nonExistingParam", 0d);
+ }
+ sw.stop();
+ System.out.println(sw.getTotalTimeMillis());
+ assertTrue("getStringParameter took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 250);
+ }
+
+ public void testGetBooleanParameterWithDefaultValueHandlingIsFastEnough() {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ StopWatch sw = new StopWatch();
+ sw.start();
+ for (int i = 0; i < 1000000; i++) {
+ ServletRequestUtils.getBooleanParameter(request, "nonExistingParam", false);
+ }
+ sw.stop();
+ System.out.println(sw.getTotalTimeMillis());
+ assertTrue("getStringParameter took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 250);
+ }
+
+ public void testGetStringParameterWithDefaultValueHandlingIsFastEnough() {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ StopWatch sw = new StopWatch();
+ sw.start();
+ for (int i = 0; i < 1000000; i++) {
+ ServletRequestUtils.getStringParameter(request, "nonExistingParam", "defaultValue");
+ }
+ sw.stop();
+ System.out.println(sw.getTotalTimeMillis());
+ assertTrue("getStringParameter took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 250);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/ContextLoaderTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/context/ContextLoaderTests.java
new file mode 100644
index 00000000000..1eb8fbabf29
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/ContextLoaderTests.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.context;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.http.HttpServlet;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.BeanDefinitionStoreException;
+import org.springframework.beans.factory.LifecycleBean;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextException;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.mock.web.MockServletConfig;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.web.context.support.XmlWebApplicationContext;
+import org.springframework.web.servlet.DispatcherServlet;
+import org.springframework.web.servlet.SimpleWebApplicationContext;
+
+/**
+ * JUnit 3.8 based tests for {@link ContextLoader},
+ * {@link ContextLoaderListener}, {@link ContextLoaderServlet}, and related
+ * classes.
+ *
+ * @author Juergen Hoeller
+ * @author Sam Brannen
+ * @since 12.08.2003
+ */
+public class ContextLoaderTests extends TestCase {
+
+ public void testContextLoaderListenerWithDefaultContext() throws Exception {
+ MockServletContext sc = new MockServletContext("");
+ sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
+ "/org/springframework/web/context/WEB-INF/applicationContext.xml "
+ + "/org/springframework/web/context/WEB-INF/context-addition.xml");
+ ServletContextListener listener = new ContextLoaderListener();
+ ServletContextEvent event = new ServletContextEvent(sc);
+ listener.contextInitialized(event);
+ WebApplicationContext context = (WebApplicationContext) sc.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
+ assertTrue("Correct WebApplicationContext exposed in ServletContext",
+ context instanceof XmlWebApplicationContext);
+ LifecycleBean lb = (LifecycleBean) context.getBean("lifecycle");
+ assertTrue("Has father", context.containsBean("father"));
+ assertTrue("Has rod", context.containsBean("rod"));
+ assertTrue("Has kerry", context.containsBean("kerry"));
+ assertTrue("Not destroyed", !lb.isDestroyed());
+ assertFalse(context.containsBean("beans1.bean1"));
+ assertFalse(context.containsBean("beans1.bean2"));
+ listener.contextDestroyed(event);
+ assertTrue("Destroyed", lb.isDestroyed());
+ }
+
+ /**
+ * Addresses the issues raised in SPR-4008: Supply an opportunity to customize
+ * context before calling refresh in ContextLoaders.
+ */
+ public void testContextLoaderListenerWithCustomizedContextLoader() throws Exception {
+ final StringBuffer buffer = new StringBuffer();
+ final String expectedContents = "customizeContext() was called";
+ final MockServletContext sc = new MockServletContext("");
+ sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
+ "/org/springframework/web/context/WEB-INF/applicationContext.xml");
+ final ServletContextListener listener = new ContextLoaderListener() {
+ protected ContextLoader createContextLoader() {
+ return new ContextLoader() {
+ protected void customizeContext(ServletContext servletContext, ConfigurableWebApplicationContext applicationContext) {
+ assertNotNull("The ServletContext should not be null.", servletContext);
+ assertEquals("Verifying that we received the expected ServletContext.", sc, servletContext);
+ assertFalse("The ApplicationContext should not yet have been refreshed.", applicationContext.isActive());
+ buffer.append(expectedContents);
+ }
+ };
+ }
+ };
+ listener.contextInitialized(new ServletContextEvent(sc));
+ assertEquals("customizeContext() should have been called.", expectedContents, buffer.toString());
+ }
+
+ public void testContextLoaderServletWithDefaultContext() throws Exception {
+ MockServletContext sc = new MockServletContext("");
+ sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
+ "/org/springframework/web/context/WEB-INF/applicationContext.xml");
+ HttpServlet servlet = new ContextLoaderServlet();
+ ServletConfig config = new MockServletConfig(sc, "test");
+ servlet.init(config);
+ WebApplicationContext context = (WebApplicationContext) sc.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
+ assertTrue("Correct WebApplicationContext exposed in ServletContext",
+ context instanceof XmlWebApplicationContext);
+ LifecycleBean lb = (LifecycleBean) context.getBean("lifecycle");
+ assertTrue("Not destroyed", !lb.isDestroyed());
+ assertFalse(context.containsBean("beans1.bean1"));
+ assertFalse(context.containsBean("beans1.bean2"));
+ servlet.destroy();
+ assertTrue("Destroyed", lb.isDestroyed());
+ }
+
+ public void testContextLoaderWithDefaultContextAndParent() throws Exception {
+ MockServletContext sc = new MockServletContext("");
+ sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
+ "/org/springframework/web/context/WEB-INF/applicationContext.xml "
+ + "/org/springframework/web/context/WEB-INF/context-addition.xml");
+ sc.addInitParameter(ContextLoader.LOCATOR_FACTORY_SELECTOR_PARAM,
+ "classpath:org/springframework/beans/factory/access/ref1.xml");
+ sc.addInitParameter(ContextLoader.LOCATOR_FACTORY_KEY_PARAM, "a.qualified.name.of.some.sort");
+ ServletContextListener listener = new ContextLoaderListener();
+ ServletContextEvent event = new ServletContextEvent(sc);
+ listener.contextInitialized(event);
+ WebApplicationContext context = (WebApplicationContext) sc.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
+ assertTrue("Correct WebApplicationContext exposed in ServletContext",
+ context instanceof XmlWebApplicationContext);
+ LifecycleBean lb = (LifecycleBean) context.getBean("lifecycle");
+ assertTrue("Has father", context.containsBean("father"));
+ assertTrue("Has rod", context.containsBean("rod"));
+ assertTrue("Has kerry", context.containsBean("kerry"));
+ assertTrue("Not destroyed", !lb.isDestroyed());
+ assertTrue(context.containsBean("beans1.bean1"));
+ assertTrue(context.isTypeMatch("beans1.bean1", org.springframework.beans.factory.access.TestBean.class));
+ assertTrue(context.containsBean("beans1.bean2"));
+ assertTrue(context.isTypeMatch("beans1.bean2", org.springframework.beans.factory.access.TestBean.class));
+ listener.contextDestroyed(event);
+ assertTrue("Destroyed", lb.isDestroyed());
+ }
+
+ public void testContextLoaderWithCustomContext() throws Exception {
+ MockServletContext sc = new MockServletContext("");
+ sc.addInitParameter(ContextLoader.CONTEXT_CLASS_PARAM,
+ "org.springframework.web.servlet.SimpleWebApplicationContext");
+ ServletContextListener listener = new ContextLoaderListener();
+ ServletContextEvent event = new ServletContextEvent(sc);
+ listener.contextInitialized(event);
+ WebApplicationContext wc = (WebApplicationContext) sc.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
+ assertTrue("Correct WebApplicationContext exposed in ServletContext", wc instanceof SimpleWebApplicationContext);
+ }
+
+ public void testContextLoaderWithInvalidLocation() throws Exception {
+ MockServletContext sc = new MockServletContext("");
+ sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM, "/WEB-INF/myContext.xml");
+ ServletContextListener listener = new ContextLoaderListener();
+ ServletContextEvent event = new ServletContextEvent(sc);
+ try {
+ listener.contextInitialized(event);
+ fail("Should have thrown BeanDefinitionStoreException");
+ }
+ catch (BeanDefinitionStoreException ex) {
+ // expected
+ assertTrue(ex.getCause() instanceof FileNotFoundException);
+ }
+ }
+
+ public void testContextLoaderWithInvalidContext() throws Exception {
+ MockServletContext sc = new MockServletContext("");
+ sc.addInitParameter(ContextLoader.CONTEXT_CLASS_PARAM,
+ "org.springframework.web.context.support.InvalidWebApplicationContext");
+ ServletContextListener listener = new ContextLoaderListener();
+ ServletContextEvent event = new ServletContextEvent(sc);
+ try {
+ listener.contextInitialized(event);
+ fail("Should have thrown ApplicationContextException");
+ }
+ catch (ApplicationContextException ex) {
+ // expected
+ assertTrue(ex.getCause() instanceof ClassNotFoundException);
+ }
+ }
+
+ public void testContextLoaderWithDefaultLocation() throws Exception {
+ MockServletContext sc = new MockServletContext("");
+ ServletContextListener listener = new ContextLoaderListener();
+ ServletContextEvent event = new ServletContextEvent(sc);
+ try {
+ listener.contextInitialized(event);
+ fail("Should have thrown BeanDefinitionStoreException");
+ }
+ catch (BeanDefinitionStoreException ex) {
+ // expected
+ assertTrue(ex.getCause() instanceof IOException);
+ assertTrue(ex.getCause().getMessage().indexOf("/WEB-INF/applicationContext.xml") != -1);
+ }
+ }
+
+ public void testFrameworkServletWithDefaultLocation() throws Exception {
+ DispatcherServlet servlet = new DispatcherServlet();
+ servlet.setContextClass(XmlWebApplicationContext.class);
+ try {
+ servlet.init(new MockServletConfig(new MockServletContext(""), "test"));
+ fail("Should have thrown BeanDefinitionStoreException");
+ }
+ catch (BeanDefinitionStoreException ex) {
+ // expected
+ assertTrue(ex.getCause() instanceof IOException);
+ assertTrue(ex.getCause().getMessage().indexOf("/WEB-INF/test-servlet.xml") != -1);
+ }
+ }
+
+ public void testFrameworkServletWithCustomLocation() throws Exception {
+ DispatcherServlet servlet = new DispatcherServlet();
+ servlet.setContextConfigLocation("/org/springframework/web/context/WEB-INF/testNamespace.xml "
+ + "/org/springframework/web/context/WEB-INF/context-addition.xml");
+ servlet.init(new MockServletConfig(new MockServletContext(""), "test"));
+ assertTrue(servlet.getWebApplicationContext().containsBean("kerry"));
+ assertTrue(servlet.getWebApplicationContext().containsBean("kerryX"));
+ }
+
+ public void testClassPathXmlApplicationContext() throws IOException {
+ ApplicationContext context = new ClassPathXmlApplicationContext(
+ "/org/springframework/web/context/WEB-INF/applicationContext.xml");
+ assertTrue("Has father", context.containsBean("father"));
+ assertTrue("Has rod", context.containsBean("rod"));
+ assertFalse("Hasn't kerry", context.containsBean("kerry"));
+ assertTrue("Doesn't have spouse", ((TestBean) context.getBean("rod")).getSpouse() == null);
+ assertTrue("myinit not evaluated", "Roderick".equals(((TestBean) context.getBean("rod")).getName()));
+
+ context = new ClassPathXmlApplicationContext(new String[] {
+ "/org/springframework/web/context/WEB-INF/applicationContext.xml",
+ "/org/springframework/web/context/WEB-INF/context-addition.xml" });
+ assertTrue("Has father", context.containsBean("father"));
+ assertTrue("Has rod", context.containsBean("rod"));
+ assertTrue("Has kerry", context.containsBean("kerry"));
+ }
+
+ public void testSingletonDestructionOnStartupFailure() throws IOException {
+ try {
+ new ClassPathXmlApplicationContext(new String[] {
+ "/org/springframework/web/context/WEB-INF/applicationContext.xml",
+ "/org/springframework/web/context/WEB-INF/fail.xml" }) {
+
+ public void refresh() throws BeansException {
+ try {
+ super.refresh();
+ }
+ catch (BeanCreationException ex) {
+ DefaultListableBeanFactory factory = (DefaultListableBeanFactory) getBeanFactory();
+ assertEquals(0, factory.getSingletonCount());
+ throw ex;
+ }
+ }
+ };
+ fail("Should have thrown BeanCreationException");
+ }
+ catch (BeanCreationException ex) {
+ // expected
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/ResourceBundleMessageSourceTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/context/ResourceBundleMessageSourceTests.java
new file mode 100644
index 00000000000..f231c749219
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/ResourceBundleMessageSourceTests.java
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.web.context;
+
+import java.util.Date;
+import java.util.Locale;
+
+import org.springframework.context.AbstractApplicationContextTests;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.MessageSource;
+import org.springframework.context.NoSuchMessageException;
+import org.springframework.context.support.AbstractMessageSource;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.ui.context.Theme;
+import org.springframework.ui.context.ThemeSource;
+import org.springframework.web.context.support.StaticWebApplicationContext;
+import org.springframework.web.context.support.XmlWebApplicationContext;
+import org.springframework.web.servlet.theme.AbstractThemeResolver;
+
+/**
+ * Creates a WebApplicationContext that points to a "web.xml" file that
+ * contains the entry for what file to use for the applicationContext
+ * (file "org/springframework/web/context/WEB-INF/applicationContext.xml").
+ * That file then has an entry for a bean called "messageSource".
+ * Whatever the basename property is set to for this bean is what the name of
+ * a properties file in the classpath must be (in our case the name is
+ * "messages" - note no package names).
+ * Thus the catalog filename will be in the root of where the classes are compiled
+ * to and will be called "messages_XX_YY.properties" where "XX" and "YY" are the
+ * language and country codes known by the ResourceBundle class.
+ *
+ *
NOTE: The main method of this class is the "createWebApplicationContext(...)" method,
+ * and it was copied from org.springframework.web.context.XmlWebApplicationContextTests.
+ *
+ * @author Rod Johnson
+ * @author Jean-Pierre Pawlak
+ */
+public class ResourceBundleMessageSourceTests extends AbstractApplicationContextTests {
+
+ /**
+ * We use ticket WAR root for file structure.
+ * We don't attempt to read web.xml.
+ */
+ public static final String WAR_ROOT = "/org/springframework/web/context";
+
+ private ConfigurableWebApplicationContext root;
+
+ private MessageSource themeMsgSource;
+
+ protected ConfigurableApplicationContext createContext() throws Exception {
+ root = new XmlWebApplicationContext();
+ MockServletContext sc = new MockServletContext();
+ root.setServletContext(sc);
+ root.setConfigLocations(new String[] {"/org/springframework/web/context/WEB-INF/applicationContext.xml"});
+ root.refresh();
+
+ ConfigurableWebApplicationContext wac = new XmlWebApplicationContext();
+ wac.setParent(root);
+ wac.setServletContext(sc);
+ wac.setNamespace("test-servlet");
+ wac.setConfigLocations(new String[] {"/org/springframework/web/context/WEB-INF/test-servlet.xml"});
+ wac.refresh();
+
+ Theme theme = ((ThemeSource) wac).getTheme(AbstractThemeResolver.ORIGINAL_DEFAULT_THEME_NAME);
+ assertNotNull(theme);
+ assertTrue("Theme name has to be the default theme name", AbstractThemeResolver.ORIGINAL_DEFAULT_THEME_NAME.equals(theme.getName()));
+ themeMsgSource = theme.getMessageSource();
+ assertNotNull(themeMsgSource);
+ return wac;
+ }
+
+ public void testCount() {
+ assertTrue("should have 14 beans, not " +
+ this.applicationContext.getBeanDefinitionCount(),
+ this.applicationContext.getBeanDefinitionCount() == 14);
+ }
+
+ /**
+ * Overridden as we can't trust superclass method.
+ * @see org.springframework.context.AbstractApplicationContextTests#testEvents()
+ */
+ public void testEvents() throws Exception {
+ // Do nothing
+ }
+
+ public void testRootMessageSourceWithUseCodeAsDefaultMessage() throws NoSuchMessageException {
+ AbstractMessageSource messageSource = (AbstractMessageSource) root.getBean("messageSource");
+ messageSource.setUseCodeAsDefaultMessage(true);
+
+ assertEquals("message1", applicationContext.getMessage("code1", null, Locale.getDefault()));
+ assertEquals("message2", applicationContext.getMessage("code2", null, Locale.getDefault()));
+
+ try {
+ applicationContext.getMessage("code0", null, Locale.getDefault());
+ fail("looking for code0 should throw a NoSuchMessageException");
+ }
+ catch (NoSuchMessageException ex) {
+ // that's how it should be
+ }
+ }
+
+ /**
+ * @see org.springframework.context.support.AbstractMessageSource for more details.
+ * NOTE: Messages are contained within the "test/org/springframework/web/context/WEB-INF/messagesXXX.properties" files.
+ */
+ public void testGetMessageWithDefaultPassedInAndFoundInMsgCatalog() {
+ assertTrue("valid msg from resourcebundle with default msg passed in returned default msg. Expected msg from catalog.",
+ getApplicationContext().getMessage("message.format.example2", null, "This is a default msg if not found in msg.cat.", Locale.US
+ )
+ .equals("This is a test message in the message catalog with no args."));
+ // getApplicationContext().getTheme("theme").getMessageSource().getMessage()
+ }
+
+ /**
+ * @see org.springframework.context.support.AbstractMessageSource for more details.
+ * NOTE: Messages are contained within the "test/org/springframework/web/context/WEB-INF/messagesXXX.properties" files.
+ */
+ public void testGetMessageWithDefaultPassedInAndNotFoundInMsgCatalog() {
+ assertTrue("bogus msg from resourcebundle with default msg passed in returned default msg",
+ getApplicationContext().getMessage("bogus.message", null, "This is a default msg if not found in msg.cat.", Locale.UK
+ )
+ .equals("This is a default msg if not found in msg.cat."));
+ }
+
+ /**
+ * The underlying implementation uses a hashMap to cache messageFormats
+ * once a message has been asked for. This test is an attempt to
+ * make sure the cache is being used properly.
+ * NOTE: Messages are contained within the "test/org/springframework/web/context/WEB-INF/messagesXXX.properties" files.
+ * @see org.springframework.context.support.AbstractMessageSource for more details.
+ */
+ public void testGetMessageWithMessageAlreadyLookedFor() throws Exception {
+ Object[] arguments = {
+ new Integer(7), new Date(System.currentTimeMillis()),
+ "a disturbance in the Force"
+ };
+
+ // The first time searching, we don't care about for this test
+ getApplicationContext().getMessage("message.format.example1", arguments, Locale.US);
+
+ // Now msg better be as expected
+ assertTrue("2nd search within MsgFormat cache returned expected message for Locale.US",
+ getApplicationContext().getMessage("message.format.example1", arguments, Locale.US
+ )
+ .indexOf("there was \"a disturbance in the Force\" on planet 7.") != -1);
+
+ Object[] newArguments = {
+ new Integer(8), new Date(System.currentTimeMillis()),
+ "a disturbance in the Force"
+ };
+
+ // Now msg better be as expected even with different args
+ assertTrue("2nd search within MsgFormat cache with different args returned expected message for Locale.US",
+ getApplicationContext().getMessage("message.format.example1", newArguments, Locale.US
+ )
+ .indexOf("there was \"a disturbance in the Force\" on planet 8.") != -1);
+ }
+
+ /**
+ * @see org.springframework.context.support.AbstractMessageSource for more details.
+ * NOTE: Messages are contained within the "test/org/springframework/web/context/WEB-INF/messagesXXX.properties" files.
+ * Example taken from the javadocs for the java.text.MessageFormat class
+ */
+ public void testGetMessageWithNoDefaultPassedInAndFoundInMsgCatalog() throws Exception {
+ Object[] arguments = {
+ new Integer(7), new Date(System.currentTimeMillis()),
+ "a disturbance in the Force"
+ };
+
+ /*
+ Try with Locale.US
+ Since the msg has a time value in it, we will use String.indexOf(...)
+ to just look for a substring without the time. This is because it is
+ possible that by the time we store a time variable in this method
+ and the time the ResourceBundleMessageSource resolves the msg the
+ minutes of the time might not be the same.
+ */
+ assertTrue("msg from resourcebundle for Locale.US substituting args for placeholders is as expected",
+ getApplicationContext().getMessage("message.format.example1", arguments, Locale.US
+ )
+ .indexOf("there was \"a disturbance in the Force\" on planet 7.") != -1);
+
+ // Try with Locale.UK
+ assertTrue("msg from resourcebundle for Locale.UK substituting args for placeholders is as expected",
+ getApplicationContext().getMessage("message.format.example1", arguments, Locale.UK
+ )
+ .indexOf("there was \"a disturbance in the Force\" on station number 7.") != -1);
+
+ // Try with Locale.US - different test msg that requires no args
+ assertTrue("msg from resourcebundle that requires no args for Locale.US is as expected",
+ getApplicationContext().getMessage("message.format.example2", null, Locale.US)
+ .equals("This is a test message in the message catalog with no args."));
+ }
+
+ /**
+ * @see org.springframework.context.support.AbstractMessageSource for more details.
+ * NOTE: Messages are contained within the "test/org/springframework/web/context/WEB-INF/messagesXXX.properties" files.
+ */
+ public void testGetMessageWithNoDefaultPassedInAndNotFoundInMsgCatalog() {
+ // Expecting an exception
+ try {
+ getApplicationContext().getMessage("bogus.message", null, Locale.UK);
+ fail("bogus msg from resourcebundle without default msg should have thrown exception");
+ }
+ catch (NoSuchMessageException tExcept) {
+ assertTrue("bogus msg from resourcebundle without default msg threw expected exception",
+ true);
+ }
+ }
+
+ public void testGetMultipleBasenamesForMessageSource() throws NoSuchMessageException {
+ assertEquals("message1", getApplicationContext().getMessage("code1", null, Locale.UK));
+ assertEquals("message2", getApplicationContext().getMessage("code2", null, Locale.UK));
+ assertEquals("message3", getApplicationContext().getMessage("code3", null, Locale.UK));
+ }
+
+ /**
+ * @see org.springframework.context.support.AbstractMessageSource for more details.
+ * NOTE: Messages are contained within the "test/org/springframework/web/context/WEB-INF/themeXXX.properties" files.
+ */
+ public void testGetMessageWithDefaultPassedInAndFoundInThemeCatalog() {
+ // Try with Locale.US
+ String msg = getThemeMessage("theme.example1", null, "This is a default theme msg if not found in theme cat.", Locale.US);
+ assertTrue("valid msg from theme resourcebundle with default msg passed in returned default msg. Expected msg from catalog. Received: " + msg,
+ msg.equals("This is a test message in the theme message catalog."));
+ // Try with Locale.UK
+ msg = getThemeMessage("theme.example1", null, "This is a default theme msg if not found in theme cat.", Locale.UK);
+ assertTrue("valid msg from theme resourcebundle with default msg passed in returned default msg. Expected msg from catalog.",
+ msg.equals("This is a test message in the theme message catalog with no args."));
+ }
+
+ /**
+ * @see org.springframework.context.support.AbstractMessageSource for more details.
+ * NOTE: Messages are contained within the "test/org/springframework/web/context/WEB-INF/themeXXX.properties" files.
+ */
+ public void testGetMessageWithDefaultPassedInAndNotFoundInThemeCatalog() {
+ assertTrue("bogus msg from theme resourcebundle with default msg passed in returned default msg",
+ getThemeMessage("bogus.message", null, "This is a default msg if not found in theme cat.", Locale.UK
+ )
+ .equals("This is a default msg if not found in theme cat."));
+ }
+
+ public void testThemeSourceNesting() throws NoSuchMessageException {
+ String overriddenMsg = getThemeMessage("theme.example2", null, null, Locale.UK);
+ MessageSource ms = ((ThemeSource) root).getTheme(AbstractThemeResolver.ORIGINAL_DEFAULT_THEME_NAME).getMessageSource();
+ String originalMsg = ms.getMessage("theme.example2", null, Locale.UK);
+ assertTrue("correct overridden msg", "test-message2".equals(overriddenMsg));
+ assertTrue("correct original msg", "message2".equals(originalMsg));
+ }
+
+ public void testThemeSourceNestingWithParentDefault() throws NoSuchMessageException {
+ StaticWebApplicationContext leaf = new StaticWebApplicationContext();
+ leaf.setParent(getApplicationContext());
+ leaf.refresh();
+ assertNotNull("theme still found", leaf.getTheme("theme"));
+ MessageSource ms = leaf.getTheme("theme").getMessageSource();
+ String msg = ms.getMessage("theme.example2", null, null, Locale.UK);
+ assertEquals("correct overridden msg", "test-message2", msg);
+ }
+
+ private String getThemeMessage(String code, Object args[], String defaultMessage, Locale locale) {
+ return themeMsgSource.getMessage(code, args, defaultMessage, locale);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/ServletConfigAwareBean.java b/org.springframework.testsuite/src/test/java/org/springframework/web/context/ServletConfigAwareBean.java
new file mode 100644
index 00000000000..5dfa1a7bacb
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/ServletConfigAwareBean.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.context;
+
+import javax.servlet.ServletConfig;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class ServletConfigAwareBean implements ServletConfigAware {
+
+ private ServletConfig servletConfig;
+
+ public void setServletConfig(ServletConfig servletConfig) {
+ this.servletConfig = servletConfig;
+ }
+
+ public ServletConfig getServletConfig() {
+ return servletConfig;
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/ServletContextAwareBean.java b/org.springframework.testsuite/src/test/java/org/springframework/web/context/ServletContextAwareBean.java
new file mode 100644
index 00000000000..ecaaae502bc
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/ServletContextAwareBean.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.context;
+
+import javax.servlet.ServletContext;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class ServletContextAwareBean implements ServletContextAware {
+
+ private ServletContext servletContext;
+
+ public void setServletContext(ServletContext servletContext) {
+ this.servletContext = servletContext;
+ }
+
+ public ServletContext getServletContext() {
+ return servletContext;
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/ServletContextAwareProcessorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/context/ServletContextAwareProcessorTests.java
new file mode 100644
index 00000000000..3b68b7508ea
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/ServletContextAwareProcessorTests.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.context;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.MockServletConfig;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.web.context.support.ServletContextAwareProcessor;
+
+/**
+ * @author Juergen Hoeller
+ * @author Mark Fisher
+ */
+public class ServletContextAwareProcessorTests extends TestCase {
+
+ public void testServletContextAwareWithServletContext() {
+ ServletContext servletContext = new MockServletContext();
+ ServletContextAwareProcessor processor = new ServletContextAwareProcessor(servletContext);
+ ServletContextAwareBean bean = new ServletContextAwareBean();
+ assertNull(bean.getServletContext());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNotNull("ServletContext should have been set", bean.getServletContext());
+ assertEquals(servletContext, bean.getServletContext());
+ }
+
+ public void testServletContextAwareWithServletConfig() {
+ ServletContext servletContext = new MockServletContext();
+ ServletConfig servletConfig = new MockServletConfig(servletContext);
+ ServletContextAwareProcessor processor = new ServletContextAwareProcessor(servletConfig);
+ ServletContextAwareBean bean = new ServletContextAwareBean();
+ assertNull(bean.getServletContext());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNotNull("ServletContext should have been set", bean.getServletContext());
+ assertEquals(servletContext, bean.getServletContext());
+ }
+
+ public void testServletContextAwareWithServletContextAndServletConfig() {
+ ServletContext servletContext = new MockServletContext();
+ ServletConfig servletConfig = new MockServletConfig(servletContext);
+ ServletContextAwareProcessor processor = new ServletContextAwareProcessor(servletContext, servletConfig);
+ ServletContextAwareBean bean = new ServletContextAwareBean();
+ assertNull(bean.getServletContext());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNotNull("ServletContext should have been set", bean.getServletContext());
+ assertEquals(servletContext, bean.getServletContext());
+ }
+
+ public void testServletContextAwareWithNullServletContextAndNonNullServletConfig() {
+ ServletContext servletContext = new MockServletContext();
+ ServletConfig servletConfig = new MockServletConfig(servletContext);
+ ServletContextAwareProcessor processor = new ServletContextAwareProcessor(null, servletConfig);
+ ServletContextAwareBean bean = new ServletContextAwareBean();
+ assertNull(bean.getServletContext());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNotNull("ServletContext should have been set", bean.getServletContext());
+ assertEquals(servletContext, bean.getServletContext());
+ }
+
+ public void testServletContextAwareWithNonNullServletContextAndNullServletConfig() {
+ ServletContext servletContext = new MockServletContext();
+ ServletContextAwareProcessor processor = new ServletContextAwareProcessor(servletContext, null);
+ ServletContextAwareBean bean = new ServletContextAwareBean();
+ assertNull(bean.getServletContext());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNotNull("ServletContext should have been set", bean.getServletContext());
+ assertEquals(servletContext, bean.getServletContext());
+ }
+
+ public void testServletContextAwareWithNullServletContext() {
+ ServletContext servletContext = null;
+ ServletContextAwareProcessor processor = new ServletContextAwareProcessor(servletContext);
+ ServletContextAwareBean bean = new ServletContextAwareBean();
+ assertNull(bean.getServletContext());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNull(bean.getServletContext());
+ }
+
+ public void testServletConfigAwareWithServletContextOnly() {
+ ServletContext servletContext = new MockServletContext();
+ ServletContextAwareProcessor processor = new ServletContextAwareProcessor(servletContext);
+ ServletConfigAwareBean bean = new ServletConfigAwareBean();
+ assertNull(bean.getServletConfig());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNull(bean.getServletConfig());
+ }
+
+ public void testServletConfigAwareWithServletConfig() {
+ ServletContext servletContext = new MockServletContext();
+ ServletConfig servletConfig = new MockServletConfig(servletContext);
+ ServletContextAwareProcessor processor = new ServletContextAwareProcessor(servletConfig);
+ ServletConfigAwareBean bean = new ServletConfigAwareBean();
+ assertNull(bean.getServletConfig());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNotNull("ServletConfig should have been set", bean.getServletConfig());
+ assertEquals(servletConfig, bean.getServletConfig());
+ }
+
+ public void testServletConfigAwareWithServletContextAndServletConfig() {
+ ServletContext servletContext = new MockServletContext();
+ ServletConfig servletConfig = new MockServletConfig(servletContext);
+ ServletContextAwareProcessor processor = new ServletContextAwareProcessor(servletContext, servletConfig);
+ ServletConfigAwareBean bean = new ServletConfigAwareBean();
+ assertNull(bean.getServletConfig());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNotNull("ServletConfig should have been set", bean.getServletConfig());
+ assertEquals(servletConfig, bean.getServletConfig());
+ }
+
+ public void testServletConfigAwareWithNullServletContextAndNonNullServletConfig() {
+ ServletContext servletContext = new MockServletContext();
+ ServletConfig servletConfig = new MockServletConfig(servletContext);
+ ServletContextAwareProcessor processor = new ServletContextAwareProcessor(null, servletConfig);
+ ServletConfigAwareBean bean = new ServletConfigAwareBean();
+ assertNull(bean.getServletConfig());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNotNull("ServletConfig should have been set", bean.getServletConfig());
+ assertEquals(servletConfig, bean.getServletConfig());
+ }
+
+ public void testServletConfigAwareWithNonNullServletContextAndNullServletConfig() {
+ ServletContext servletContext = new MockServletContext();
+ ServletContextAwareProcessor processor = new ServletContextAwareProcessor(servletContext, null);
+ ServletConfigAwareBean bean = new ServletConfigAwareBean();
+ assertNull(bean.getServletConfig());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNull(bean.getServletConfig());
+ }
+
+ public void testServletConfigAwareWithNullServletContext() {
+ ServletContext servletContext = null;
+ ServletContextAwareProcessor processor = new ServletContextAwareProcessor(servletContext);
+ ServletConfigAwareBean bean = new ServletConfigAwareBean();
+ assertNull(bean.getServletConfig());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNull(bean.getServletConfig());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/applicationContext.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/applicationContext.xml
new file mode 100644
index 00000000000..105055c2d68
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/applicationContext.xml
@@ -0,0 +1,81 @@
+
+
+]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ dummy
+
+
+ -1
+
+
+
+
+
+
+
+
+ true
+
+
+ &contextInclude;
+
+
+
+ /org/springframework/web/context/WEB-INF/myoverride.properties
+
+
+
+
+
+
+ classpath:/org/springframework/web/context/WEB-INF/myplace*.properties
+ classpath:/org/springframework/web/context/WEB-INF/myover*.properties
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/context-addition.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/context-addition.xml
new file mode 100644
index 00000000000..c888047524d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/context-addition.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Roderick
+ 31
+
+
+
+
+
+ Kerry
+ 34
+
+
+
+
+ typeMismatch
+ 34x
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+ listenerVeto
+ 66
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/context-messages.properties b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/context-messages.properties
new file mode 100644
index 00000000000..57aa4782a7b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/context-messages.properties
@@ -0,0 +1,6 @@
+code1=message1
+code2=message2
+
+# Example taken from the javadocs for the java.text.MessageFormat class
+message.format.example1=At '{1,time}' on "{1,date}", there was "{2}" on planet {0,number,integer}.
+message.format.example2=This is a test message in the message catalog with no args.
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/context-messages_en_GB.properties b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/context-messages_en_GB.properties
new file mode 100644
index 00000000000..623a71a8401
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/context-messages_en_GB.properties
@@ -0,0 +1,2 @@
+# Example taken from the javadocs for the java.text.MessageFormat class
+message.format.example1=At '{1,time}' on "{1,date}", there was "{2}" on station number {0,number,integer}.
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/context-messages_en_US.properties b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/context-messages_en_US.properties
new file mode 100644
index 00000000000..2bdc0944860
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/context-messages_en_US.properties
@@ -0,0 +1,5 @@
+code1=message1
+
+# Example taken from the javadocs for the java.text.MessageFormat class
+message.format.example1=At '{1,time}' on "{1,date}", there was "{2}" on planet {0,number,integer}.
+message.format.example2=This is a test message in the message catalog with no args.
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/contextInclude.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/contextInclude.xml
new file mode 100644
index 00000000000..2e4938383be
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/contextInclude.xml
@@ -0,0 +1,6 @@
+
+
+
+ yetanotherdummy
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/empty-servlet.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/empty-servlet.xml
new file mode 100644
index 00000000000..b49584e11dd
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/empty-servlet.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/fail.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/fail.xml
new file mode 100644
index 00000000000..54d05ef2a3b
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/fail.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/more-context-messages.properties b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/more-context-messages.properties
new file mode 100644
index 00000000000..c703c78757c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/more-context-messages.properties
@@ -0,0 +1,2 @@
+code1=message1x
+code3=message3
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/myoverride.properties b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/myoverride.properties
new file mode 100644
index 00000000000..62b6240c8ef
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/myoverride.properties
@@ -0,0 +1,3 @@
+father.name=Albert
+rod.age=31
+rod.name=Roderick
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/myplaceholder.properties b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/myplaceholder.properties
new file mode 100644
index 00000000000..1d454bdb1a2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/myplaceholder.properties
@@ -0,0 +1,4 @@
+useCodeAsDefaultMessage=false
+message-file=context-messages
+objectName=test:service=myservice
+theme-base=org/springframework/web/context/WEB-INF/
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/resources/messageSource.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/resources/messageSource.xml
new file mode 100644
index 00000000000..a40e827ba9a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/resources/messageSource.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+ ${useCodeAsDefaultMessage}
+
+
+
+ org/springframework/web/context/WEB-INF/${message-file}
+ org/springframework/web/context/WEB-INF/more-context-messages
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/resources/themeSource.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/resources/themeSource.xml
new file mode 100644
index 00000000000..1e7d04517db
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/resources/themeSource.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+ ${theme-base}
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/sessionContext.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/sessionContext.xml
new file mode 100644
index 00000000000..7da590d1f21
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/sessionContext.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/test-messages.properties b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/test-messages.properties
new file mode 100644
index 00000000000..98686bf3827
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/test-messages.properties
@@ -0,0 +1 @@
+code2=message2
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/test-servlet.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/test-servlet.xml
new file mode 100644
index 00000000000..115e118427a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/test-servlet.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+ org/springframework/web/context/WEB-INF/test-messages
+
+
+
+ org/springframework/web/context/WEB-INF/test-
+
+
+
+
+
+
+
+ Rod
+ 31
+
+
+
+
+
+
+ Roderick
+ 31
+
+
+
+
+
+ Kerry
+ 34
+
+
+
+
+ typeMismatch
+ 34x
+
+
+
+
+
+
+
+ false
+
+
+
+ listenerVeto
+ 66
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/test-theme.properties b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/test-theme.properties
new file mode 100644
index 00000000000..019517d124f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/test-theme.properties
@@ -0,0 +1 @@
+theme.example2=test-message2
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/testNamespace.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/testNamespace.xml
new file mode 100644
index 00000000000..dd10e5fcab7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/testNamespace.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+ Rod
+ 31
+
+
+
+ Kerry
+ 34
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/theme.properties b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/theme.properties
new file mode 100644
index 00000000000..8e5e4c2614d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/theme.properties
@@ -0,0 +1,2 @@
+theme.example1=This is a test message in the theme message catalog with no args.
+theme.example2=message2
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/theme_en_GB.properties b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/theme_en_GB.properties
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/theme_en_US.properties b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/theme_en_US.properties
new file mode 100644
index 00000000000..cbe5be548d2
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/theme_en_US.properties
@@ -0,0 +1 @@
+theme.example1=This is a test message in the theme message catalog.
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/web.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/web.xml
new file mode 100644
index 00000000000..1d412973bea
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/WEB-INF/web.xml
@@ -0,0 +1,151 @@
+
+
+
+
+ ticket-webapp
+ Web interface for ticket application
+
+
+
+
+
+
+
+
+ config
+ org.springframework.framework.web.context.ContextLoaderServlet
+
+ contextClass
+ org.springframework.framework.web.context.XMLWebApplicationContext
+
+
+ log4jPropertiesUrl
+ /WEB-INF/log4j_PRODUCTION.properties
+
+
+ 1
+
+
+
+
+ boxOffice
+ org.springframework.framework.web.workflow.CommandServlet
+
+
+
+
+
+
+ boxOffice
+ /*.html
+
+
+
+ config
+ /context/context.html
+
+
+
+
+60
+
+
+
+
+ /welcome.jsp
+
+
+
+ 403
+ /jsp/layout/twocolumn/403-Forbidden.jsp
+
+
+
+ 404
+ /jsp/layout/twocolumn/404-NotFound.jsp
+
+
+
+ java.lang.Throwable
+ /jsp/layout/twocolumn/uncaughtException.jsp
+
+
+
+ /bind
+ /WEB-INF/tlds/b11.tld
+
+
+
+ /events
+ /WEB-INF/tlds/event11.tld
+
+
+
+
+ SalesInfo
+
+ purchase.html
+ GET
+ POST
+
+
+ registeredUsers
+
+
+ NONE
+
+
+
+
+
+ FORM
+
+
+ ticket
+
+
+ login.jsp
+ loginError.jsp
+
+
+
+
+
+ registeredUsers
+
+
+
+
+
+
+ ejb/FixtureManager
+ Session
+ com.wrox.j2eedd.ticket.ejb.fixturemanager.FixtureManagerRemoteHome
+ com.wrox.j2eedd.ticket.ejb.fixturemanager.FixtureManagerRemote
+ FixtureManager
+
+
+
+
+ ejb/BoxOffice
+ Session
+ com.wrox.j2eedd.ticket.ejb.booking.BoxOfficeRemoteHome
+ com.wrox.j2eedd.ticket.ejb.booking.BoxOfficeRemote
+ BookingManager
+
+
+
+ ejb/CustomerManager
+ Session
+ com.wrox.j2eedd.ticket.ejb.customer.CustomerManagerRemoteHoms
+ com.wrox.j2eedd.ticket.ejb.customer.CustomerManagerRemote
+ CustomerManager
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/XmlWebApplicationContextTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/context/XmlWebApplicationContextTests.java
new file mode 100644
index 00000000000..16270d62a4a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/XmlWebApplicationContextTests.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.web.context;
+
+import java.util.Locale;
+
+import javax.servlet.ServletException;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.context.AbstractApplicationContextTests;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.NoSuchMessageException;
+import org.springframework.context.TestListener;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.web.context.support.XmlWebApplicationContext;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public class XmlWebApplicationContextTests extends AbstractApplicationContextTests {
+
+ private ConfigurableWebApplicationContext root;
+
+ protected ConfigurableApplicationContext createContext() throws Exception {
+ InitAndIB.constructed = false;
+ root = new XmlWebApplicationContext();
+ MockServletContext sc = new MockServletContext("");
+ root.setServletContext(sc);
+ root.setConfigLocations(new String[] {"/org/springframework/web/context/WEB-INF/applicationContext.xml"});
+ root.addBeanFactoryPostProcessor(new BeanFactoryPostProcessor() {
+ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
+ beanFactory.addBeanPostProcessor(new BeanPostProcessor() {
+ public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
+ if (bean instanceof TestBean) {
+ ((TestBean) bean).getFriends().add("myFriend");
+ }
+ return bean;
+ }
+ public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
+ return bean;
+ }
+ });
+ }
+ });
+ root.refresh();
+ XmlWebApplicationContext wac = new XmlWebApplicationContext();
+ wac.setParent(root);
+ wac.setServletContext(sc);
+ wac.setNamespace("test-servlet");
+ wac.setConfigLocations(new String[] {"/org/springframework/web/context/WEB-INF/test-servlet.xml"});
+ wac.refresh();
+ return wac;
+ }
+
+ /**
+ * Overridden as we can't trust superclass method
+ * @see org.springframework.context.AbstractApplicationContextTests#testEvents()
+ */
+ public void testEvents() throws Exception {
+ TestListener listener = (TestListener) this.applicationContext.getBean("testListener");
+ listener.zeroCounter();
+ TestListener parentListener = (TestListener) this.applicationContext.getParent().getBean("parentListener");
+ parentListener.zeroCounter();
+
+ parentListener.zeroCounter();
+ assertTrue("0 events before publication", listener.getEventCount() == 0);
+ assertTrue("0 parent events before publication", parentListener.getEventCount() == 0);
+ this.applicationContext.publishEvent(new MyEvent(this));
+ assertTrue("1 events after publication, not " + listener.getEventCount(), listener.getEventCount() == 1);
+ assertTrue("1 parent events after publication", parentListener.getEventCount() == 1);
+ }
+
+ public void testCount() {
+ assertTrue("should have 14 beans, not "+ this.applicationContext.getBeanDefinitionCount(),
+ this.applicationContext.getBeanDefinitionCount() == 14);
+ }
+
+ public void testWithoutMessageSource() throws Exception {
+ MockServletContext sc = new MockServletContext("");
+ XmlWebApplicationContext wac = new XmlWebApplicationContext();
+ wac.setParent(root);
+ wac.setServletContext(sc);
+ wac.setNamespace("testNamespace");
+ wac.setConfigLocations(new String[] {"/org/springframework/web/context/WEB-INF/test-servlet.xml"});
+ wac.refresh();
+ try {
+ wac.getMessage("someMessage", null, Locale.getDefault());
+ fail("Should have thrown NoSuchMessageException");
+ }
+ catch (NoSuchMessageException ex) {
+ // expected;
+ }
+ String msg = wac.getMessage("someMessage", null, "default", Locale.getDefault());
+ assertTrue("Default message returned", "default".equals(msg));
+ }
+
+ public void testContextNesting() {
+ TestBean father = (TestBean) this.applicationContext.getBean("father");
+ assertTrue("Bean from root context", father != null);
+ assertTrue("Custom BeanPostProcessor applied", father.getFriends().contains("myFriend"));
+
+ TestBean rod = (TestBean) this.applicationContext.getBean("rod");
+ assertTrue("Bean from child context", "Rod".equals(rod.getName()));
+ assertTrue("Bean has external reference", rod.getSpouse() == father);
+ assertTrue("Custom BeanPostProcessor not applied", !rod.getFriends().contains("myFriend"));
+
+ rod = (TestBean) this.root.getBean("rod");
+ assertTrue("Bean from root context", "Roderick".equals(rod.getName()));
+ assertTrue("Custom BeanPostProcessor applied", rod.getFriends().contains("myFriend"));
+ }
+
+ public void testInitializingBeanAndInitMethod() throws Exception {
+ assertFalse(InitAndIB.constructed);
+ InitAndIB iib = (InitAndIB) this.applicationContext.getBean("init-and-ib");
+ assertTrue(InitAndIB.constructed);
+ assertTrue(iib.afterPropertiesSetInvoked && iib.initMethodInvoked);
+ assertTrue(!iib.destroyed && !iib.customDestroyed);
+ this.applicationContext.close();
+ assertTrue(!iib.destroyed && !iib.customDestroyed);
+ ConfigurableApplicationContext parent = (ConfigurableApplicationContext) this.applicationContext.getParent();
+ parent.close();
+ assertTrue(iib.destroyed && iib.customDestroyed);
+ parent.close();
+ assertTrue(iib.destroyed && iib.customDestroyed);
+ }
+
+
+ public static class InitAndIB implements InitializingBean, DisposableBean {
+
+ public static boolean constructed;
+
+ public boolean afterPropertiesSetInvoked, initMethodInvoked, destroyed, customDestroyed;
+
+ public InitAndIB() {
+ constructed = true;
+ }
+
+ public void afterPropertiesSet() {
+ if (this.initMethodInvoked)
+ fail();
+ this.afterPropertiesSetInvoked = true;
+ }
+
+ /** Init method */
+ public void customInit() throws ServletException {
+ if (!this.afterPropertiesSetInvoked)
+ fail();
+ this.initMethodInvoked = true;
+ }
+
+ public void destroy() {
+ if (this.customDestroyed)
+ fail();
+ if (this.destroyed) {
+ throw new IllegalStateException("Already destroyed");
+ }
+ this.destroyed = true;
+ }
+
+ public void customDestroy() {
+ if (!this.destroyed)
+ fail();
+ if (this.customDestroyed) {
+ throw new IllegalStateException("Already customDestroyed");
+ }
+ this.customDestroyed = true;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/RequestAndSessionScopedProxyTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/RequestAndSessionScopedProxyTests.java
new file mode 100644
index 00000000000..bdd42b60a07
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/RequestAndSessionScopedProxyTests.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.context.request;
+
+import javax.servlet.http.HttpServletRequest;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import org.springframework.web.context.support.StaticWebApplicationContext;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public class RequestAndSessionScopedProxyTests extends TestCase {
+
+ public void testPutBeanInRequest() throws Exception {
+ String targetBeanName = "target";
+
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
+ bd.setScope(WebApplicationContext.SCOPE_REQUEST);
+ bd.getPropertyValues().addPropertyValue("name", "abc");
+ wac.registerBeanDefinition(targetBeanName, bd);
+ wac.refresh();
+
+ HttpServletRequest request = new MockHttpServletRequest();
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
+ TestBean target = (TestBean) wac.getBean(targetBeanName);
+ assertEquals("abc", target.getName());
+ assertSame(target, request.getAttribute(targetBeanName));
+
+ TestBean target2 = (TestBean) wac.getBean(targetBeanName);
+ assertEquals("abc", target2.getName());
+ assertSame(target2, target);
+ assertSame(target2, request.getAttribute(targetBeanName));
+
+ request = new MockHttpServletRequest();
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
+ TestBean target3 = (TestBean) wac.getBean(targetBeanName);
+ assertEquals("abc", target3.getName());
+ assertSame(target3, request.getAttribute(targetBeanName));
+ assertNotSame(target3, target);
+
+ RequestContextHolder.setRequestAttributes(null);
+ try {
+ wac.getBean(targetBeanName);
+ fail("Should have thrown BeanCreationException");
+ }
+ catch (BeanCreationException ex) {
+ // expected
+ }
+ }
+
+ public void testPutBeanInSession() throws Exception {
+ String targetBeanName = "target";
+ HttpServletRequest request = new MockHttpServletRequest();
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
+
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
+ bd.setScope(WebApplicationContext.SCOPE_SESSION);
+ bd.getPropertyValues().addPropertyValue("name", "abc");
+ wac.registerBeanDefinition(targetBeanName, bd);
+ wac.refresh();
+
+ TestBean target = (TestBean) wac.getBean(targetBeanName);
+ assertEquals("abc", target.getName());
+ assertSame(target, request.getSession().getAttribute(targetBeanName));
+
+ RequestContextHolder.setRequestAttributes(null);
+ try {
+ wac.getBean(targetBeanName);
+ fail("Should have thrown BeanCreationException");
+ }
+ catch (BeanCreationException ex) {
+ // expected
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/RequestContextListenerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/RequestContextListenerTests.java
new file mode 100644
index 00000000000..a84c73d83d8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/RequestContextListenerTests.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.context.request;
+
+import javax.servlet.ServletRequestEvent;
+
+import junit.framework.TestCase;
+
+import org.springframework.core.task.MockRunnable;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockServletContext;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class RequestContextListenerTests extends TestCase {
+
+ public void testRequestContextListenerWithSameThread() {
+ RequestContextListener listener = new RequestContextListener();
+ MockServletContext context = new MockServletContext();
+ MockHttpServletRequest request = new MockHttpServletRequest(context);
+ request.setAttribute("test", "value");
+
+ assertNull(RequestContextHolder.getRequestAttributes());
+ listener.requestInitialized(new ServletRequestEvent(context, request));
+ assertNotNull(RequestContextHolder.getRequestAttributes());
+ assertEquals("value",
+ RequestContextHolder.getRequestAttributes().getAttribute("test", RequestAttributes.SCOPE_REQUEST));
+ MockRunnable runnable = new MockRunnable();
+ RequestContextHolder.getRequestAttributes().registerDestructionCallback(
+ "test", runnable, RequestAttributes.SCOPE_REQUEST);
+
+ listener.requestDestroyed(new ServletRequestEvent(context, request));
+ assertNull(RequestContextHolder.getRequestAttributes());
+ assertTrue(runnable.wasExecuted());
+ }
+
+ public void testRequestContextListenerWithSameThreadAndAttributesGone() {
+ RequestContextListener listener = new RequestContextListener();
+ MockServletContext context = new MockServletContext();
+ MockHttpServletRequest request = new MockHttpServletRequest(context);
+ request.setAttribute("test", "value");
+
+ assertNull(RequestContextHolder.getRequestAttributes());
+ listener.requestInitialized(new ServletRequestEvent(context, request));
+ assertNotNull(RequestContextHolder.getRequestAttributes());
+ assertEquals("value",
+ RequestContextHolder.getRequestAttributes().getAttribute("test", RequestAttributes.SCOPE_REQUEST));
+ MockRunnable runnable = new MockRunnable();
+ RequestContextHolder.getRequestAttributes().registerDestructionCallback(
+ "test", runnable, RequestAttributes.SCOPE_REQUEST);
+
+ request.clearAttributes();
+ listener.requestDestroyed(new ServletRequestEvent(context, request));
+ assertNull(RequestContextHolder.getRequestAttributes());
+ assertTrue(runnable.wasExecuted());
+ }
+
+ public void testRequestContextListenerWithDifferentThread() {
+ final RequestContextListener listener = new RequestContextListener();
+ final MockServletContext context = new MockServletContext();
+ final MockHttpServletRequest request = new MockHttpServletRequest(context);
+ request.setAttribute("test", "value");
+
+ assertNull(RequestContextHolder.getRequestAttributes());
+ listener.requestInitialized(new ServletRequestEvent(context, request));
+ assertNotNull(RequestContextHolder.getRequestAttributes());
+ assertEquals("value",
+ RequestContextHolder.getRequestAttributes().getAttribute("test", RequestAttributes.SCOPE_REQUEST));
+ MockRunnable runnable = new MockRunnable();
+ RequestContextHolder.getRequestAttributes().registerDestructionCallback(
+ "test", runnable, RequestAttributes.SCOPE_REQUEST);
+
+ // Execute requestDestroyed callback in different thread.
+ Thread thread = new Thread() {
+ public void run() {
+ listener.requestDestroyed(new ServletRequestEvent(context, request));
+ }
+ };
+ thread.start();
+ try {
+ thread.join();
+ }
+ catch (InterruptedException ex) {
+ }
+ // Still bound to original thread, but at least completed.
+ assertNotNull(RequestContextHolder.getRequestAttributes());
+ assertTrue(runnable.wasExecuted());
+
+ // Check that a repeated execution in the same thread works and performs cleanup.
+ listener.requestInitialized(new ServletRequestEvent(context, request));
+ listener.requestDestroyed(new ServletRequestEvent(context, request));
+ assertNull(RequestContextHolder.getRequestAttributes());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/RequestScopeTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/RequestScopeTests.java
new file mode 100644
index 00000000000..ecf5b153ff1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/RequestScopeTests.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.context.request;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.DerivedTestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.BeanCurrentlyInCreationException;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.mock.web.MockHttpServletRequest;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ * @author Mark Fisher
+ * @since 2.0
+ */
+public class RequestScopeTests extends TestCase {
+
+ private DefaultListableBeanFactory beanFactory;
+
+ protected void setUp() throws Exception {
+ this.beanFactory = new DefaultListableBeanFactory();
+ this.beanFactory.registerScope("request", new RequestScope());
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this.beanFactory);
+ reader.loadBeanDefinitions(new ClassPathResource("requestScopeTests.xml", getClass()));
+ this.beanFactory.preInstantiateSingletons();
+ }
+
+ public void testGetFromScope() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ RequestAttributes requestAttributes = new ServletRequestAttributes(request);
+ RequestContextHolder.setRequestAttributes(requestAttributes);
+
+ try {
+ String name = "requestScopedObject";
+ assertNull(request.getAttribute(name));
+ TestBean bean = (TestBean) this.beanFactory.getBean(name);
+ assertSame(bean, request.getAttribute(name));
+ assertSame(bean, this.beanFactory.getBean(name));
+ }
+ finally {
+ RequestContextHolder.setRequestAttributes(null);
+ }
+ }
+
+ public void testDestructionAtRequestCompletion() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
+ RequestContextHolder.setRequestAttributes(requestAttributes);
+
+ try {
+ String name = "requestScopedDisposableObject";
+ assertNull(request.getAttribute(name));
+ DerivedTestBean bean = (DerivedTestBean) this.beanFactory.getBean(name);
+ assertSame(bean, request.getAttribute(name));
+ assertSame(bean, this.beanFactory.getBean(name));
+
+ requestAttributes.requestCompleted();
+ assertTrue(bean.wasDestroyed());
+ }
+ finally {
+ RequestContextHolder.setRequestAttributes(null);
+ }
+ }
+
+ public void testGetFromFactoryBeanInScope() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ RequestAttributes requestAttributes = new ServletRequestAttributes(request);
+ RequestContextHolder.setRequestAttributes(requestAttributes);
+
+ try {
+ String name = "requestScopedFactoryBean";
+ assertNull(request.getAttribute(name));
+ TestBean bean = (TestBean) this.beanFactory.getBean(name);
+ assertTrue(request.getAttribute(name) instanceof FactoryBean);
+ assertSame(bean, this.beanFactory.getBean(name));
+ }
+ finally {
+ RequestContextHolder.setRequestAttributes(null);
+ }
+ }
+
+ public void testCircleLeadsToException() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ RequestAttributes requestAttributes = new ServletRequestAttributes(request);
+ RequestContextHolder.setRequestAttributes(requestAttributes);
+
+ try {
+ String name = "requestScopedObjectCircle1";
+ assertNull(request.getAttribute(name));
+ this.beanFactory.getBean(name);
+ fail("Should have thrown BeanCreationException");
+ }
+ catch (BeanCreationException ex) {
+ // expected
+ assertTrue(ex.contains(BeanCurrentlyInCreationException.class));
+ }
+ finally {
+ RequestContextHolder.setRequestAttributes(null);
+ }
+ }
+
+ public void testInnerBeanInheritsContainingBeanScopeByDefault() {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
+ RequestContextHolder.setRequestAttributes(requestAttributes);
+
+ try {
+ String outerBeanName = "requestScopedOuterBean";
+ assertNull(request.getAttribute(outerBeanName));
+ TestBean outer1 = (TestBean) this.beanFactory.getBean(outerBeanName);
+ assertNotNull(request.getAttribute(outerBeanName));
+ TestBean inner1 = (TestBean) outer1.getSpouse();
+ assertSame(outer1, this.beanFactory.getBean(outerBeanName));
+ requestAttributes.requestCompleted();
+ assertTrue(outer1.wasDestroyed());
+ assertTrue(inner1.wasDestroyed());
+ request = new MockHttpServletRequest();
+ requestAttributes = new ServletRequestAttributes(request);
+ RequestContextHolder.setRequestAttributes(requestAttributes);
+ TestBean outer2 = (TestBean) this.beanFactory.getBean(outerBeanName);
+ assertNotSame(outer1, outer2);
+ assertNotSame(inner1, outer2.getSpouse());
+ }
+ finally {
+ RequestContextHolder.setRequestAttributes(null);
+ }
+ }
+
+ public void testRequestScopedInnerBeanDestroyedWhileContainedBySingleton() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
+ RequestContextHolder.setRequestAttributes(requestAttributes);
+
+ try {
+ String outerBeanName = "singletonOuterBean";
+ TestBean outer1 = (TestBean) this.beanFactory.getBean(outerBeanName);
+ assertNull(request.getAttribute(outerBeanName));
+ TestBean inner1 = (TestBean) outer1.getSpouse();
+ TestBean outer2 = (TestBean) this.beanFactory.getBean(outerBeanName);
+ assertSame(outer1, outer2);
+ assertSame(inner1, outer2.getSpouse());
+ requestAttributes.requestCompleted();
+ assertTrue(inner1.wasDestroyed());
+ assertFalse(outer1.wasDestroyed());
+ }
+ finally {
+ RequestContextHolder.setRequestAttributes(null);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/RequestScopedProxyTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/RequestScopedProxyTests.java
new file mode 100644
index 00000000000..1ba7a8d0a6a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/RequestScopedProxyTests.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.web.context.request;
+
+import junit.framework.TestCase;
+
+import org.springframework.aop.support.AopUtils;
+import org.springframework.beans.DerivedTestBean;
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.DummyFactory;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.BeanDefinitionHolder;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.mock.web.MockHttpServletRequest;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class RequestScopedProxyTests extends TestCase {
+
+ private DefaultListableBeanFactory beanFactory;
+
+ protected void setUp() throws Exception {
+ this.beanFactory = new DefaultListableBeanFactory();
+ this.beanFactory.registerScope("request", new RequestScope());
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this.beanFactory);
+ reader.loadBeanDefinitions(new ClassPathResource("requestScopedProxyTests.xml", getClass()));
+ this.beanFactory.preInstantiateSingletons();
+ }
+
+ public void testGetFromScope() throws Exception {
+ String name = "requestScopedObject";
+ TestBean bean = (TestBean) this.beanFactory.getBean(name);
+ assertTrue(AopUtils.isCglibProxy(bean));
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ RequestAttributes requestAttributes = new ServletRequestAttributes(request);
+ RequestContextHolder.setRequestAttributes(requestAttributes);
+
+ try {
+ assertNull(request.getAttribute("scopedTarget." + name));
+ assertEquals("scoped", bean.getName());
+ assertNotNull(request.getAttribute("scopedTarget." + name));
+ assertEquals(TestBean.class, request.getAttribute("scopedTarget." + name).getClass());
+ assertEquals("scoped", ((TestBean) request.getAttribute("scopedTarget." + name)).getName());
+ assertSame(bean, this.beanFactory.getBean(name));
+ }
+ finally {
+ RequestContextHolder.setRequestAttributes(null);
+ }
+ }
+
+ public void testGetFromScopeThroughDynamicProxy() throws Exception {
+ String name = "requestScopedProxy";
+ ITestBean bean = (ITestBean) this.beanFactory.getBean(name);
+ assertTrue(AopUtils.isJdkDynamicProxy(bean));
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ RequestAttributes requestAttributes = new ServletRequestAttributes(request);
+ RequestContextHolder.setRequestAttributes(requestAttributes);
+
+ try {
+ assertNull(request.getAttribute("scopedTarget." + name));
+ assertEquals("scoped", bean.getName());
+ assertNotNull(request.getAttribute("scopedTarget." + name));
+ assertEquals(TestBean.class, request.getAttribute("scopedTarget." + name).getClass());
+ assertEquals("scoped", ((TestBean) request.getAttribute("scopedTarget." + name)).getName());
+ assertSame(bean, this.beanFactory.getBean(name));
+ }
+ finally {
+ RequestContextHolder.setRequestAttributes(null);
+ }
+ }
+
+ public void testDestructionAtRequestCompletion() throws Exception {
+ String name = "requestScopedDisposableObject";
+ DerivedTestBean bean = (DerivedTestBean) this.beanFactory.getBean(name);
+ assertTrue(AopUtils.isCglibProxy(bean));
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
+ RequestContextHolder.setRequestAttributes(requestAttributes);
+
+ try {
+ assertNull(request.getAttribute("scopedTarget." + name));
+ assertEquals("scoped", bean.getName());
+ assertNotNull(request.getAttribute("scopedTarget." + name));
+ assertEquals(DerivedTestBean.class, request.getAttribute("scopedTarget." + name).getClass());
+ assertEquals("scoped", ((TestBean) request.getAttribute("scopedTarget." + name)).getName());
+ assertSame(bean, this.beanFactory.getBean(name));
+
+ requestAttributes.requestCompleted();
+ assertTrue(((TestBean) request.getAttribute("scopedTarget." + name)).wasDestroyed());
+ }
+ finally {
+ RequestContextHolder.setRequestAttributes(null);
+ }
+ }
+
+ public void testGetFromFactoryBeanInScope() throws Exception {
+ String name = "requestScopedFactoryBean";
+ TestBean bean = (TestBean) this.beanFactory.getBean(name);
+ assertTrue(AopUtils.isCglibProxy(bean));
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ RequestAttributes requestAttributes = new ServletRequestAttributes(request);
+ RequestContextHolder.setRequestAttributes(requestAttributes);
+
+ try {
+ assertNull(request.getAttribute("scopedTarget." + name));
+ assertEquals(DummyFactory.SINGLETON_NAME, bean.getName());
+ assertNotNull(request.getAttribute("scopedTarget." + name));
+ assertEquals(DummyFactory.class, request.getAttribute("scopedTarget." + name).getClass());
+ assertSame(bean, this.beanFactory.getBean(name));
+ }
+ finally {
+ RequestContextHolder.setRequestAttributes(null);
+ }
+ }
+
+ public void testGetInnerBeanFromScope() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("outerBean");
+ assertFalse(AopUtils.isAopProxy(bean));
+ assertTrue(AopUtils.isCglibProxy(bean.getSpouse()));
+
+ String name = "scopedInnerBean";
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ RequestAttributes requestAttributes = new ServletRequestAttributes(request);
+ RequestContextHolder.setRequestAttributes(requestAttributes);
+
+ try {
+ assertNull(request.getAttribute("scopedTarget." + name));
+ assertEquals("scoped", bean.getSpouse().getName());
+ assertNotNull(request.getAttribute("scopedTarget." + name));
+ assertEquals(TestBean.class, request.getAttribute("scopedTarget." + name).getClass());
+ assertEquals("scoped", ((TestBean) request.getAttribute("scopedTarget." + name)).getName());
+ }
+ finally {
+ RequestContextHolder.setRequestAttributes(null);
+ }
+ }
+
+ public void testGetAnonymousInnerBeanFromScope() throws Exception {
+ TestBean bean = (TestBean) this.beanFactory.getBean("outerBean");
+ assertFalse(AopUtils.isAopProxy(bean));
+ assertTrue(AopUtils.isCglibProxy(bean.getSpouse()));
+
+ BeanDefinition beanDef = this.beanFactory.getBeanDefinition("outerBean");
+ BeanDefinitionHolder innerBeanDef =
+ (BeanDefinitionHolder) beanDef.getPropertyValues().getPropertyValue("spouse").getValue();
+ String name = innerBeanDef.getBeanName();
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ RequestAttributes requestAttributes = new ServletRequestAttributes(request);
+ RequestContextHolder.setRequestAttributes(requestAttributes);
+
+ try {
+ assertNull(request.getAttribute("scopedTarget." + name));
+ assertEquals("scoped", bean.getSpouse().getName());
+ assertNotNull(request.getAttribute("scopedTarget." + name));
+ assertEquals(TestBean.class, request.getAttribute("scopedTarget." + name).getClass());
+ assertEquals("scoped", ((TestBean) request.getAttribute("scopedTarget." + name)).getName());
+ }
+ finally {
+ RequestContextHolder.setRequestAttributes(null);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/ServletRequestAttributesTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/ServletRequestAttributesTests.java
new file mode 100644
index 00000000000..d6c83b12387
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/ServletRequestAttributesTests.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.web.context.request;
+
+import java.io.Serializable;
+
+import javax.servlet.http.HttpServletRequest;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpSession;
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class ServletRequestAttributesTests extends TestCase {
+
+ private static final String KEY = "ThatThingThatThing";
+
+
+ private static final Serializable VALUE = new Serializable() {
+ };
+
+
+ public void testCtorRejectsNullArg() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new ServletRequestAttributes(null);
+ }
+ }.runTest();
+ }
+
+ public void testUpdateAccessedAttributes() throws Exception {
+ MockHttpSession session = new MockHttpSession();
+ session.setAttribute(KEY, VALUE);
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setSession(session);
+ ServletRequestAttributes attrs = new ServletRequestAttributes(request);
+ Object value = attrs.getAttribute(KEY, RequestAttributes.SCOPE_SESSION);
+ assertSame(VALUE, value);
+ attrs.requestCompleted();
+ }
+
+ public void testSetRequestScopedAttribute() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ ServletRequestAttributes attrs = new ServletRequestAttributes(request);
+ attrs.setAttribute(KEY, VALUE, RequestAttributes.SCOPE_REQUEST);
+ Object value = request.getAttribute(KEY);
+ assertSame(VALUE, value);
+ }
+
+ public void testSetRequestScopedAttributeAfterCompletion() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ ServletRequestAttributes attrs = new ServletRequestAttributes(request);
+ request.close();
+ try {
+ attrs.setAttribute(KEY, VALUE, RequestAttributes.SCOPE_REQUEST);
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ public void testSetSessionScopedAttribute() throws Exception {
+ MockHttpSession session = new MockHttpSession();
+ session.setAttribute(KEY, VALUE);
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setSession(session);
+ ServletRequestAttributes attrs = new ServletRequestAttributes(request);
+ attrs.setAttribute(KEY, VALUE, RequestAttributes.SCOPE_SESSION);
+ Object value = session.getAttribute(KEY);
+ assertSame(VALUE, value);
+ }
+
+ public void testSetSessionScopedAttributeAfterCompletion() throws Exception {
+ MockHttpSession session = new MockHttpSession();
+ session.setAttribute(KEY, VALUE);
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setSession(session);
+ ServletRequestAttributes attrs = new ServletRequestAttributes(request);
+ attrs.requestCompleted();
+ request.close();
+ attrs.setAttribute(KEY, VALUE, RequestAttributes.SCOPE_SESSION);
+ Object value = session.getAttribute(KEY);
+ assertSame(VALUE, value);
+ }
+
+ public void testSetGlobalSessionScopedAttribute() throws Exception {
+ MockHttpSession session = new MockHttpSession();
+ session.setAttribute(KEY, VALUE);
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setSession(session);
+ ServletRequestAttributes attrs = new ServletRequestAttributes(request);
+ attrs.setAttribute(KEY, VALUE, RequestAttributes.SCOPE_GLOBAL_SESSION);
+ Object value = session.getAttribute(KEY);
+ assertSame(VALUE, value);
+ }
+
+ public void testSetGlobalSessionScopedAttributeAfterCompletion() throws Exception {
+ MockHttpSession session = new MockHttpSession();
+ session.setAttribute(KEY, VALUE);
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setSession(session);
+ ServletRequestAttributes attrs = new ServletRequestAttributes(request);
+ attrs.requestCompleted();
+ request.close();
+ attrs.setAttribute(KEY, VALUE, RequestAttributes.SCOPE_GLOBAL_SESSION);
+ Object value = session.getAttribute(KEY);
+ assertSame(VALUE, value);
+ }
+
+ public void testGetSessionScopedAttributeDoesNotForceCreationOfSession() throws Exception {
+ MockControl mockRequest = MockControl.createControl(HttpServletRequest.class);
+ HttpServletRequest request = (HttpServletRequest) mockRequest.getMock();
+ request.getSession(false);
+ mockRequest.setReturnValue(null, 1);
+ mockRequest.replay();
+
+ ServletRequestAttributes attrs = new ServletRequestAttributes(request);
+ Object value = attrs.getAttribute(KEY, RequestAttributes.SCOPE_SESSION);
+ assertNull(value);
+
+ mockRequest.verify();
+ }
+
+ public void testRemoveSessionScopedAttribute() throws Exception {
+ MockHttpSession session = new MockHttpSession();
+ session.setAttribute(KEY, VALUE);
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setSession(session);
+ ServletRequestAttributes attrs = new ServletRequestAttributes(request);
+ attrs.removeAttribute(KEY, RequestAttributes.SCOPE_SESSION);
+ Object value = session.getAttribute(KEY);
+ assertNull(value);
+ }
+
+ public void testRemoveSessionScopedAttributeDoesNotForceCreationOfSession() throws Exception {
+ MockControl mockRequest = MockControl.createControl(HttpServletRequest.class);
+ HttpServletRequest request = (HttpServletRequest) mockRequest.getMock();
+ request.getSession(false);
+ mockRequest.setReturnValue(null, 1);
+ mockRequest.replay();
+
+ ServletRequestAttributes attrs = new ServletRequestAttributes(request);
+ attrs.removeAttribute(KEY, RequestAttributes.SCOPE_SESSION);
+
+ mockRequest.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/ServletWebRequestTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/ServletWebRequestTests.java
new file mode 100644
index 00000000000..3280b533149
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/ServletWebRequestTests.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.context.request;
+
+import java.util.Locale;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.MockHttpServletRequest;
+
+/**
+ * @author Juergen Hoeller
+ * @since 26.07.2006
+ */
+public class ServletWebRequestTests extends TestCase {
+
+ public void testParameters() {
+ MockHttpServletRequest servletRequest = new MockHttpServletRequest();
+ servletRequest.addParameter("param1", "value1");
+ servletRequest.addParameter("param2", "value2");
+ servletRequest.addParameter("param2", "value2a");
+
+ ServletWebRequest request = new ServletWebRequest(servletRequest);
+ assertEquals("value1", request.getParameter("param1"));
+ assertEquals(1, request.getParameterValues("param1").length);
+ assertEquals("value1", request.getParameterValues("param1")[0]);
+ assertEquals("value2", request.getParameter("param2"));
+ assertEquals(2, request.getParameterValues("param2").length);
+ assertEquals("value2", request.getParameterValues("param2")[0]);
+ assertEquals("value2a", request.getParameterValues("param2")[1]);
+
+ Map paramMap = request.getParameterMap();
+ assertEquals(2, paramMap.size());
+ assertEquals(1, ((String[]) paramMap.get("param1")).length);
+ assertEquals("value1", ((String[]) paramMap.get("param1"))[0]);
+ assertEquals(2, ((String[]) paramMap.get("param2")).length);
+ assertEquals("value2", ((String[]) paramMap.get("param2"))[0]);
+ assertEquals("value2a", ((String[]) paramMap.get("param2"))[1]);
+ }
+
+ public void testLocale() {
+ MockHttpServletRequest servletRequest = new MockHttpServletRequest();
+ servletRequest.addPreferredLocale(Locale.UK);
+
+ ServletWebRequest request = new ServletWebRequest(servletRequest);
+ assertEquals(Locale.UK, request.getLocale());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/SessionScopeTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/SessionScopeTests.java
new file mode 100644
index 00000000000..b3d1d3925b9
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/SessionScopeTests.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.context.request;
+
+import java.io.Serializable;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.DerivedTestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.BeanNameAware;
+import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpSession;
+import org.springframework.util.SerializationTestUtils;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class SessionScopeTests extends TestCase {
+
+ private DefaultListableBeanFactory beanFactory;
+
+ protected void setUp() throws Exception {
+ this.beanFactory = new DefaultListableBeanFactory();
+ this.beanFactory.registerScope("session", new SessionScope());
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this.beanFactory);
+ reader.loadBeanDefinitions(new ClassPathResource("sessionScopeTests.xml", getClass()));
+ }
+
+ public void testGetFromScope() throws Exception {
+ MockHttpSession session = new MockHttpSession();
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setSession(session);
+ ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
+
+ RequestContextHolder.setRequestAttributes(requestAttributes);
+ try {
+ String name = "sessionScopedObject";
+ assertNull(session.getAttribute(name));
+ TestBean bean = (TestBean) this.beanFactory.getBean(name);
+ assertEquals(session.getAttribute(name), bean);
+ assertSame(bean, this.beanFactory.getBean(name));
+ }
+ finally {
+ RequestContextHolder.setRequestAttributes(null);
+ }
+ }
+
+ public void testDestructionAtSessionTermination() throws Exception {
+ MockHttpSession session = new MockHttpSession();
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setSession(session);
+ ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
+
+ RequestContextHolder.setRequestAttributes(requestAttributes);
+ try {
+ String name = "sessionScopedDisposableObject";
+ assertNull(session.getAttribute(name));
+ DerivedTestBean bean = (DerivedTestBean) this.beanFactory.getBean(name);
+ assertEquals(session.getAttribute(name), bean);
+ assertSame(bean, this.beanFactory.getBean(name));
+
+ requestAttributes.requestCompleted();
+ session.invalidate();
+ assertTrue(bean.wasDestroyed());
+ }
+ finally {
+ RequestContextHolder.setRequestAttributes(null);
+ }
+ }
+
+ public void testDestructionWithSessionSerialization() throws Exception {
+ doTestDestructionWithSessionSerialization(false);
+ }
+
+ public void testDestructionWithSessionSerializationAndBeanPostProcessor() throws Exception {
+ this.beanFactory.addBeanPostProcessor(new CustomDestructionAwareBeanPostProcessor());
+ doTestDestructionWithSessionSerialization(false);
+ }
+
+ public void testDestructionWithSessionSerializationAndSerializableBeanPostProcessor() throws Exception {
+ this.beanFactory.addBeanPostProcessor(new CustomSerializableDestructionAwareBeanPostProcessor());
+ doTestDestructionWithSessionSerialization(true);
+ }
+
+ private void doTestDestructionWithSessionSerialization(boolean beanNameReset) throws Exception {
+ Serializable serializedState = null;
+
+ MockHttpSession session = new MockHttpSession();
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setSession(session);
+ ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
+
+ RequestContextHolder.setRequestAttributes(requestAttributes);
+ try {
+ String name = "sessionScopedDisposableObject";
+ assertNull(session.getAttribute(name));
+ DerivedTestBean bean = (DerivedTestBean) this.beanFactory.getBean(name);
+ assertEquals(session.getAttribute(name), bean);
+ assertSame(bean, this.beanFactory.getBean(name));
+
+ requestAttributes.requestCompleted();
+ serializedState = session.serializeState();
+ assertFalse(bean.wasDestroyed());
+ }
+ finally {
+ RequestContextHolder.setRequestAttributes(null);
+ }
+
+ serializedState = (Serializable) SerializationTestUtils.serializeAndDeserialize(serializedState);
+
+ session = new MockHttpSession();
+ session.deserializeState(serializedState);
+ request = new MockHttpServletRequest();
+ request.setSession(session);
+ requestAttributes = new ServletRequestAttributes(request);
+
+ RequestContextHolder.setRequestAttributes(requestAttributes);
+ try {
+ String name = "sessionScopedDisposableObject";
+ assertNotNull(session.getAttribute(name));
+ DerivedTestBean bean = (DerivedTestBean) this.beanFactory.getBean(name);
+ assertEquals(session.getAttribute(name), bean);
+ assertSame(bean, this.beanFactory.getBean(name));
+
+ requestAttributes.requestCompleted();
+ session.invalidate();
+ assertTrue(bean.wasDestroyed());
+
+ if (beanNameReset) {
+ assertNull(bean.getBeanName());
+ }
+ else {
+ assertNotNull(bean.getBeanName());
+ }
+ }
+ finally {
+ RequestContextHolder.setRequestAttributes(null);
+ }
+ }
+
+
+ private static class CustomDestructionAwareBeanPostProcessor implements DestructionAwareBeanPostProcessor {
+
+ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+ return bean;
+ }
+
+ public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+ return bean;
+ }
+
+ public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
+ }
+ }
+
+
+ private static class CustomSerializableDestructionAwareBeanPostProcessor
+ implements DestructionAwareBeanPostProcessor, Serializable {
+
+ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+ return bean;
+ }
+
+ public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+ return bean;
+ }
+
+ public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
+ if (bean instanceof BeanNameAware) {
+ ((BeanNameAware) bean).setBeanName(null);
+ }
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/requestScopeTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/requestScopeTests.xml
new file mode 100644
index 00000000000..badc6d6cf20
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/requestScopeTests.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/requestScopedProxyTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/requestScopedProxyTests.xml
new file mode 100644
index 00000000000..ee1313d4dc1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/requestScopedProxyTests.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/sessionScopeTests.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/sessionScopeTests.xml
new file mode 100644
index 00000000000..e4f05b9abe5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/request/sessionScopeTests.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/support/HttpRequestHandlerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/context/support/HttpRequestHandlerTests.java
new file mode 100644
index 00000000000..376211bde70
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/support/HttpRequestHandlerTests.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.context.support;
+
+import java.io.IOException;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockServletConfig;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.web.HttpRequestHandler;
+import org.springframework.web.context.WebApplicationContext;
+
+/**
+ * @author Juergen Hoeller
+ * @since 2.0
+ */
+public class HttpRequestHandlerTests extends TestCase {
+
+ public void testHttpRequestHandlerServletPassThrough() throws Exception {
+ MockServletContext servletContext = new MockServletContext();
+ final MockHttpServletRequest request = new MockHttpServletRequest();
+ final MockHttpServletResponse response = new MockHttpServletResponse();
+
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.getBeanFactory().registerSingleton("myHandler", new HttpRequestHandler() {
+ public void handleRequest(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
+ assertSame(request, req);
+ assertSame(response, res);
+ String exception = request.getParameter("exception");
+ if ("ServletException".equals(exception)) {
+ throw new ServletException("test");
+ }
+ if ("IOException".equals(exception)) {
+ throw new IOException("test");
+ }
+ res.getWriter().write("myResponse");
+ }
+ });
+ wac.setServletContext(servletContext);
+ wac.refresh();
+ servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
+
+ Servlet servlet = new HttpRequestHandlerServlet();
+ servlet.init(new MockServletConfig(servletContext, "myHandler"));
+
+ servlet.service(request, response);
+ assertEquals("myResponse", response.getContentAsString());
+
+ try {
+ request.setParameter("exception", "ServletException");
+ servlet.service(request, response);
+ fail("Should have thrown ServletException");
+ }
+ catch (ServletException ex) {
+ assertEquals("test", ex.getMessage());
+ }
+
+ try {
+ request.setParameter("exception", "IOException");
+ servlet.service(request, response);
+ fail("Should have thrown IOException");
+ }
+ catch (IOException ex) {
+ assertEquals("test", ex.getMessage());
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/support/ServletContextSupportTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/context/support/ServletContextSupportTests.java
new file mode 100644
index 00000000000..6d9c13d2a34
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/support/ServletContextSupportTests.java
@@ -0,0 +1,474 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.web.context.support;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.config.BeanDefinitionHolder;
+import org.springframework.beans.factory.config.ConstructorArgumentValues;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
+import org.springframework.beans.factory.support.ChildBeanDefinition;
+import org.springframework.beans.factory.support.ManagedList;
+import org.springframework.beans.factory.support.ManagedMap;
+import org.springframework.beans.factory.support.ManagedSet;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.core.io.Resource;
+import org.springframework.mock.web.MockServletContext;
+
+/**
+ * Tests for various ServletContext-related support classes.
+ *
+ * @author Juergen Hoeller
+ * @since 22.12.2004
+ */
+public class ServletContextSupportTests extends TestCase {
+
+ public void testServletContextFactoryBean() {
+ MockServletContext sc = new MockServletContext();
+
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(sc);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ wac.registerSingleton("servletContext", ServletContextFactoryBean.class, pvs);
+ wac.refresh();
+
+ Object value = wac.getBean("servletContext");
+ assertEquals(sc, value);
+ }
+
+ public void testServletContextAttributeFactoryBean() {
+ MockServletContext sc = new MockServletContext();
+ sc.setAttribute("myAttr", "myValue");
+
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(sc);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("attributeName", "myAttr");
+ wac.registerSingleton("importedAttr", ServletContextAttributeFactoryBean.class, pvs);
+ wac.refresh();
+
+ Object value = wac.getBean("importedAttr");
+ assertEquals("myValue", value);
+ }
+
+ public void testServletContextAttributeFactoryBeanWithAttributeNotFound() {
+ MockServletContext sc = new MockServletContext();
+
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(sc);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("attributeName", "myAttr");
+ wac.registerSingleton("importedAttr", ServletContextAttributeFactoryBean.class, pvs);
+
+ try {
+ wac.refresh();
+ fail("Should have thrown BeanCreationException");
+ }
+ catch (BeanCreationException ex) {
+ // expected
+ assertTrue(ex.getCause() instanceof IllegalStateException);
+ assertTrue(ex.getCause().getMessage().indexOf("myAttr") != -1);
+ }
+ }
+
+ public void testServletContextParameterFactoryBean() {
+ MockServletContext sc = new MockServletContext();
+ sc.addInitParameter("myParam", "myValue");
+
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(sc);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("initParamName", "myParam");
+ wac.registerSingleton("importedParam", ServletContextParameterFactoryBean.class, pvs);
+ wac.refresh();
+
+ Object value = wac.getBean("importedParam");
+ assertEquals("myValue", value);
+ }
+
+ public void testServletContextParameterFactoryBeanWithAttributeNotFound() {
+ MockServletContext sc = new MockServletContext();
+
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(sc);
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("initParamName", "myParam");
+ wac.registerSingleton("importedParam", ServletContextParameterFactoryBean.class, pvs);
+
+ try {
+ wac.refresh();
+ fail("Should have thrown BeanCreationException");
+ }
+ catch (BeanCreationException ex) {
+ // expected
+ assertTrue(ex.getCause() instanceof IllegalStateException);
+ assertTrue(ex.getCause().getMessage().indexOf("myParam") != -1);
+ }
+ }
+
+ public void testServletContextAttributeExporter() {
+ TestBean tb = new TestBean();
+ Map attributes = new HashMap();
+ attributes.put("attr1", "value1");
+ attributes.put("attr2", tb);
+
+ MockServletContext sc = new MockServletContext();
+ ServletContextAttributeExporter exporter = new ServletContextAttributeExporter();
+ exporter.setAttributes(attributes);
+ exporter.setServletContext(sc);
+
+ assertEquals("value1", sc.getAttribute("attr1"));
+ assertSame(tb, sc.getAttribute("attr2"));
+ }
+
+ public void testServletContextPropertyPlaceholderConfigurer() {
+ MockServletContext sc = new MockServletContext();
+ sc.addInitParameter("key4", "mykey4");
+
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(sc);
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("age", "${age}");
+ pvs.addPropertyValue("name", "${key4}name${var}${var}${");
+ pvs.addPropertyValue("spouse", new RuntimeBeanReference("${ref}"));
+ wac.registerSingleton("tb1", TestBean.class, pvs);
+
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, null);
+ wac.getDefaultListableBeanFactory().registerBeanDefinition("tb2", bd);
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", "age=98\nvar=${m}var\nref=tb2\nm=my");
+ wac.registerSingleton("configurer", ServletContextPropertyPlaceholderConfigurer.class, pvs);
+
+ wac.refresh();
+
+ TestBean tb1 = (TestBean) wac.getBean("tb1");
+ TestBean tb2 = (TestBean) wac.getBean("tb2");
+ assertEquals(98, tb1.getAge());
+ assertEquals("mykey4namemyvarmyvar${", tb1.getName());
+ assertEquals(tb2, tb1.getSpouse());
+ }
+
+ public void testServletContextPropertyPlaceholderConfigurerWithLocalOverriding() {
+ MockServletContext sc = new MockServletContext();
+ sc.addInitParameter("key4", "mykey4");
+
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(sc);
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("age", "${age}");
+ pvs.addPropertyValue("name", "${key4}name${var}${var}${");
+ pvs.addPropertyValue("spouse", new RuntimeBeanReference("${ref}"));
+ wac.registerSingleton("tb1", TestBean.class, pvs);
+
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, null);
+ wac.getDefaultListableBeanFactory().registerBeanDefinition("tb2", bd);
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", "age=98\nvar=${m}var\nref=tb2\nm=my\nkey4=yourkey4");
+ wac.registerSingleton("configurer", ServletContextPropertyPlaceholderConfigurer.class, pvs);
+
+ wac.refresh();
+
+ TestBean tb1 = (TestBean) wac.getBean("tb1");
+ TestBean tb2 = (TestBean) wac.getBean("tb2");
+ assertEquals(98, tb1.getAge());
+ assertEquals("yourkey4namemyvarmyvar${", tb1.getName());
+ assertEquals(tb2, tb1.getSpouse());
+ }
+
+ public void testServletContextPropertyPlaceholderConfigurerWithContextOverride() {
+ MockServletContext sc = new MockServletContext();
+ sc.addInitParameter("key4", "mykey4");
+
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(sc);
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("age", "${age}");
+ pvs.addPropertyValue("name", "${key4}name${var}${var}${");
+ pvs.addPropertyValue("spouse", new RuntimeBeanReference("${ref}"));
+ wac.registerSingleton("tb1", TestBean.class, pvs);
+
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, null);
+ wac.getDefaultListableBeanFactory().registerBeanDefinition("tb2", bd);
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", "age=98\nvar=${m}var\nref=tb2\nm=my\nkey4=yourkey4");
+ pvs.addPropertyValue("contextOverride", Boolean.TRUE);
+ wac.registerSingleton("configurer", ServletContextPropertyPlaceholderConfigurer.class, pvs);
+
+ wac.refresh();
+
+ TestBean tb1 = (TestBean) wac.getBean("tb1");
+ TestBean tb2 = (TestBean) wac.getBean("tb2");
+ assertEquals(98, tb1.getAge());
+ assertEquals("mykey4namemyvarmyvar${", tb1.getName());
+ assertEquals(tb2, tb1.getSpouse());
+ }
+
+ public void testServletContextPropertyPlaceholderConfigurerWithContextOverrideAndAttributes() {
+ MockServletContext sc = new MockServletContext();
+ sc.addInitParameter("key4", "mykey4");
+ sc.setAttribute("key4", "attrkey4");
+
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(sc);
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("age", "${age}");
+ pvs.addPropertyValue("name", "${key4}name${var}${var}${");
+ pvs.addPropertyValue("spouse", new RuntimeBeanReference("${ref}"));
+ wac.registerSingleton("tb1", TestBean.class, pvs);
+
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, null);
+ wac.getDefaultListableBeanFactory().registerBeanDefinition("tb2", bd);
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", "age=98\nvar=${m}var\nref=tb2\nm=my\nkey4=yourkey4");
+ pvs.addPropertyValue("contextOverride", Boolean.TRUE);
+ pvs.addPropertyValue("searchContextAttributes", Boolean.TRUE);
+ wac.registerSingleton("configurer", ServletContextPropertyPlaceholderConfigurer.class, pvs);
+
+ wac.refresh();
+
+ TestBean tb1 = (TestBean) wac.getBean("tb1");
+ TestBean tb2 = (TestBean) wac.getBean("tb2");
+ assertEquals(98, tb1.getAge());
+ assertEquals("attrkey4namemyvarmyvar${", tb1.getName());
+ assertEquals(tb2, tb1.getSpouse());
+ }
+
+ public void testServletContextPropertyPlaceholderConfigurerWithAttributes() {
+ MockServletContext sc = new MockServletContext();
+ sc.addInitParameter("key4", "mykey4");
+
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(sc);
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("age", "${age}");
+ pvs.addPropertyValue("name", "name${var}${var}${");
+ pvs.addPropertyValue("spouse", new RuntimeBeanReference("${ref}"));
+ wac.registerSingleton("tb1", TestBean.class, pvs);
+
+ ConstructorArgumentValues cas = new ConstructorArgumentValues();
+ cas.addIndexedArgumentValue(1, "${age}");
+ cas.addGenericArgumentValue("${var}name${age}");
+
+ pvs = new MutablePropertyValues();
+ List friends = new ManagedList();
+ friends.add("na${age}me");
+ friends.add(new RuntimeBeanReference("${ref}"));
+ pvs.addPropertyValue("friends", friends);
+
+ Set someSet = new ManagedSet();
+ someSet.add("na${age}me");
+ someSet.add(new RuntimeBeanReference("${ref}"));
+ pvs.addPropertyValue("someSet", someSet);
+
+ Map someMap = new ManagedMap();
+ someMap.put("key1", new RuntimeBeanReference("${ref}"));
+ someMap.put("key2", "${age}name");
+ MutablePropertyValues innerPvs = new MutablePropertyValues();
+ innerPvs.addPropertyValue("touchy", "${os.name}");
+ someMap.put("key3", new RootBeanDefinition(TestBean.class, innerPvs));
+ MutablePropertyValues innerPvs2 = new MutablePropertyValues(innerPvs);
+ someMap.put("${key4}", new BeanDefinitionHolder(new ChildBeanDefinition("tb1", innerPvs2), "child"));
+ pvs.addPropertyValue("someMap", someMap);
+
+ RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, cas, pvs);
+ wac.getDefaultListableBeanFactory().registerBeanDefinition("tb2", bd);
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("properties", "var=${m}var\nref=tb2\nm=my");
+ pvs.addPropertyValue("searchContextAttributes", Boolean.TRUE);
+ wac.registerSingleton("configurer", ServletContextPropertyPlaceholderConfigurer.class, pvs);
+ sc.setAttribute("age", new Integer(98));
+
+ wac.refresh();
+
+ TestBean tb1 = (TestBean) wac.getBean("tb1");
+ TestBean tb2 = (TestBean) wac.getBean("tb2");
+ assertEquals(98, tb1.getAge());
+ assertEquals(98, tb2.getAge());
+ assertEquals("namemyvarmyvar${", tb1.getName());
+ assertEquals("myvarname98", tb2.getName());
+ assertEquals(tb2, tb1.getSpouse());
+ assertEquals(2, tb2.getFriends().size());
+ assertEquals("na98me", tb2.getFriends().iterator().next());
+ assertEquals(tb2, tb2.getFriends().toArray()[1]);
+ assertEquals(2, tb2.getSomeSet().size());
+ assertTrue(tb2.getSomeSet().contains("na98me"));
+ assertTrue(tb2.getSomeSet().contains(tb2));
+ assertEquals(4, tb2.getSomeMap().size());
+ assertEquals(tb2, tb2.getSomeMap().get("key1"));
+ assertEquals("98name", tb2.getSomeMap().get("key2"));
+ TestBean inner1 = (TestBean) tb2.getSomeMap().get("key3");
+ TestBean inner2 = (TestBean) tb2.getSomeMap().get("mykey4");
+ assertEquals(0, inner1.getAge());
+ assertEquals(null, inner1.getName());
+ assertEquals(System.getProperty("os.name"), inner1.getTouchy());
+ assertEquals(98, inner2.getAge());
+ assertEquals("namemyvarmyvar${", inner2.getName());
+ assertEquals(System.getProperty("os.name"), inner2.getTouchy());
+ }
+
+ public void testServletContextResourceLoader() {
+ MockServletContext sc = new MockServletContext("classpath:org/springframework/web/context");
+ ServletContextResourceLoader rl = new ServletContextResourceLoader(sc);
+ assertTrue(rl.getResource("/WEB-INF/web.xml").exists());
+ assertTrue(rl.getResource("WEB-INF/web.xml").exists());
+ assertTrue(rl.getResource("../context/WEB-INF/web.xml").exists());
+ assertTrue(rl.getResource("/../context/WEB-INF/web.xml").exists());
+ }
+
+ public void testServletContextResourcePatternResolver() throws IOException {
+ final Set paths = new HashSet();
+ paths.add("/WEB-INF/context1.xml");
+ paths.add("/WEB-INF/context2.xml");
+
+ MockServletContext sc = new MockServletContext("classpath:org/springframework/web/context") {
+ public Set getResourcePaths(String path) {
+ if ("/WEB-INF/".equals(path)) {
+ return paths;
+ }
+ return null;
+ }
+ };
+
+ ServletContextResourcePatternResolver rpr = new ServletContextResourcePatternResolver(sc);
+ Resource[] found = rpr.getResources("/WEB-INF/*.xml");
+ Set foundPaths = new HashSet();
+ for (int i = 0; i < found.length; i++) {
+ foundPaths.add(((ServletContextResource) found[i]).getPath());
+ }
+ assertEquals(2, foundPaths.size());
+ assertTrue(foundPaths.contains("/WEB-INF/context1.xml"));
+ assertTrue(foundPaths.contains("/WEB-INF/context2.xml"));
+ }
+
+ public void testServletContextResourcePatternResolverWithPatternPath() throws IOException {
+ final Set dirs = new HashSet();
+ dirs.add("/WEB-INF/mydir1/");
+ dirs.add("/WEB-INF/mydir2/");
+
+ MockServletContext sc = new MockServletContext("classpath:org/springframework/web/context") {
+ public Set getResourcePaths(String path) {
+ if ("/WEB-INF/".equals(path)) {
+ return dirs;
+ }
+ if ("/WEB-INF/mydir1/".equals(path)) {
+ return Collections.singleton("/WEB-INF/mydir1/context1.xml");
+ }
+ if ("/WEB-INF/mydir2/".equals(path)) {
+ return Collections.singleton("/WEB-INF/mydir2/context2.xml");
+ }
+ return null;
+ }
+ };
+
+ ServletContextResourcePatternResolver rpr = new ServletContextResourcePatternResolver(sc);
+ Resource[] found = rpr.getResources("/WEB-INF/*/*.xml");
+ Set foundPaths = new HashSet();
+ for (int i = 0; i < found.length; i++) {
+ foundPaths.add(((ServletContextResource) found[i]).getPath());
+ }
+ assertEquals(2, foundPaths.size());
+ assertTrue(foundPaths.contains("/WEB-INF/mydir1/context1.xml"));
+ assertTrue(foundPaths.contains("/WEB-INF/mydir2/context2.xml"));
+ }
+
+ public void testServletContextResourcePatternResolverWithUnboundedPatternPath() throws IOException {
+ final Set dirs = new HashSet();
+ dirs.add("/WEB-INF/mydir1/");
+ dirs.add("/WEB-INF/mydir2/");
+
+ final Set paths = new HashSet();
+ paths.add("/WEB-INF/mydir2/context2.xml");
+ paths.add("/WEB-INF/mydir2/mydir3/");
+
+ MockServletContext sc = new MockServletContext("classpath:org/springframework/web/context") {
+ public Set getResourcePaths(String path) {
+ if ("/WEB-INF/".equals(path)) {
+ return dirs;
+ }
+ if ("/WEB-INF/mydir1/".equals(path)) {
+ return Collections.singleton("/WEB-INF/mydir1/context1.xml");
+ }
+ if ("/WEB-INF/mydir2/".equals(path)) {
+ return paths;
+ }
+ if ("/WEB-INF/mydir2/mydir3/".equals(path)) {
+ return Collections.singleton("/WEB-INF/mydir2/mydir3/context3.xml");
+ }
+ return null;
+ }
+ };
+
+ ServletContextResourcePatternResolver rpr = new ServletContextResourcePatternResolver(sc);
+ Resource[] found = rpr.getResources("/WEB-INF/**/*.xml");
+ Set foundPaths = new HashSet();
+ for (int i = 0; i < found.length; i++) {
+ foundPaths.add(((ServletContextResource) found[i]).getPath());
+ }
+ assertEquals(3, foundPaths.size());
+ assertTrue(foundPaths.contains("/WEB-INF/mydir1/context1.xml"));
+ assertTrue(foundPaths.contains("/WEB-INF/mydir2/context2.xml"));
+ assertTrue(foundPaths.contains("/WEB-INF/mydir2/mydir3/context3.xml"));
+ }
+
+ public void testServletContextResourcePatternResolverWithAbsolutePaths() throws IOException {
+ final Set paths = new HashSet();
+ paths.add("C:/webroot/WEB-INF/context1.xml");
+ paths.add("C:/webroot/WEB-INF/context2.xml");
+ paths.add("C:/webroot/someOtherDirThatDoesntContainPath");
+
+ MockServletContext sc = new MockServletContext("classpath:org/springframework/web/context") {
+ public Set getResourcePaths(String path) {
+ if ("/WEB-INF/".equals(path)) {
+ return paths;
+ }
+ return null;
+ }
+ };
+
+ ServletContextResourcePatternResolver rpr = new ServletContextResourcePatternResolver(sc);
+ Resource[] found = rpr.getResources("/WEB-INF/*.xml");
+ Set foundPaths = new HashSet();
+ for (int i = 0; i < found.length; i++) {
+ foundPaths.add(((ServletContextResource) found[i]).getPath());
+ }
+ assertEquals(2, foundPaths.size());
+ assertTrue(foundPaths.contains("/WEB-INF/context1.xml"));
+ assertTrue(foundPaths.contains("/WEB-INF/context2.xml"));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/context/support/WebApplicationObjectSupportTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/context/support/WebApplicationObjectSupportTests.java
new file mode 100644
index 00000000000..b7d7cc19c52
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/context/support/WebApplicationObjectSupportTests.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.web.context.support;
+
+import java.io.File;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.context.support.StaticApplicationContext;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.web.util.WebUtils;
+
+/**
+ * @author Juergen Hoeller
+ * @since 28.08.2003
+ */
+public class WebApplicationObjectSupportTests extends TestCase {
+
+ public void testWebApplicationObjectSupport() {
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(new MockServletContext());
+ File tempDir = new File("");
+ wac.getServletContext().setAttribute(WebUtils.TEMP_DIR_CONTEXT_ATTRIBUTE, tempDir);
+ wac.registerBeanDefinition("test", new RootBeanDefinition(TestWebApplicationObject.class));
+ wac.refresh();
+ WebApplicationObjectSupport wao = (WebApplicationObjectSupport) wac.getBean("test");
+ assertEquals(wao.getServletContext(), wac.getServletContext());
+ assertEquals(wao.getTempDir(), tempDir);
+ }
+
+ public void testWebApplicationObjectSupportWithWrongContext() {
+ StaticApplicationContext ac = new StaticApplicationContext();
+ ac.registerBeanDefinition("test", new RootBeanDefinition(TestWebApplicationObject.class));
+ WebApplicationObjectSupport wao = (WebApplicationObjectSupport) ac.getBean("test");
+ try {
+ wao.getWebApplicationContext();
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+
+ public static class TestWebApplicationObject extends WebApplicationObjectSupport {
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/filter/CharacterEncodingFilterTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/filter/CharacterEncodingFilterTests.java
new file mode 100644
index 00000000000..801c05440cf
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/filter/CharacterEncodingFilterTests.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.web.filter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.mock.web.MockFilterConfig;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockServletContext;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class CharacterEncodingFilterTests extends TestCase {
+
+ private static final String FILTER_NAME = "boot";
+
+ private static final String ENCODING = "UTF-8";
+
+
+ public void testForceAlwaysSetsEncoding() throws Exception {
+ MockControl mockRequest = MockControl.createControl(HttpServletRequest.class);
+ HttpServletRequest request = (HttpServletRequest) mockRequest.getMock();
+ request.setCharacterEncoding(ENCODING);
+ mockRequest.setVoidCallable();
+ request.getAttribute(FILTER_NAME + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX);
+ mockRequest.setReturnValue(null);
+ request.setAttribute(FILTER_NAME + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX, Boolean.TRUE);
+ mockRequest.setVoidCallable();
+ request.removeAttribute(FILTER_NAME + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX);
+ mockRequest.setVoidCallable();
+ mockRequest.replay();
+
+ MockControl mockResponse = MockControl.createControl(HttpServletResponse.class);
+ HttpServletResponse response = (HttpServletResponse) mockResponse.getMock();
+ response.setCharacterEncoding(ENCODING);
+ mockResponse.setVoidCallable();
+ mockResponse.replay();
+
+ MockControl mockFilter = MockControl.createControl(FilterChain.class);
+ FilterChain filterChain = (FilterChain) mockFilter.getMock();
+ filterChain.doFilter(request, response);
+ mockFilter.replay();
+
+ CharacterEncodingFilter filter = new CharacterEncodingFilter();
+ filter.setForceEncoding(true);
+ filter.setEncoding(ENCODING);
+ filter.init(new MockFilterConfig(FILTER_NAME));
+ filter.doFilter(request, response, filterChain);
+
+ mockRequest.verify();
+ mockResponse.verify();
+ mockFilter.verify();
+ }
+
+ public void testEncodingIfEmptyAndNotForced() throws Exception {
+ MockControl mockRequest = MockControl.createControl(HttpServletRequest.class);
+ HttpServletRequest request = (HttpServletRequest) mockRequest.getMock();
+ request.getCharacterEncoding();
+ mockRequest.setReturnValue(null);
+ request.setCharacterEncoding(ENCODING);
+ mockRequest.setVoidCallable();
+ request.getAttribute(FILTER_NAME + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX);
+ mockRequest.setReturnValue(null);
+ request.setAttribute(FILTER_NAME + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX, Boolean.TRUE);
+ mockRequest.setVoidCallable();
+ request.removeAttribute(FILTER_NAME + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX);
+ mockRequest.setVoidCallable();
+ mockRequest.replay();
+
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ MockControl mockFilter = MockControl.createControl(FilterChain.class);
+ FilterChain filterChain = (FilterChain) mockFilter.getMock();
+ filterChain.doFilter(request, response);
+ mockFilter.replay();
+
+ CharacterEncodingFilter filter = new CharacterEncodingFilter();
+ filter.setForceEncoding(false);
+ filter.setEncoding(ENCODING);
+ filter.init(new MockFilterConfig(FILTER_NAME));
+ filter.doFilter(request, response, filterChain);
+
+ mockRequest.verify();
+ mockFilter.verify();
+ }
+
+ public void testDoesNowtIfEncodingIsNotEmptyAndNotForced() throws Exception {
+ MockControl mockRequest = MockControl.createControl(HttpServletRequest.class);
+ HttpServletRequest request = (HttpServletRequest) mockRequest.getMock();
+ request.getCharacterEncoding();
+ mockRequest.setReturnValue(ENCODING);
+ request.getAttribute(FILTER_NAME + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX);
+ mockRequest.setReturnValue(null);
+ request.setAttribute(FILTER_NAME + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX, Boolean.TRUE);
+ mockRequest.setVoidCallable();
+ request.removeAttribute(FILTER_NAME + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX);
+ mockRequest.setVoidCallable();
+ mockRequest.replay();
+
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ MockControl mockFilter = MockControl.createControl(FilterChain.class);
+ FilterChain filterChain = (FilterChain) mockFilter.getMock();
+ filterChain.doFilter(request, response);
+ mockFilter.replay();
+
+ CharacterEncodingFilter filter = new CharacterEncodingFilter();
+ filter.setEncoding(ENCODING);
+ filter.init(new MockFilterConfig(FILTER_NAME));
+ filter.doFilter(request, response, filterChain);
+
+ mockRequest.verify();
+ mockFilter.verify();
+ }
+
+ public void testWithBeanInitialization() throws Exception {
+ MockControl mockRequest = MockControl.createControl(HttpServletRequest.class);
+ HttpServletRequest request = (HttpServletRequest) mockRequest.getMock();
+ request.getCharacterEncoding();
+ mockRequest.setReturnValue(null);
+ request.setCharacterEncoding(ENCODING);
+ mockRequest.setVoidCallable();
+ request.getAttribute(FILTER_NAME + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX);
+ mockRequest.setReturnValue(null);
+ request.setAttribute(FILTER_NAME + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX, Boolean.TRUE);
+ mockRequest.setVoidCallable();
+ request.removeAttribute(FILTER_NAME + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX);
+ mockRequest.setVoidCallable();
+ mockRequest.replay();
+
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ MockControl mockFilter = MockControl.createControl(FilterChain.class);
+ FilterChain filterChain = (FilterChain) mockFilter.getMock();
+ filterChain.doFilter(request, response);
+ mockFilter.replay();
+
+ CharacterEncodingFilter filter = new CharacterEncodingFilter();
+ filter.setEncoding(ENCODING);
+ filter.setBeanName(FILTER_NAME);
+ filter.setServletContext(new MockServletContext());
+ filter.doFilter(request, response, filterChain);
+
+ mockRequest.verify();
+ mockFilter.verify();
+ }
+
+ public void testWithIncompleteInitialization() throws Exception {
+ MockControl mockRequest = MockControl.createControl(HttpServletRequest.class);
+ HttpServletRequest request = (HttpServletRequest) mockRequest.getMock();
+ request.getCharacterEncoding();
+ mockRequest.setReturnValue(null);
+ request.setCharacterEncoding(ENCODING);
+ mockRequest.setVoidCallable();
+ request.getAttribute(CharacterEncodingFilter.class.getName() + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX);
+ mockRequest.setReturnValue(null);
+ request.setAttribute(CharacterEncodingFilter.class.getName() + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX, Boolean.TRUE);
+ mockRequest.setVoidCallable();
+ request.removeAttribute(CharacterEncodingFilter.class.getName() + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX);
+ mockRequest.setVoidCallable();
+ mockRequest.replay();
+
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ MockControl mockFilter = MockControl.createControl(FilterChain.class);
+ FilterChain filterChain = (FilterChain) mockFilter.getMock();
+ filterChain.doFilter(request, response);
+ mockFilter.replay();
+
+ CharacterEncodingFilter filter = new CharacterEncodingFilter();
+ filter.setEncoding(ENCODING);
+ filter.doFilter(request, response, filterChain);
+
+ mockRequest.verify();
+ mockFilter.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/filter/DelegatingFilterProxyTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/filter/DelegatingFilterProxyTests.java
new file mode 100644
index 00000000000..51bea2e6502
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/filter/DelegatingFilterProxyTests.java
@@ -0,0 +1,170 @@
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
+ *
+ * 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.springframework.web.filter;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.MockFilterConfig;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.StaticWebApplicationContext;
+
+/**
+ * @author Juergen Hoeller
+ * @since 08.05.2005
+ */
+public class DelegatingFilterProxyTests extends TestCase {
+
+ public void testDelegatingFilterProxy() throws ServletException, IOException {
+ ServletContext sc = new MockServletContext();
+
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(sc);
+ wac.registerSingleton("targetFilter", MockFilter.class);
+ wac.refresh();
+ sc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
+
+ MockFilter targetFilter = (MockFilter) wac.getBean("targetFilter");
+
+ MockFilterConfig proxyConfig = new MockFilterConfig(sc);
+ proxyConfig.addInitParameter("targetBeanName", "targetFilter");
+ DelegatingFilterProxy filterProxy = new DelegatingFilterProxy();
+ filterProxy.init(proxyConfig);
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ filterProxy.doFilter(request, response, null);
+
+ assertNull(targetFilter.filterConfig);
+ assertEquals(Boolean.TRUE, request.getAttribute("called"));
+
+ filterProxy.destroy();
+ assertNull(targetFilter.filterConfig);
+ }
+
+ public void testDelegatingFilterProxyWithFilterName() throws ServletException, IOException {
+ ServletContext sc = new MockServletContext();
+
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(sc);
+ wac.registerSingleton("targetFilter", MockFilter.class);
+ wac.refresh();
+ sc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
+
+ MockFilter targetFilter = (MockFilter) wac.getBean("targetFilter");
+
+ MockFilterConfig proxyConfig = new MockFilterConfig(sc, "targetFilter");
+ DelegatingFilterProxy filterProxy = new DelegatingFilterProxy();
+ filterProxy.init(proxyConfig);
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ filterProxy.doFilter(request, response, null);
+
+ assertNull(targetFilter.filterConfig);
+ assertEquals(Boolean.TRUE, request.getAttribute("called"));
+
+ filterProxy.destroy();
+ assertNull(targetFilter.filterConfig);
+ }
+
+ public void testDelegatingFilterProxyWithLazyContextStartup() throws ServletException, IOException {
+ ServletContext sc = new MockServletContext();
+
+ MockFilterConfig proxyConfig = new MockFilterConfig(sc);
+ proxyConfig.addInitParameter("targetBeanName", "targetFilter");
+ DelegatingFilterProxy filterProxy = new DelegatingFilterProxy();
+ filterProxy.init(proxyConfig);
+
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(sc);
+ wac.registerSingleton("targetFilter", MockFilter.class);
+ wac.refresh();
+ sc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
+
+ MockFilter targetFilter = (MockFilter) wac.getBean("targetFilter");
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ filterProxy.doFilter(request, response, null);
+
+ assertNull(targetFilter.filterConfig);
+ assertEquals(Boolean.TRUE, request.getAttribute("called"));
+
+ filterProxy.destroy();
+ assertNull(targetFilter.filterConfig);
+ }
+
+ public void testDelegatingFilterProxyWithTargetFilterLifecycle() throws ServletException, IOException {
+ ServletContext sc = new MockServletContext();
+
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(sc);
+ wac.registerSingleton("targetFilter", MockFilter.class);
+ wac.refresh();
+ sc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
+
+ MockFilter targetFilter = (MockFilter) wac.getBean("targetFilter");
+
+ MockFilterConfig proxyConfig = new MockFilterConfig(sc);
+ proxyConfig.addInitParameter("targetBeanName", "targetFilter");
+ proxyConfig.addInitParameter("targetFilterLifecycle", "true");
+ DelegatingFilterProxy filterProxy = new DelegatingFilterProxy();
+ filterProxy.init(proxyConfig);
+ assertEquals(proxyConfig, targetFilter.filterConfig);
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ filterProxy.doFilter(request, response, null);
+
+ assertEquals(proxyConfig, targetFilter.filterConfig);
+ assertEquals(Boolean.TRUE, request.getAttribute("called"));
+
+ filterProxy.destroy();
+ assertNull(targetFilter.filterConfig);
+ }
+
+
+ public static class MockFilter implements Filter {
+
+ public FilterConfig filterConfig;
+
+ public void init(FilterConfig filterConfig) throws ServletException {
+ this.filterConfig = filterConfig;
+ }
+
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
+ request.setAttribute("called", Boolean.TRUE);
+ }
+
+ public void destroy() {
+ this.filterConfig = null;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/filter/RequestContextFilterTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/filter/RequestContextFilterTests.java
new file mode 100644
index 00000000000..a1272ad66c4
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/filter/RequestContextFilterTests.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.filter;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.MockFilterConfig;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public class RequestContextFilterTests extends TestCase {
+
+ public void testHappyPath() throws Exception {
+ testFilterInvocation(null);
+ }
+
+ public void testWithException() throws Exception {
+ testFilterInvocation(new ServletException());
+ }
+
+ public void testFilterInvocation(final ServletException sex) throws Exception {
+ final MockHttpServletRequest req = new MockHttpServletRequest();
+ req.setAttribute("myAttr", "myValue");
+ final MockHttpServletResponse resp = new MockHttpServletResponse();
+
+ // Expect one invocation by the filter being tested
+ class DummyFilterChain implements FilterChain {
+ public int invocations = 0;
+ public void doFilter(ServletRequest req, ServletResponse resp) throws IOException, ServletException {
+ ++invocations;
+ if (invocations == 1) {
+ assertSame("myValue",
+ RequestContextHolder.currentRequestAttributes().getAttribute("myAttr", RequestAttributes.SCOPE_REQUEST));
+ if (sex != null) {
+ throw sex;
+ }
+ }
+ else {
+ throw new IllegalStateException("Too many invocations");
+ }
+ }
+ };
+
+ DummyFilterChain fc = new DummyFilterChain();
+ MockFilterConfig mfc = new MockFilterConfig(new MockServletContext(), "foo");
+
+ RequestContextFilter rbf = new RequestContextFilter();
+ rbf.init(mfc);
+
+ try {
+ rbf.doFilter(req, resp, fc);
+ if (sex != null) {
+ fail();
+ }
+ }
+ catch (ServletException ex) {
+ assertNotNull(sex);
+ }
+
+ try {
+ RequestContextHolder.currentRequestAttributes();
+ fail();
+ }
+ catch (IllegalStateException ex) {
+ // Ok
+ }
+
+ assertEquals(1, fc.invocations);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/jsf/DelegatingNavigationHandlerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/jsf/DelegatingNavigationHandlerTests.java
new file mode 100644
index 00000000000..6e58058bf0e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/jsf/DelegatingNavigationHandlerTests.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.jsf;
+
+import javax.faces.application.NavigationHandler;
+import javax.faces.context.FacesContext;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.support.StaticListableBeanFactory;
+
+/**
+ * @author Colin Sampaleanu
+ * @author Juergen Hoeller
+ */
+public class DelegatingNavigationHandlerTests extends TestCase {
+
+ private MockFacesContext facesContext;
+ private StaticListableBeanFactory beanFactory;
+ private TestNavigationHandler origNavHandler;
+ private DelegatingNavigationHandlerProxy delNavHandler;
+
+ protected void setUp() {
+ facesContext = new MockFacesContext();
+ beanFactory = new StaticListableBeanFactory();
+ origNavHandler = new TestNavigationHandler();
+
+ delNavHandler = new DelegatingNavigationHandlerProxy(origNavHandler) {
+ protected BeanFactory getBeanFactory(FacesContext facesContext) {
+ return beanFactory;
+ }
+ };
+ }
+
+ public void testHandleNavigationWithoutDecoration() {
+ TestNavigationHandler targetHandler = new TestNavigationHandler();
+ beanFactory.addBean("jsfNavigationHandler", targetHandler);
+
+ delNavHandler.handleNavigation(facesContext, "fromAction", "myViewId");
+ assertEquals(targetHandler.lastFromAction, "fromAction");
+ assertEquals(targetHandler.lastOutcome, "myViewId");
+ }
+
+ public void testHandleNavigationWithDecoration() {
+ TestDecoratingNavigationHandler targetHandler = new TestDecoratingNavigationHandler();
+ beanFactory.addBean("jsfNavigationHandler", targetHandler);
+
+ delNavHandler.handleNavigation(facesContext, "fromAction", "myViewId");
+ assertEquals(targetHandler.lastFromAction, "fromAction");
+ assertEquals(targetHandler.lastOutcome, "myViewId");
+
+ // Original handler must have been invoked as well...
+ assertEquals(origNavHandler.lastFromAction, "fromAction");
+ assertEquals(origNavHandler.lastOutcome, "myViewId");
+ }
+
+
+ public static class TestNavigationHandler extends NavigationHandler {
+
+ private String lastFromAction;
+ private String lastOutcome;
+
+ public void handleNavigation(FacesContext facesContext, String fromAction, String outcome) {
+ lastFromAction = fromAction;
+ lastOutcome = outcome;
+ }
+ }
+
+
+ public static class TestDecoratingNavigationHandler extends DecoratingNavigationHandler {
+
+ private String lastFromAction;
+ private String lastOutcome;
+
+ public void handleNavigation(
+ FacesContext facesContext, String fromAction, String outcome, NavigationHandler originalNavigationHandler) {
+ lastFromAction = fromAction;
+ lastOutcome = outcome;
+ if (originalNavigationHandler != null) {
+ originalNavigationHandler.handleNavigation(facesContext, fromAction, outcome);
+ }
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/jsf/DelegatingPhaseListenerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/jsf/DelegatingPhaseListenerTests.java
new file mode 100644
index 00000000000..48af11100d6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/jsf/DelegatingPhaseListenerTests.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.jsf;
+
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseEvent;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PhaseListener;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.factory.ListableBeanFactory;
+import org.springframework.beans.factory.support.StaticListableBeanFactory;
+
+/**
+ * @author Colin Sampaleanu
+ * @author Juergen Hoeller
+ */
+public class DelegatingPhaseListenerTests extends TestCase {
+
+ private MockFacesContext facesContext;
+ private StaticListableBeanFactory beanFactory;
+ private DelegatingPhaseListenerMulticaster delPhaseListener;
+
+ protected void setUp() {
+ facesContext = new MockFacesContext();
+ beanFactory = new StaticListableBeanFactory();
+
+ delPhaseListener = new DelegatingPhaseListenerMulticaster() {
+ protected ListableBeanFactory getBeanFactory(FacesContext facesContext) {
+ return beanFactory;
+ }
+ };
+ }
+
+ public void testBeforeAndAfterPhaseWithSingleTarget() {
+ TestListener target = new TestListener();
+ beanFactory.addBean("testListener", target);
+
+ assertEquals(delPhaseListener.getPhaseId(), PhaseId.ANY_PHASE);
+ PhaseEvent event = new PhaseEvent(facesContext, PhaseId.INVOKE_APPLICATION, new MockLifecycle());
+
+ delPhaseListener.beforePhase(event);
+ assertTrue(target.beforeCalled);
+
+ delPhaseListener.afterPhase(event);
+ assertTrue(target.afterCalled);
+ }
+
+ public void testBeforeAndAfterPhaseWithMultipleTargets() {
+ TestListener target1 = new TestListener();
+ TestListener target2 = new TestListener();
+ beanFactory.addBean("testListener1", target1);
+ beanFactory.addBean("testListener2", target2);
+
+ assertEquals(delPhaseListener.getPhaseId(), PhaseId.ANY_PHASE);
+ PhaseEvent event = new PhaseEvent(facesContext, PhaseId.INVOKE_APPLICATION, new MockLifecycle());
+
+ delPhaseListener.beforePhase(event);
+ assertTrue(target1.beforeCalled);
+ assertTrue(target2.beforeCalled);
+
+ delPhaseListener.afterPhase(event);
+ assertTrue(target1.afterCalled);
+ assertTrue(target2.afterCalled);
+ }
+
+
+ public static class TestListener implements PhaseListener {
+
+ boolean beforeCalled = false;
+ boolean afterCalled = false;
+
+ public PhaseId getPhaseId() {
+ return PhaseId.ANY_PHASE;
+ }
+
+ public void beforePhase(PhaseEvent arg0) {
+ beforeCalled = true;
+ }
+
+ public void afterPhase(PhaseEvent arg0) {
+ afterCalled = true;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/jsf/DelegatingVariableResolverTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/jsf/DelegatingVariableResolverTests.java
new file mode 100644
index 00000000000..76e8c829b14
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/jsf/DelegatingVariableResolverTests.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.jsf;
+
+import javax.faces.context.FacesContext;
+import javax.faces.el.EvaluationException;
+import javax.faces.el.VariableResolver;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.StaticWebApplicationContext;
+
+/**
+ * @author Juergen Hoeller
+ * @since 02.08.2004
+ */
+public class DelegatingVariableResolverTests extends TestCase {
+
+ public void testDelegatingVariableResolver() {
+ final StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.registerSingleton("bean1", TestBean.class, null);
+ wac.registerSingleton("var1", TestBean.class, null);
+ wac.refresh();
+ TestBean bean1 = (TestBean) wac.getBean("bean1");
+
+ // We need to override the getWebApplicationContext method here:
+ // FacesContext and ExternalContext are hard to mock.
+ DelegatingVariableResolver resolver = new DelegatingVariableResolver(new OriginalVariableResolver()) {
+ protected WebApplicationContext getWebApplicationContext(FacesContext facesContext) {
+ return wac;
+ }
+ };
+ assertEquals(bean1, resolver.resolveVariable(null, "bean1"));
+ assertEquals("val1", resolver.resolveVariable(null, "var1"));
+ }
+
+ public void testSpringBeanVariableResolver() {
+ final StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.registerSingleton("bean1", TestBean.class, null);
+ wac.registerSingleton("var1", TestBean.class, null);
+ wac.refresh();
+ TestBean bean1 = (TestBean) wac.getBean("bean1");
+ TestBean var1 = (TestBean) wac.getBean("var1");
+
+ // We need to override the getWebApplicationContext method here:
+ // FacesContext and ExternalContext are hard to mock.
+ SpringBeanVariableResolver resolver = new SpringBeanVariableResolver(new OriginalVariableResolver()) {
+ protected WebApplicationContext getWebApplicationContext(FacesContext facesContext) {
+ return wac;
+ }
+ };
+ assertEquals(bean1, resolver.resolveVariable(null, "bean1"));
+ assertEquals(var1, resolver.resolveVariable(null, "var1"));
+ }
+
+
+ private static class OriginalVariableResolver extends VariableResolver {
+
+ public Object resolveVariable(FacesContext facesContext, String name) throws EvaluationException {
+ if ("var1".equals(name)) {
+ return "val1";
+ }
+ return null;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/jsf/MockFacesContext.java b/org.springframework.testsuite/src/test/java/org/springframework/web/jsf/MockFacesContext.java
new file mode 100644
index 00000000000..91c775c6a32
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/jsf/MockFacesContext.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.jsf;
+
+import java.util.Iterator;
+
+import javax.faces.application.Application;
+import javax.faces.application.FacesMessage;
+import javax.faces.application.FacesMessage.Severity;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseStream;
+import javax.faces.context.ResponseWriter;
+import javax.faces.render.RenderKit;
+
+/**
+ * Mock implementation of the FacesContext class to facilitate
+ * standalone Action unit tests.
+ *
+ * @author Ulrik Sandberg
+ * @see javax.faces.context.FacesContext
+ */
+public class MockFacesContext extends FacesContext {
+
+ private ExternalContext externalContext;
+
+ private Application application;
+
+ private UIViewRoot viewRoot;
+
+
+ public Application getApplication() {
+ return application;
+ }
+
+ public void setApplication(Application application) {
+ this.application = application;
+ }
+
+ public Iterator getClientIdsWithMessages() {
+ return null;
+ }
+
+ public ExternalContext getExternalContext() {
+ return externalContext;
+ }
+
+ public void setExternalContext(ExternalContext externalContext) {
+ this.externalContext = externalContext;
+ }
+
+ public Severity getMaximumSeverity() {
+ return null;
+ }
+
+ public Iterator getMessages() {
+ return null;
+ }
+
+ public Iterator getMessages(String arg0) {
+ return null;
+ }
+
+ public RenderKit getRenderKit() {
+ return null;
+ }
+
+ public boolean getRenderResponse() {
+ return false;
+ }
+
+ public boolean getResponseComplete() {
+ return false;
+ }
+
+ public ResponseStream getResponseStream() {
+ return null;
+ }
+
+ public void setResponseStream(ResponseStream arg0) {
+ }
+
+ public ResponseWriter getResponseWriter() {
+ return null;
+ }
+
+ public void setResponseWriter(ResponseWriter arg0) {
+ }
+
+ public UIViewRoot getViewRoot() {
+ return viewRoot;
+ }
+
+ public void setViewRoot(UIViewRoot viewRoot) {
+ this.viewRoot = viewRoot;
+ }
+
+ public void addMessage(String arg0, FacesMessage arg1) {
+ }
+
+ public void release() {
+ }
+
+ public void renderResponse() {
+ }
+
+ public void responseComplete() {
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/jsf/MockLifecycle.java b/org.springframework.testsuite/src/test/java/org/springframework/web/jsf/MockLifecycle.java
new file mode 100644
index 00000000000..29a22aa6fcf
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/jsf/MockLifecycle.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.jsf;
+
+import javax.faces.FacesException;
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseListener;
+import javax.faces.lifecycle.Lifecycle;
+
+/**
+ * @author Juergen Hoeller
+ * @since 29.01.2006
+ */
+public class MockLifecycle extends Lifecycle {
+
+ public void addPhaseListener(PhaseListener phaseListener) {
+ }
+
+ public void execute(FacesContext facesContext) throws FacesException {
+ }
+
+ public PhaseListener[] getPhaseListeners() {
+ return null;
+ }
+
+ public void removePhaseListener(PhaseListener phaseListener) {
+ }
+
+ public void render(FacesContext facesContext) throws FacesException {
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/multipart/MockMultipartHttpServletRequestTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/multipart/MockMultipartHttpServletRequestTests.java
new file mode 100644
index 00000000000..6352a08bf04
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/multipart/MockMultipartHttpServletRequestTests.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.multipart;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.mock.web.MockMultipartHttpServletRequest;
+import org.springframework.util.FileCopyUtils;
+import org.springframework.util.ObjectUtils;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class MockMultipartHttpServletRequestTests extends TestCase {
+
+ public void testMockMultipartHttpServletRequestWithByteArray() throws IOException {
+ MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
+ assertFalse(request.getFileNames().hasNext());
+ assertNull(request.getFile("file1"));
+ assertNull(request.getFile("file2"));
+ assertTrue(request.getFileMap().isEmpty());
+
+ request.addFile(new MockMultipartFile("file1", "myContent1".getBytes()));
+ request.addFile(new MockMultipartFile("file2", "myOrigFilename", "text/plain", "myContent2".getBytes()));
+ doTestMultipartHttpServletRequest(request);
+ }
+
+ public void testMockMultipartHttpServletRequestWithInputStream() throws IOException {
+ MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
+ request.addFile(new MockMultipartFile("file1", new ByteArrayInputStream("myContent1".getBytes())));
+ request.addFile(new MockMultipartFile("file2", "myOrigFilename", "text/plain", new ByteArrayInputStream("myContent2".getBytes())));
+ doTestMultipartHttpServletRequest(request);
+ }
+
+ private void doTestMultipartHttpServletRequest(MultipartHttpServletRequest request) throws IOException {
+ Set fileNames = new HashSet();
+ Iterator fileIter = request.getFileNames();
+ while (fileIter.hasNext()) {
+ fileNames.add(fileIter.next());
+ }
+ assertEquals(2, fileNames.size());
+ assertTrue(fileNames.contains("file1"));
+ assertTrue(fileNames.contains("file2"));
+ MultipartFile file1 = request.getFile("file1");
+ MultipartFile file2 = request.getFile("file2");
+ Map fileMap = request.getFileMap();
+ List fileMapKeys = new LinkedList(fileMap.keySet());
+ assertEquals(2, fileMapKeys.size());
+ assertEquals(file1, fileMap.get("file1"));
+ assertEquals(file2, fileMap.get("file2"));
+
+ assertEquals("file1", file1.getName());
+ assertEquals("", file1.getOriginalFilename());
+ assertNull(file1.getContentType());
+ assertTrue(ObjectUtils.nullSafeEquals("myContent1".getBytes(), file1.getBytes()));
+ assertTrue(ObjectUtils.nullSafeEquals("myContent1".getBytes(), FileCopyUtils.copyToByteArray(file1.getInputStream())));
+ assertEquals("file2", file2.getName());
+ assertEquals("myOrigFilename", file2.getOriginalFilename());
+ assertEquals("text/plain", file2.getContentType());
+ assertTrue(ObjectUtils.nullSafeEquals("myContent2".getBytes(), file2.getBytes()));
+ assertTrue(ObjectUtils.nullSafeEquals("myContent2".getBytes(), FileCopyUtils.copyToByteArray(file2.getInputStream())));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/multipart/commons/CommonsMultipartResolverTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/multipart/commons/CommonsMultipartResolverTests.java
new file mode 100644
index 00000000000..015d4fdb738
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/multipart/commons/CommonsMultipartResolverTests.java
@@ -0,0 +1,485 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.web.multipart.commons;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import junit.framework.TestCase;
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileItemFactory;
+import org.apache.commons.fileupload.FileUpload;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.mock.web.MockFilterConfig;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.mock.web.PassThroughFilterChain;
+import org.springframework.web.bind.ServletRequestDataBinder;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.StaticWebApplicationContext;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.MultipartHttpServletRequest;
+import org.springframework.web.multipart.support.ByteArrayMultipartFileEditor;
+import org.springframework.web.multipart.support.MultipartFilter;
+import org.springframework.web.multipart.support.StringMultipartFileEditor;
+import org.springframework.web.util.WebUtils;
+
+/**
+ * @author Juergen Hoeller
+ * @since 08.10.2003
+ */
+public class CommonsMultipartResolverTests extends TestCase {
+
+ public void testWithApplicationContext() throws Exception {
+ doTestWithApplicationContext(false);
+ }
+
+ public void testWithApplicationContextAndLazyResolution() throws Exception {
+ doTestWithApplicationContext(true);
+ }
+
+ private void doTestWithApplicationContext(boolean lazy) throws Exception {
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(new MockServletContext());
+ wac.getServletContext().setAttribute(WebUtils.TEMP_DIR_CONTEXT_ATTRIBUTE, new File("mytemp"));
+ wac.refresh();
+ MockCommonsMultipartResolver resolver = new MockCommonsMultipartResolver();
+ resolver.setMaxUploadSize(1000);
+ resolver.setMaxInMemorySize(100);
+ resolver.setDefaultEncoding("enc");
+ if (lazy) {
+ resolver.setResolveLazily(false);
+ }
+ resolver.setServletContext(wac.getServletContext());
+ assertEquals(1000, resolver.getFileUpload().getSizeMax());
+ assertEquals(100, resolver.getFileItemFactory().getSizeThreshold());
+ assertEquals("enc", resolver.getFileUpload().getHeaderEncoding());
+ assertTrue(resolver.getFileItemFactory().getRepository().getAbsolutePath().endsWith("mytemp"));
+
+ MockHttpServletRequest originalRequest = new MockHttpServletRequest();
+ originalRequest.setMethod("POST");
+ originalRequest.setContentType("multipart/form-data");
+ originalRequest.addHeader("Content-type", "multipart/form-data");
+ originalRequest.addParameter("getField", "getValue");
+ assertTrue(resolver.isMultipart(originalRequest));
+ MultipartHttpServletRequest request = resolver.resolveMultipart(originalRequest);
+
+ Set parameterNames = new HashSet();
+ Enumeration parameterEnum = request.getParameterNames();
+ while (parameterEnum.hasMoreElements()) {
+ parameterNames.add(parameterEnum.nextElement());
+ }
+ assertEquals(3, parameterNames.size());
+ assertTrue(parameterNames.contains("field3"));
+ assertTrue(parameterNames.contains("field4"));
+ assertTrue(parameterNames.contains("getField"));
+ assertEquals("value3", request.getParameter("field3"));
+ List parameterValues = Arrays.asList(request.getParameterValues("field3"));
+ assertEquals(1, parameterValues.size());
+ assertTrue(parameterValues.contains("value3"));
+ assertEquals("value4", request.getParameter("field4"));
+ parameterValues = Arrays.asList(request.getParameterValues("field4"));
+ assertEquals(2, parameterValues.size());
+ assertTrue(parameterValues.contains("value4"));
+ assertTrue(parameterValues.contains("value5"));
+ assertEquals("value4", request.getParameter("field4"));
+ assertEquals("getValue", request.getParameter("getField"));
+
+ List parameterMapKeys = new ArrayList();
+ List parameterMapValues = new ArrayList();
+ for (Iterator parameterMapIter = request.getParameterMap().keySet().iterator(); parameterMapIter.hasNext();) {
+ String key = (String) parameterMapIter.next();
+ parameterMapKeys.add(key);
+ parameterMapValues.add(request.getParameterMap().get(key));
+ }
+ assertEquals(3, parameterMapKeys.size());
+ assertEquals(3, parameterMapValues.size());
+ int field3Index = parameterMapKeys.indexOf("field3");
+ int field4Index = parameterMapKeys.indexOf("field4");
+ int getFieldIndex = parameterMapKeys.indexOf("getField");
+ assertTrue(field3Index != -1);
+ assertTrue(field4Index != -1);
+ assertTrue(getFieldIndex != -1);
+ parameterValues = Arrays.asList((String[]) parameterMapValues.get(field3Index));
+ assertEquals(1, parameterValues.size());
+ assertTrue(parameterValues.contains("value3"));
+ parameterValues = Arrays.asList((String[]) parameterMapValues.get(field4Index));
+ assertEquals(2, parameterValues.size());
+ assertTrue(parameterValues.contains("value4"));
+ assertTrue(parameterValues.contains("value5"));
+ parameterValues = Arrays.asList((String[]) parameterMapValues.get(getFieldIndex));
+ assertEquals(1, parameterValues.size());
+ assertTrue(parameterValues.contains("getValue"));
+
+ Set fileNames = new HashSet();
+ Iterator fileIter = request.getFileNames();
+ while (fileIter.hasNext()) {
+ fileNames.add(fileIter.next());
+ }
+ assertEquals(3, fileNames.size());
+ assertTrue(fileNames.contains("field1"));
+ assertTrue(fileNames.contains("field2"));
+ assertTrue(fileNames.contains("field2x"));
+ CommonsMultipartFile file1 = (CommonsMultipartFile) request.getFile("field1");
+ CommonsMultipartFile file2 = (CommonsMultipartFile) request.getFile("field2");
+ CommonsMultipartFile file2x = (CommonsMultipartFile) request.getFile("field2x");
+ Map fileMap = request.getFileMap();
+ assertEquals(3, fileMap.size());
+ assertTrue(fileMap.containsKey("field1"));
+ assertTrue(fileMap.containsKey("field2"));
+ assertTrue(fileMap.containsKey("field2x"));
+ assertEquals(file1, fileMap.get("field1"));
+ assertEquals(file2, fileMap.get("field2"));
+ assertEquals(file2x, fileMap.get("field2x"));
+
+ assertEquals("type1", file1.getContentType());
+ assertEquals("type2", file2.getContentType());
+ assertEquals("type2", file2x.getContentType());
+ assertEquals("field1.txt", file1.getOriginalFilename());
+ assertEquals("field2.txt", file2.getOriginalFilename());
+ assertEquals("field2x.txt", file2x.getOriginalFilename());
+ assertEquals("text1", new String(file1.getBytes()));
+ assertEquals("text2", new String(file2.getBytes()));
+ assertEquals(5, file1.getSize());
+ assertEquals(5, file2.getSize());
+ assertTrue(file1.getInputStream() instanceof ByteArrayInputStream);
+ assertTrue(file2.getInputStream() instanceof ByteArrayInputStream);
+ File transfer1 = new File("C:/transfer1");
+ File transfer2 = new File("C:/transfer2");
+ file1.transferTo(transfer1);
+ file2.transferTo(transfer2);
+ assertEquals(transfer1, ((MockFileItem) file1.getFileItem()).writtenFile);
+ assertEquals(transfer2, ((MockFileItem) file2.getFileItem()).writtenFile);
+
+ MultipartTestBean1 mtb1 = new MultipartTestBean1();
+ assertEquals(null, mtb1.getField1());
+ assertEquals(null, mtb1.getField2());
+ ServletRequestDataBinder binder = new ServletRequestDataBinder(mtb1, "mybean");
+ binder.registerCustomEditor(byte[].class, new ByteArrayMultipartFileEditor());
+ binder.bind(request);
+ assertEquals(file1, mtb1.getField1());
+ assertEquals(new String(file2.getBytes()), new String(mtb1.getField2()));
+
+ MultipartTestBean2 mtb2 = new MultipartTestBean2();
+ assertEquals(null, mtb2.getField1());
+ assertEquals(null, mtb2.getField2());
+ binder = new ServletRequestDataBinder(mtb2, "mybean");
+ binder.registerCustomEditor(String.class, "field1", new StringMultipartFileEditor());
+ binder.registerCustomEditor(String.class, "field2", new StringMultipartFileEditor("UTF-16"));
+ binder.bind(request);
+ assertEquals(new String(file1.getBytes()), mtb2.getField1());
+ assertEquals(new String(file2.getBytes(), "UTF-16"), mtb2.getField2());
+
+ resolver.cleanupMultipart(request);
+ assertTrue(((MockFileItem) file1.getFileItem()).deleted);
+ assertTrue(((MockFileItem) file2.getFileItem()).deleted);
+
+ resolver.setEmpty(true);
+ request = resolver.resolveMultipart(originalRequest);
+ binder.setBindEmptyMultipartFiles(false);
+ String firstBound = mtb2.getField1();
+ binder.bind(request);
+ assertTrue(mtb2.getField1().length() > 0);
+ assertEquals(firstBound, mtb2.getField1());
+
+ request = resolver.resolveMultipart(originalRequest);
+ binder.setBindEmptyMultipartFiles(true);
+ binder.bind(request);
+ assertTrue(mtb2.getField1().length() == 0);
+ }
+
+ public void testWithServletContextAndFilter() throws Exception {
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(new MockServletContext());
+ wac.registerSingleton("filterMultipartResolver", MockCommonsMultipartResolver.class, new MutablePropertyValues());
+ wac.getServletContext().setAttribute(WebUtils.TEMP_DIR_CONTEXT_ATTRIBUTE, new File("mytemp"));
+ wac.refresh();
+ wac.getServletContext().setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
+ CommonsMultipartResolver resolver = new CommonsMultipartResolver(wac.getServletContext());
+ assertTrue(resolver.getFileItemFactory().getRepository().getAbsolutePath().endsWith("mytemp"));
+
+ MockFilterConfig filterConfig = new MockFilterConfig(wac.getServletContext(), "filter");
+ filterConfig.addInitParameter("class", "notWritable");
+ filterConfig.addInitParameter("unknownParam", "someValue");
+ final MultipartFilter filter = new MultipartFilter();
+ filter.init(filterConfig);
+
+ final List files = new ArrayList();
+ final FilterChain filterChain = new FilterChain() {
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) {
+ MultipartHttpServletRequest request = (MultipartHttpServletRequest) servletRequest;
+ files.addAll(request.getFileMap().values());
+ }
+ };
+
+ FilterChain filterChain2 = new PassThroughFilterChain(filter, filterChain);
+
+ MockHttpServletRequest originalRequest = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ originalRequest.setMethod("POST");
+ originalRequest.setContentType("multipart/form-data");
+ originalRequest.addHeader("Content-type", "multipart/form-data");
+ filter.doFilter(originalRequest, response, filterChain2);
+
+ CommonsMultipartFile file1 = (CommonsMultipartFile) files.get(0);
+ CommonsMultipartFile file2 = (CommonsMultipartFile) files.get(1);
+ assertTrue(((MockFileItem) file1.getFileItem()).deleted);
+ assertTrue(((MockFileItem) file2.getFileItem()).deleted);
+ }
+
+ public void testWithServletContextAndFilterWithCustomBeanName() throws Exception {
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.setServletContext(new MockServletContext());
+ wac.refresh();
+ wac.registerSingleton("myMultipartResolver", MockCommonsMultipartResolver.class, new MutablePropertyValues());
+ wac.getServletContext().setAttribute(WebUtils.TEMP_DIR_CONTEXT_ATTRIBUTE, new File("mytemp"));
+ wac.getServletContext().setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
+ CommonsMultipartResolver resolver = new CommonsMultipartResolver(wac.getServletContext());
+ assertTrue(resolver.getFileItemFactory().getRepository().getAbsolutePath().endsWith("mytemp"));
+
+ MockFilterConfig filterConfig = new MockFilterConfig(wac.getServletContext(), "filter");
+ filterConfig.addInitParameter("multipartResolverBeanName", "myMultipartResolver");
+
+ final List files = new ArrayList();
+ FilterChain filterChain = new FilterChain() {
+ public void doFilter(ServletRequest originalRequest, ServletResponse response) {
+ if (originalRequest instanceof MultipartHttpServletRequest) {
+ MultipartHttpServletRequest request = (MultipartHttpServletRequest) originalRequest;
+ files.addAll(request.getFileMap().values());
+ }
+ }
+ };
+
+ MultipartFilter filter = new MultipartFilter() {
+ private boolean invoked = false;
+ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
+ FilterChain filterChain) throws ServletException, IOException {
+ super.doFilterInternal(request, response, filterChain);
+ super.doFilterInternal(request, response, filterChain);
+ if (invoked) {
+ throw new ServletException("Should not have been invoked twice");
+ }
+ invoked = true;
+ }
+ };
+ filter.init(filterConfig);
+
+ MockHttpServletRequest originalRequest = new MockHttpServletRequest();
+ originalRequest.setMethod("POST");
+ originalRequest.setContentType("multipart/form-data");
+ originalRequest.addHeader("Content-type", "multipart/form-data");
+ HttpServletResponse response = new MockHttpServletResponse();
+ filter.doFilter(originalRequest, response, filterChain);
+ CommonsMultipartFile file1 = (CommonsMultipartFile) files.get(0);
+ CommonsMultipartFile file2 = (CommonsMultipartFile) files.get(1);
+ assertTrue(((MockFileItem) file1.getFileItem()).deleted);
+ assertTrue(((MockFileItem) file2.getFileItem()).deleted);
+ }
+
+
+ public static class MockCommonsMultipartResolver extends CommonsMultipartResolver {
+
+ private boolean empty;
+
+ protected void setEmpty(boolean empty) {
+ this.empty = empty;
+ }
+
+ protected FileUpload newFileUpload(FileItemFactory fileItemFactory) {
+ return new ServletFileUpload() {
+ public List parseRequest(HttpServletRequest request) {
+ if (request instanceof MultipartHttpServletRequest) {
+ throw new IllegalStateException("Already a multipart request");
+ }
+ List fileItems = new ArrayList();
+ MockFileItem fileItem1 = new MockFileItem(
+ "field1", "type1", empty ? "" : "field1.txt", empty ? "" : "text1");
+ MockFileItem fileItem2 = new MockFileItem(
+ "field2", "type2", empty ? "" : "C:/field2.txt", empty ? "" : "text2");
+ MockFileItem fileItem2x = new MockFileItem(
+ "field2x", "type2", empty ? "" : "C:\\field2x.txt", empty ? "" : "text2");
+ MockFileItem fileItem3 = new MockFileItem("field3", null, null, "value3");
+ MockFileItem fileItem4 = new MockFileItem("field4", null, null, "value4");
+ MockFileItem fileItem5 = new MockFileItem("field4", null, null, "value5");
+ fileItems.add(fileItem1);
+ fileItems.add(fileItem2);
+ fileItems.add(fileItem2x);
+ fileItems.add(fileItem3);
+ fileItems.add(fileItem4);
+ fileItems.add(fileItem5);
+ return fileItems;
+ }
+ };
+ }
+ }
+
+
+ private static class MockFileItem implements FileItem {
+
+ private String fieldName;
+ private String contentType;
+ private String name;
+ private String value;
+
+ private File writtenFile;
+ private boolean deleted;
+
+ public MockFileItem(String fieldName, String contentType, String name, String value) {
+ this.fieldName = fieldName;
+ this.contentType = contentType;
+ this.name = name;
+ this.value = value;
+ }
+
+ public InputStream getInputStream() throws IOException {
+ return new ByteArrayInputStream(value.getBytes());
+ }
+
+ public String getContentType() {
+ return contentType;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public boolean isInMemory() {
+ return true;
+ }
+
+ public long getSize() {
+ return value.length();
+ }
+
+ public byte[] get() {
+ return value.getBytes();
+ }
+
+ public String getString(String encoding) throws UnsupportedEncodingException {
+ return new String(get(), encoding);
+ }
+
+ public String getString() {
+ return value;
+ }
+
+ public void write(File file) throws Exception {
+ this.writtenFile = file;
+ }
+
+ public File getWrittenFile() {
+ return writtenFile;
+ }
+
+ public void delete() {
+ this.deleted = true;
+ }
+
+ public boolean isDeleted() {
+ return deleted;
+ }
+
+ public String getFieldName() {
+ return fieldName;
+ }
+
+ public void setFieldName(String s) {
+ this.fieldName = s;
+ }
+
+ public boolean isFormField() {
+ return (this.name == null);
+ }
+
+ public void setFormField(boolean b) {
+ throw new UnsupportedOperationException();
+ }
+
+ public OutputStream getOutputStream() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+
+ public class MultipartTestBean1 {
+
+ private MultipartFile field1;
+ private byte[] field2;
+
+ public void setField1(MultipartFile field1) {
+ this.field1 = field1;
+ }
+
+ public MultipartFile getField1() {
+ return field1;
+ }
+
+ public void setField2(byte[] field2) {
+ this.field2 = field2;
+ }
+
+ public byte[] getField2() {
+ return field2;
+ }
+ }
+
+
+ public class MultipartTestBean2 {
+
+ private String field1;
+ private String field2;
+
+ public void setField1(String field1) {
+ this.field1 = field1;
+ }
+
+ public String getField1() {
+ return field1;
+ }
+
+ public void setField2(String field2) {
+ this.field2 = field2;
+ }
+
+ public String getField2() {
+ return field2;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/multipart/support/ByteArrayMultipartFileEditorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/multipart/support/ByteArrayMultipartFileEditorTests.java
new file mode 100644
index 00000000000..169f2477e01
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/multipart/support/ByteArrayMultipartFileEditorTests.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.multipart.support;
+
+import java.io.IOException;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * @author Rick Evans
+ */
+public final class ByteArrayMultipartFileEditorTests extends TestCase {
+
+ public void testSetValueAsByteArray() throws Exception {
+ ByteArrayMultipartFileEditor editor = new ByteArrayMultipartFileEditor();
+ String expectedValue = "Shumwere, shumhow, a shuck ish washing you. - Drunken Far Side";
+ editor.setValue(expectedValue.getBytes());
+ assertEquals(expectedValue, editor.getAsText());
+ }
+
+ public void testSetValueAsString() throws Exception {
+ ByteArrayMultipartFileEditor editor = new ByteArrayMultipartFileEditor();
+ String expectedValue = "'Green Wing' - classic British comedy";
+ editor.setValue(expectedValue);
+ assertEquals(expectedValue, editor.getAsText());
+ }
+
+ public void testSetValueAsCustomObjectInvokesToString() throws Exception {
+ ByteArrayMultipartFileEditor editor = new ByteArrayMultipartFileEditor();
+ final String expectedValue = "'Green Wing' - classic British comedy";
+ Object object = new Object() {
+ public String toString() {
+ return expectedValue;
+ }
+ };
+ editor.setValue(object);
+ assertEquals(expectedValue, editor.getAsText());
+ }
+
+ public void testSetValueAsNullGetsBackEmptyString() throws Exception {
+ ByteArrayMultipartFileEditor editor = new ByteArrayMultipartFileEditor();
+ editor.setValue(null);
+ assertEquals("", editor.getAsText());
+ }
+
+ public void testSetValueAsMultipartFile() throws Exception {
+ String expectedValue = "That is comforting to know";
+ ByteArrayMultipartFileEditor editor = new ByteArrayMultipartFileEditor();
+ MockControl mock = MockControl.createControl(MultipartFile.class);
+ MultipartFile file = (MultipartFile) mock.getMock();
+ file.getBytes();
+ mock.setReturnValue(expectedValue.getBytes());
+ mock.replay();
+ editor.setValue(file);
+ assertEquals(expectedValue, editor.getAsText());
+ mock.verify();
+ }
+
+ public void testSetValueAsMultipartFileWithBadBytes() throws Exception {
+ ByteArrayMultipartFileEditor editor = new ByteArrayMultipartFileEditor();
+ MockControl mock = MockControl.createControl(MultipartFile.class);
+ MultipartFile file = (MultipartFile) mock.getMock();
+ file.getBytes();
+ mock.setThrowable(new IOException());
+ mock.replay();
+ try {
+ editor.setValue(file);
+ fail("Must have thrown an IllegalArgumentException: IOException thrown when reading MultipartFile bytes");
+ }
+ catch (IllegalArgumentException expected) {
+ }
+ mock.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/ComplexPortletApplicationContext.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/ComplexPortletApplicationContext.java
new file mode 100644
index 00000000000..f7aa8c1aad8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/ComplexPortletApplicationContext.java
@@ -0,0 +1,504 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.portlet;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.Portlet;
+import javax.portlet.PortletConfig;
+import javax.portlet.PortletException;
+import javax.portlet.PortletRequest;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.factory.config.ConstructorArgumentValues;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
+import org.springframework.beans.factory.support.ManagedList;
+import org.springframework.beans.factory.support.ManagedMap;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.i18n.LocaleContextHolder;
+import org.springframework.core.Ordered;
+import org.springframework.mock.web.portlet.MockPortletConfig;
+import org.springframework.mock.web.portlet.MockPortletContext;
+import org.springframework.web.multipart.MaxUploadSizeExceededException;
+import org.springframework.web.multipart.MultipartException;
+import org.springframework.web.portlet.bind.PortletRequestBindingException;
+import org.springframework.web.portlet.context.PortletRequestHandledEvent;
+import org.springframework.web.portlet.context.StaticPortletApplicationContext;
+import org.springframework.web.portlet.handler.ParameterHandlerMapping;
+import org.springframework.web.portlet.handler.ParameterMappingInterceptor;
+import org.springframework.web.portlet.handler.PortletModeHandlerMapping;
+import org.springframework.web.portlet.handler.PortletModeParameterHandlerMapping;
+import org.springframework.web.portlet.handler.SimpleMappingExceptionResolver;
+import org.springframework.web.portlet.handler.SimplePortletHandlerAdapter;
+import org.springframework.web.portlet.handler.SimplePortletPostProcessor;
+import org.springframework.web.portlet.handler.UserRoleAuthorizationInterceptor;
+import org.springframework.web.portlet.multipart.DefaultMultipartActionRequest;
+import org.springframework.web.portlet.multipart.MultipartActionRequest;
+import org.springframework.web.portlet.multipart.PortletMultipartResolver;
+import org.springframework.web.portlet.mvc.Controller;
+import org.springframework.web.portlet.mvc.SimpleControllerHandlerAdapter;
+
+/**
+ * @author Juergen Hoeller
+ * @author Mark Fisher
+ */
+public class ComplexPortletApplicationContext extends StaticPortletApplicationContext {
+
+ public void refresh() throws BeansException {
+ registerSingleton("standardHandlerAdapter", SimpleControllerHandlerAdapter.class);
+ registerSingleton("portletHandlerAdapter", SimplePortletHandlerAdapter.class);
+ registerSingleton("myHandlerAdapter", MyHandlerAdapter.class);
+
+ registerSingleton("viewController", ViewController.class);
+ registerSingleton("editController", EditController.class);
+ registerSingleton("helpController1", HelpController1.class);
+ registerSingleton("helpController2", HelpController2.class);
+ registerSingleton("testController1", TestController1.class);
+ registerSingleton("testController2", TestController2.class);
+ registerSingleton("requestLocaleCheckingController", RequestLocaleCheckingController.class);
+ registerSingleton("localeContextCheckingController", LocaleContextCheckingController.class);
+
+ registerSingleton("exceptionThrowingHandler1", ExceptionThrowingHandler.class);
+ registerSingleton("exceptionThrowingHandler2", ExceptionThrowingHandler.class);
+ registerSingleton("unknownHandler", Object.class);
+
+ registerSingleton("myPortlet", MyPortlet.class);
+ registerSingleton("portletMultipartResolver", MockMultipartResolver.class);
+ registerSingleton("portletPostProcessor", SimplePortletPostProcessor.class);
+ registerSingleton("testListener", TestApplicationListener.class);
+
+ ConstructorArgumentValues cvs = new ConstructorArgumentValues();
+ cvs.addIndexedArgumentValue(0, new MockPortletContext());
+ cvs.addIndexedArgumentValue(1, "complex");
+ registerBeanDefinition("portletConfig", new RootBeanDefinition(MockPortletConfig.class, cvs, null));
+
+ UserRoleAuthorizationInterceptor userRoleInterceptor = new UserRoleAuthorizationInterceptor();
+ userRoleInterceptor.setAuthorizedRoles(new String[] {"role1", "role2"});
+
+ ParameterHandlerMapping interceptingHandlerMapping = new ParameterHandlerMapping();
+ interceptingHandlerMapping.setParameterName("interceptingParam");
+ ParameterMappingInterceptor parameterMappingInterceptor = new ParameterMappingInterceptor();
+ parameterMappingInterceptor.setParameterName("interceptingParam");
+
+ List interceptors = new ArrayList();
+ interceptors.add(parameterMappingInterceptor);
+ interceptors.add(userRoleInterceptor);
+ interceptors.add(new MyHandlerInterceptor1());
+ interceptors.add(new MyHandlerInterceptor2());
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ Map portletModeMap = new ManagedMap();
+ portletModeMap.put("view", new RuntimeBeanReference("viewController"));
+ portletModeMap.put("edit", new RuntimeBeanReference("editController"));
+ pvs.addPropertyValue("portletModeMap", portletModeMap);
+ pvs.addPropertyValue("interceptors", interceptors);
+ registerSingleton("handlerMapping3", PortletModeHandlerMapping.class, pvs);
+
+ pvs = new MutablePropertyValues();
+ Map parameterMap = new ManagedMap();
+ parameterMap.put("test1", new RuntimeBeanReference("testController1"));
+ parameterMap.put("test2", new RuntimeBeanReference("testController2"));
+ parameterMap.put("requestLocaleChecker", new RuntimeBeanReference("requestLocaleCheckingController"));
+ parameterMap.put("contextLocaleChecker", new RuntimeBeanReference("localeContextCheckingController"));
+ parameterMap.put("exception1", new RuntimeBeanReference("exceptionThrowingHandler1"));
+ parameterMap.put("exception2", new RuntimeBeanReference("exceptionThrowingHandler2"));
+ parameterMap.put("myPortlet", new RuntimeBeanReference("myPortlet"));
+ parameterMap.put("unknown", new RuntimeBeanReference("unknownHandler"));
+ pvs.addPropertyValue("parameterMap", parameterMap);
+ pvs.addPropertyValue("parameterName", "myParam");
+ pvs.addPropertyValue("order", "2");
+ registerSingleton("handlerMapping2", ParameterHandlerMapping.class, pvs);
+
+ pvs = new MutablePropertyValues();
+ Map innerMap = new ManagedMap();
+ innerMap.put("help1", new RuntimeBeanReference("helpController1"));
+ innerMap.put("help2", new RuntimeBeanReference("helpController2"));
+ Map outerMap = new ManagedMap();
+ outerMap.put("help", innerMap);
+ pvs.addPropertyValue("portletModeParameterMap", outerMap);
+ pvs.addPropertyValue("order", "1");
+ registerSingleton("handlerMapping1", PortletModeParameterHandlerMapping.class, pvs);
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("order", "1");
+ pvs.addPropertyValue("exceptionMappings",
+ "java.lang.IllegalAccessException=failed-illegalaccess\n" +
+ "PortletRequestBindingException=failed-binding\n" +
+ "UnavailableException=failed-unavailable");
+ pvs.addPropertyValue("defaultErrorView", "failed-default-1");
+ registerSingleton("exceptionResolver", SimpleMappingExceptionResolver.class, pvs);
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("order", "0");
+ pvs.addPropertyValue("exceptionMappings",
+ "java.lang.Exception=failed-exception\n" +
+ "java.lang.RuntimeException=failed-runtime");
+ List mappedHandlers = new ManagedList();
+ mappedHandlers.add(new RuntimeBeanReference("exceptionThrowingHandler1"));
+ pvs.addPropertyValue("mappedHandlers", mappedHandlers);
+ pvs.addPropertyValue("defaultErrorView", "failed-default-0");
+ registerSingleton("handlerExceptionResolver", SimpleMappingExceptionResolver.class, pvs);
+
+ addMessage("test", Locale.ENGLISH, "test message");
+ addMessage("test", Locale.CANADA, "Canadian & test message");
+ addMessage("test.args", Locale.ENGLISH, "test {0} and {1}");
+
+ super.refresh();
+ }
+
+
+ public static class TestController1 implements Controller {
+
+ public void handleActionRequest(ActionRequest request, ActionResponse response) {
+ response.setRenderParameter("result", "test1-action");
+ }
+
+ public ModelAndView handleRenderRequest(RenderRequest request, RenderResponse response) throws Exception {
+ return null;
+ }
+ }
+
+
+ public static class TestController2 implements Controller {
+
+ public void handleActionRequest(ActionRequest request, ActionResponse response) {}
+
+ public ModelAndView handleRenderRequest(RenderRequest request, RenderResponse response) throws Exception {
+ response.setProperty("result", "test2-view");
+ return null;
+ }
+ }
+
+
+ public static class ViewController implements Controller {
+
+ public void handleActionRequest(ActionRequest request, ActionResponse response) {}
+
+ public ModelAndView handleRenderRequest(RenderRequest request, RenderResponse response) throws Exception {
+ return new ModelAndView("someViewName", "result", "view was here");
+ }
+ }
+
+
+ public static class EditController implements Controller {
+
+ public void handleActionRequest(ActionRequest request, ActionResponse response) {
+ response.setRenderParameter("param", "edit was here");
+ }
+
+ public ModelAndView handleRenderRequest(RenderRequest request, RenderResponse response) throws Exception {
+ return new ModelAndView(request.getParameter("param"));
+ }
+ }
+
+
+ public static class HelpController1 implements Controller {
+
+ public void handleActionRequest(ActionRequest request, ActionResponse response) {
+ response.setRenderParameter("param", "help1 was here");
+ }
+
+ public ModelAndView handleRenderRequest(RenderRequest request, RenderResponse response) throws Exception {
+ return new ModelAndView("help1-view");
+ }
+ }
+
+
+ public static class HelpController2 implements Controller {
+
+ public void handleActionRequest(ActionRequest request, ActionResponse response) {
+ response.setRenderParameter("param", "help2 was here");
+ }
+
+ public ModelAndView handleRenderRequest(RenderRequest request, RenderResponse response) throws Exception {
+ return new ModelAndView("help2-view");
+ }
+ }
+
+ public static class RequestLocaleCheckingController implements Controller {
+
+ public void handleActionRequest(ActionRequest request, ActionResponse response) throws PortletException {
+ if (!Locale.CANADA.equals(request.getLocale())) {
+ throw new PortletException("Incorrect Locale in ActionRequest");
+ }
+ }
+
+ public ModelAndView handleRenderRequest(RenderRequest request, RenderResponse response)
+ throws PortletException, IOException {
+ if (!Locale.CANADA.equals(request.getLocale())) {
+ throw new PortletException("Incorrect Locale in RenderRequest");
+ }
+ response.getWriter().write("locale-ok");
+ return null;
+ }
+ }
+
+
+ public static class LocaleContextCheckingController implements Controller {
+
+ public void handleActionRequest(ActionRequest request, ActionResponse response) throws PortletException {
+ if (!Locale.CANADA.equals(LocaleContextHolder.getLocale())) {
+ throw new PortletException("Incorrect Locale in LocaleContextHolder");
+ }
+ }
+
+ public ModelAndView handleRenderRequest(RenderRequest request, RenderResponse response)
+ throws PortletException, IOException {
+ if (!Locale.CANADA.equals(LocaleContextHolder.getLocale())) {
+ throw new PortletException("Incorrect Locale in LocaleContextHolder");
+ }
+ response.getWriter().write("locale-ok");
+ return null;
+ }
+ }
+
+
+ public static class MyPortlet implements Portlet {
+
+ private PortletConfig portletConfig;
+
+ public void init(PortletConfig portletConfig) throws PortletException {
+ this.portletConfig = portletConfig;
+ }
+
+ public void processAction(ActionRequest request, ActionResponse response) throws PortletException {
+ response.setRenderParameter("result", "myPortlet action called");
+ }
+
+ public void render(RenderRequest request, RenderResponse response) throws PortletException, IOException {
+ response.getWriter().write("myPortlet was here");
+ }
+
+ public PortletConfig getPortletConfig() {
+ return this.portletConfig;
+ }
+
+ public void destroy() {
+ this.portletConfig = null;
+ }
+ }
+
+
+ public static interface MyHandler {
+
+ public void doSomething(PortletRequest request) throws Exception;
+ }
+
+
+ public static class ExceptionThrowingHandler implements MyHandler {
+
+ public void doSomething(PortletRequest request) throws Exception {
+ if (request.getParameter("fail") != null) {
+ throw new ModelAndViewDefiningException(new ModelAndView("failed-modelandview"));
+ }
+ if (request.getParameter("access") != null) {
+ throw new IllegalAccessException("portlet-illegalaccess");
+ }
+ if (request.getParameter("binding") != null) {
+ throw new PortletRequestBindingException("portlet-binding");
+ }
+ if (request.getParameter("generic") != null) {
+ throw new Exception("portlet-generic");
+ }
+ if (request.getParameter("runtime") != null) {
+ throw new RuntimeException("portlet-runtime");
+ }
+ throw new IllegalArgumentException("illegal argument");
+ }
+ }
+
+
+ public static class MyHandlerAdapter implements HandlerAdapter, Ordered {
+
+ public int getOrder() {
+ return 99;
+ }
+
+ public boolean supports(Object handler) {
+ return handler != null && MyHandler.class.isAssignableFrom(handler.getClass());
+ }
+
+ public void handleAction(ActionRequest request, ActionResponse response, Object delegate) throws Exception {
+ ((MyHandler) delegate).doSomething(request);
+ }
+
+ public ModelAndView handleRender(RenderRequest request, RenderResponse response, Object delegate) throws Exception {
+ ((MyHandler) delegate).doSomething(request);
+ return null;
+ }
+ }
+
+
+ public static class MyHandlerInterceptor1 implements HandlerInterceptor {
+
+ public boolean preHandleAction(ActionRequest request, ActionResponse response, Object handler) {
+ return true;
+ }
+
+ public void afterActionCompletion(ActionRequest request, ActionResponse response, Object handler, Exception ex) {
+ }
+
+ public boolean preHandleRender(RenderRequest request, RenderResponse response, Object handler)
+ throws PortletException {
+ if (request.getAttribute("test2-remove-never") != null) {
+ throw new PortletException("Wrong interceptor order");
+ }
+ request.setAttribute("test1-remove-never", "test1-remove-never");
+ request.setAttribute("test1-remove-post", "test1-remove-post");
+ request.setAttribute("test1-remove-after", "test1-remove-after");
+ return true;
+ }
+
+ public void postHandleRender(
+ RenderRequest request, RenderResponse response, Object handler, ModelAndView modelAndView)
+ throws PortletException {
+ if (request.getAttribute("test2-remove-post") != null) {
+ throw new PortletException("Wrong interceptor order");
+ }
+ if (!"test1-remove-post".equals(request.getAttribute("test1-remove-post"))) {
+ throw new PortletException("Incorrect request attribute");
+ }
+ request.removeAttribute("test1-remove-post");
+ }
+
+ public void afterRenderCompletion(
+ RenderRequest request, RenderResponse response, Object handler, Exception ex)
+ throws PortletException {
+ if (request.getAttribute("test2-remove-after") != null) {
+ throw new PortletException("Wrong interceptor order");
+ }
+ request.removeAttribute("test1-remove-after");
+ }
+ }
+
+
+ public static class MyHandlerInterceptor2 implements HandlerInterceptor {
+
+ public boolean preHandleAction(ActionRequest request, ActionResponse response, Object handler) {
+ return true;
+ }
+
+ public void afterActionCompletion(ActionRequest request, ActionResponse response, Object handler, Exception ex) {
+ }
+
+ public boolean preHandleRender(RenderRequest request, RenderResponse response, Object handler)
+ throws PortletException {
+ if (request.getAttribute("test1-remove-post") == null) {
+ throw new PortletException("Wrong interceptor order");
+ }
+ if ("true".equals(request.getParameter("abort"))) {
+ return false;
+ }
+ request.setAttribute("test2-remove-never", "test2-remove-never");
+ request.setAttribute("test2-remove-post", "test2-remove-post");
+ request.setAttribute("test2-remove-after", "test2-remove-after");
+ return true;
+ }
+
+ public void postHandleRender(
+ RenderRequest request, RenderResponse response, Object handler, ModelAndView modelAndView)
+ throws PortletException {
+ if ("true".equals(request.getParameter("noView"))) {
+ modelAndView.clear();
+ }
+ if (request.getAttribute("test1-remove-post") == null) {
+ throw new PortletException("Wrong interceptor order");
+ }
+ if (!"test2-remove-post".equals(request.getAttribute("test2-remove-post"))) {
+ throw new PortletException("Incorrect request attribute");
+ }
+ request.removeAttribute("test2-remove-post");
+ }
+
+ public void afterRenderCompletion(
+ RenderRequest request, RenderResponse response, Object handler, Exception ex)
+ throws Exception {
+ if (request.getAttribute("test1-remove-after") == null) {
+ throw new PortletException("Wrong interceptor order");
+ }
+ request.removeAttribute("test2-remove-after");
+ }
+ }
+
+
+ public static class MultipartCheckingHandler implements MyHandler {
+
+ public void doSomething(PortletRequest request) throws PortletException, IllegalAccessException {
+ if (!(request instanceof MultipartActionRequest)) {
+ throw new PortletException("Not in a MultipartActionRequest");
+ }
+ }
+ }
+
+
+ public static class MockMultipartResolver implements PortletMultipartResolver {
+
+ public boolean isMultipart(ActionRequest request) {
+ return true;
+ }
+
+ public MultipartActionRequest resolveMultipart(ActionRequest request) throws MultipartException {
+ if (request.getAttribute("fail") != null) {
+ throw new MaxUploadSizeExceededException(1000);
+ }
+ if (request instanceof MultipartActionRequest) {
+ throw new IllegalStateException("Already a multipart request");
+ }
+ if (request.getAttribute("resolved") != null) {
+ throw new IllegalStateException("Already resolved");
+ }
+ request.setAttribute("resolved", Boolean.TRUE);
+ Map files = new HashMap();
+ files.put("someFile", "someFile");
+ Map params = new HashMap();
+ params.put("someParam", "someParam");
+ return new DefaultMultipartActionRequest(request, files, params);
+ }
+
+ public void cleanupMultipart(MultipartActionRequest request) {
+ if (request.getAttribute("cleanedUp") != null) {
+ throw new IllegalStateException("Already cleaned up");
+ }
+ request.setAttribute("cleanedUp", Boolean.TRUE);
+ }
+ }
+
+
+ public static class TestApplicationListener implements ApplicationListener {
+
+ public int counter = 0;
+
+ public void onApplicationEvent(ApplicationEvent event) {
+ if (event instanceof PortletRequestHandledEvent) {
+ this.counter++;
+ }
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/DispatcherPortletTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/DispatcherPortletTests.java
new file mode 100644
index 00000000000..8cef7bb6ee0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/DispatcherPortletTests.java
@@ -0,0 +1,989 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.portlet;
+
+import java.io.IOException;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.portlet.PortletContext;
+import javax.portlet.PortletException;
+import javax.portlet.PortletMode;
+import javax.portlet.PortletSecurityException;
+import javax.portlet.PortletSession;
+import javax.portlet.UnavailableException;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.i18n.LocaleContext;
+import org.springframework.context.i18n.LocaleContextHolder;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.mock.web.portlet.MockActionRequest;
+import org.springframework.mock.web.portlet.MockActionResponse;
+import org.springframework.mock.web.portlet.MockPortletConfig;
+import org.springframework.mock.web.portlet.MockPortletContext;
+import org.springframework.mock.web.portlet.MockPortletSession;
+import org.springframework.mock.web.portlet.MockRenderRequest;
+import org.springframework.mock.web.portlet.MockRenderResponse;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import org.springframework.web.context.support.StaticWebApplicationContext;
+import org.springframework.web.multipart.MaxUploadSizeExceededException;
+import org.springframework.web.portlet.context.PortletApplicationContextUtils;
+import org.springframework.web.portlet.context.PortletConfigAwareBean;
+import org.springframework.web.portlet.context.PortletContextAwareBean;
+import org.springframework.web.portlet.handler.PortletSessionRequiredException;
+import org.springframework.web.portlet.multipart.MultipartActionRequest;
+import org.springframework.web.portlet.multipart.PortletMultipartResolver;
+import org.springframework.web.servlet.ViewRendererServlet;
+import org.springframework.web.servlet.view.InternalResourceView;
+
+/**
+ * @author Mark Fisher
+ * @author Juergen Hoeller
+ * @author Dan McCallum
+ */
+public class DispatcherPortletTests extends TestCase {
+
+ private MockPortletConfig simplePortletConfig;
+
+ private MockPortletConfig complexPortletConfig;
+
+ private DispatcherPortlet simpleDispatcherPortlet;
+
+ private DispatcherPortlet complexDispatcherPortlet;
+
+
+ protected void setUp() throws PortletException {
+ simplePortletConfig = new MockPortletConfig(new MockPortletContext(), "simple");
+ complexPortletConfig = new MockPortletConfig(simplePortletConfig.getPortletContext(), "complex");
+ complexPortletConfig.addInitParameter("publishContext", "false");
+
+ simpleDispatcherPortlet = new DispatcherPortlet();
+ simpleDispatcherPortlet.setContextClass(SimplePortletApplicationContext.class);
+ simpleDispatcherPortlet.init(simplePortletConfig);
+
+ complexDispatcherPortlet = new DispatcherPortlet();
+ complexDispatcherPortlet.setContextClass(ComplexPortletApplicationContext.class);
+ complexDispatcherPortlet.setNamespace("test");
+ complexDispatcherPortlet.addRequiredProperty("publishContext");
+ complexDispatcherPortlet.init(complexPortletConfig);
+ }
+
+ private PortletContext getPortletContext() {
+ return complexPortletConfig.getPortletContext();
+ }
+
+
+ public void testDispatcherPortletGetPortletNameDoesNotFailWithoutConfig() {
+ DispatcherPortlet dp = new DispatcherPortlet();
+ assertEquals(null, dp.getPortletConfig());
+ assertEquals(null, dp.getPortletName());
+ assertEquals(null, dp.getPortletContext());
+ }
+
+ public void testDispatcherPortlets() {
+ assertTrue("Correct namespace",
+ ("simple" + FrameworkPortlet.DEFAULT_NAMESPACE_SUFFIX).equals(simpleDispatcherPortlet.getNamespace()));
+ assertTrue("Correct attribute",
+ (FrameworkPortlet.PORTLET_CONTEXT_PREFIX + "simple").equals(simpleDispatcherPortlet.getPortletContextAttributeName()));
+ assertTrue("Context published",
+ simpleDispatcherPortlet.getPortletApplicationContext() ==
+ getPortletContext().getAttribute(FrameworkPortlet.PORTLET_CONTEXT_PREFIX + "simple"));
+
+ assertTrue("Correct namespace", "test".equals(complexDispatcherPortlet.getNamespace()));
+ assertTrue("Correct attribute",
+ (FrameworkPortlet.PORTLET_CONTEXT_PREFIX + "complex").equals(complexDispatcherPortlet.getPortletContextAttributeName()));
+ assertTrue("Context not published",
+ getPortletContext().getAttribute(FrameworkPortlet.PORTLET_CONTEXT_PREFIX + "complex") == null);
+ }
+
+ public void testSimpleValidActionRequest() throws Exception {
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ request.setParameter("action", "form");
+ request.setParameter("age", "29");
+ simpleDispatcherPortlet.processAction(request, response);
+ String exceptionParam = response.getRenderParameter(DispatcherPortlet.ACTION_EXCEPTION_RENDER_PARAMETER);
+ assertNull(exceptionParam);
+ SimplePortletApplicationContext ac = (SimplePortletApplicationContext)simpleDispatcherPortlet.getPortletApplicationContext();
+ String commandAttribute = ac.getRenderCommandSessionAttributeName();
+ TestBean testBean = (TestBean) request.getPortletSession().getAttribute(commandAttribute);
+ assertEquals(39, testBean.getAge());
+ }
+
+ public void testSimpleInvalidActionRequest() throws Exception {
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ request.setParameter("action", "invalid");
+ simpleDispatcherPortlet.processAction(request, response);
+ String exceptionParam = response.getRenderParameter(DispatcherPortlet.ACTION_EXCEPTION_RENDER_PARAMETER);
+ assertNotNull(exceptionParam);
+ assertTrue(exceptionParam.startsWith(UnavailableException.class.getName()));
+ }
+
+ public void testSimpleFormViewNoBindOnNewForm() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setParameter("action", "form");
+ request.setParameter("age", "29");
+ simpleDispatcherPortlet.doDispatch(request, response);
+ assertEquals("5", response.getContentAsString());
+ }
+
+ public void testSimpleFormViewBindOnNewForm() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setParameter("action", "form-bind");
+ request.setParameter("age", "29");
+ simpleDispatcherPortlet.doDispatch(request, response);
+ assertEquals("34", response.getContentAsString());
+ }
+
+ public void testSimpleFormViewWithSessionAndBindOnNewForm() throws Exception {
+ MockRenderRequest renderRequest = new MockRenderRequest();
+ MockRenderResponse renderResponse = new MockRenderResponse();
+ renderRequest.setParameter("action", "form-session-bind");
+ renderRequest.setParameter("age", "30");
+ TestBean testBean = new TestBean();
+ testBean.setAge(40);
+ SimplePortletApplicationContext ac =
+ (SimplePortletApplicationContext)simpleDispatcherPortlet.getPortletApplicationContext();
+ String formAttribute = ac.getFormSessionAttributeName();
+ PortletSession session = new MockPortletSession();
+ session.setAttribute(formAttribute, testBean);
+ renderRequest.setSession(session);
+ simpleDispatcherPortlet.doDispatch(renderRequest, renderResponse);
+ assertEquals("35", renderResponse.getContentAsString());
+ }
+
+ public void testSimpleFormViewWithSessionNoBindOnNewForm() throws Exception {
+ MockActionRequest actionRequest = new MockActionRequest();
+ MockActionResponse actionResponse = new MockActionResponse();
+ actionRequest.setSession(new MockPortletSession());
+ actionRequest.setParameter("action", "form-session-nobind");
+ actionRequest.setParameter("age", "27");
+ simpleDispatcherPortlet.processAction(actionRequest, actionResponse);
+ Map renderParameters = actionResponse.getRenderParameterMap();
+
+ MockRenderRequest renderRequest = new MockRenderRequest();
+ MockRenderResponse renderResponse = new MockRenderResponse();
+ renderRequest.setParameters(renderParameters);
+ renderRequest.setParameter("action", "form-session-nobind");
+ renderRequest.setParameter("age", "30");
+ renderRequest.setSession(actionRequest.getPortletSession());
+ simpleDispatcherPortlet.doDispatch(renderRequest, renderResponse);
+ assertEquals("finished42", renderResponse.getContentAsString());
+ }
+
+ public void testSimpleRequiredSessionFormWithoutSession() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setParameter("action", "form-session-bind");
+ try {
+ simpleDispatcherPortlet.doDispatch(request, response);
+ fail("Should have thrown PortletSessionRequiredException");
+ }
+ catch (PortletSessionRequiredException ex) {
+ // expected
+ }
+ }
+
+ public void testSimpleFormSubmission() throws Exception {
+ MockActionRequest actionRequest = new MockActionRequest();
+ MockActionResponse actionResponse = new MockActionResponse();
+ actionRequest.setParameter("action", "form");
+ actionRequest.setParameter("age", "29");
+ simpleDispatcherPortlet.processAction(actionRequest, actionResponse);
+
+ MockRenderRequest renderRequest = new MockRenderRequest();
+ MockRenderResponse renderResponse = new MockRenderResponse();
+ renderRequest.setSession(actionRequest.getPortletSession());
+ renderRequest.setParameters(actionResponse.getRenderParameterMap());
+ renderRequest.setParameter("action", "form");
+ simpleDispatcherPortlet.doDispatch(renderRequest, renderResponse);
+ assertEquals("finished44", renderResponse.getContentAsString());
+ }
+
+ public void testSimpleFormSubmissionWithValidationError() throws Exception {
+ MockActionRequest actionRequest = new MockActionRequest();
+ MockActionResponse actionResponse = new MockActionResponse();
+ actionRequest.setParameter("action", "form");
+ actionRequest.setParameter("age", "XX");
+ simpleDispatcherPortlet.processAction(actionRequest, actionResponse);
+
+ MockRenderRequest renderRequest = new MockRenderRequest();
+ MockRenderResponse renderResponse = new MockRenderResponse();
+ renderRequest.setSession(actionRequest.getPortletSession());
+ renderRequest.setParameters(actionResponse.getRenderParameterMap());
+ renderRequest.setParameter("action", "form");
+ simpleDispatcherPortlet.doDispatch(renderRequest, renderResponse);
+ assertEquals("5", renderResponse.getContentAsString());
+ }
+
+ public void testSimpleInvalidRenderRequest() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setParameter("action", "invalid");
+ try {
+ simpleDispatcherPortlet.doDispatch(request, response);
+ fail("Should have thrown UnavailableException");
+ }
+ catch (UnavailableException ex) {
+ // expected
+ }
+ }
+
+ public void testPortletModeParameterMappingHelp1() throws Exception {
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ request.setPortletMode(PortletMode.HELP);
+ request.setParameter("action", "help1");
+ complexDispatcherPortlet.processAction(request, response);
+ String param = response.getRenderParameter("param");
+ assertEquals("help1 was here", param);
+ }
+
+ public void testPortletModeParameterMappingHelp2() throws Exception {
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ request.setPortletMode(PortletMode.HELP);
+ request.setParameter("action", "help2");
+ complexDispatcherPortlet.processAction(request, response);
+ String param = response.getRenderParameter("param");
+ assertEquals("help2 was here", param);
+ }
+
+ public void testPortletModeParameterMappingInvalidHelpActionRequest() throws Exception {
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ request.setPortletMode(PortletMode.HELP);
+ request.setParameter("action", "help3");
+ complexDispatcherPortlet.processAction(request, response);
+ String exceptionParam = response.getRenderParameter(DispatcherPortlet.ACTION_EXCEPTION_RENDER_PARAMETER);
+ assertNotNull(exceptionParam);
+ assertTrue(exceptionParam.startsWith(UnavailableException.class.getName()));
+ }
+
+ public void testPortletModeParameterMappingInvalidHelpRenderRequest() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setPortletMode(PortletMode.HELP);
+ request.setParameter("action", "help3");
+ complexDispatcherPortlet.doDispatch(request, response);
+ Map model = (Map) request.getAttribute(ViewRendererServlet.MODEL_ATTRIBUTE);
+ assertTrue(model.get("exception").getClass().equals(UnavailableException.class));
+ InternalResourceView view = (InternalResourceView) request.getAttribute(ViewRendererServlet.VIEW_ATTRIBUTE);
+ assertEquals("failed-unavailable", view.getBeanName());
+ }
+
+ public void testPortletModeMappingValidEditActionRequest() throws Exception {
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ request.setPortletMode(PortletMode.EDIT);
+ request.addUserRole("role1");
+ request.setParameter("action", "not mapped");
+ request.setParameter("myParam", "not mapped");
+ complexDispatcherPortlet.processAction(request, response);
+ assertEquals("edit was here", response.getRenderParameter("param"));
+ }
+
+ public void testPortletModeMappingEditActionRequestWithUnauthorizedUserRole() throws Exception {
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ request.setPortletMode(PortletMode.EDIT);
+ request.addUserRole("role3");
+ request.setParameter("action", "not mapped");
+ request.setParameter("myParam", "not mapped");
+ complexDispatcherPortlet.processAction(request, response);
+ String exception = response.getRenderParameter(DispatcherPortlet.ACTION_EXCEPTION_RENDER_PARAMETER);
+ assertNotNull(exception);
+ String name = PortletSecurityException.class.getName();
+ assertTrue(exception.startsWith(name));
+ }
+
+ public void testPortletModeMappingValidViewRenderRequest() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setPortletMode(PortletMode.VIEW);
+ request.addUserRole("role2");
+ request.setParameter("action", "not mapped");
+ request.setParameter("myParam", "not mapped");
+ complexDispatcherPortlet.doDispatch(request, response);
+ Map model = (Map) request.getAttribute(ViewRendererServlet.MODEL_ATTRIBUTE);
+ assertEquals("view was here", model.get("result"));
+ InternalResourceView view = (InternalResourceView) request.getAttribute(ViewRendererServlet.VIEW_ATTRIBUTE);
+ assertEquals("someViewName", view.getBeanName());
+ }
+
+ public void testPortletModeMappingViewRenderRequestWithUnauthorizedUserRole() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setPortletMode(PortletMode.VIEW);
+ request.addUserRole("role3");
+ request.setParameter("action", "not mapped");
+ request.setParameter("myParam", "not mapped");
+ complexDispatcherPortlet.doDispatch(request, response);
+ Map model = (Map) request.getAttribute(ViewRendererServlet.MODEL_ATTRIBUTE);
+ Exception exception = (Exception) model.get("exception");
+ assertNotNull(exception);
+ assertTrue(exception.getClass().equals(PortletSecurityException.class));
+ InternalResourceView view = (InternalResourceView) request.getAttribute(ViewRendererServlet.VIEW_ATTRIBUTE);
+ assertEquals("failed-default-1", view.getBeanName());
+ }
+
+ public void testParameterMappingValidActionRequest() throws Exception {
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ request.setPortletMode(PortletMode.EDIT);
+ request.setParameter("action", "not mapped");
+ request.setParameter("myParam", "test1");
+ complexDispatcherPortlet.processAction(request, response);
+ assertEquals("test1-action", response.getRenderParameter("result"));
+ }
+
+ public void testParameterMappingValidRenderRequest() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setPortletMode(PortletMode.VIEW);
+ request.setParameter("action", "not mapped");
+ request.setParameter("myParam", "test2");
+ complexDispatcherPortlet.doDispatch(request, response);
+ assertEquals("test2-view", response.getProperty("result"));
+ }
+
+ public void testUnknownHandlerActionRequest() throws Exception {
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ request.setParameter("myParam", "unknown");
+ complexDispatcherPortlet.processAction(request, response);
+ String exceptionParam = response.getRenderParameter(DispatcherPortlet.ACTION_EXCEPTION_RENDER_PARAMETER);
+ assertNotNull(exceptionParam);
+ assertTrue(exceptionParam.startsWith(PortletException.class.getName()));
+ assertTrue(exceptionParam.indexOf("No adapter for handler") != -1);
+ }
+
+ public void testUnknownHandlerRenderRequest() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setParameter("myParam", "unknown");
+ complexDispatcherPortlet.doDispatch(request, response);
+ Map model = (Map) request.getAttribute(ViewRendererServlet.MODEL_ATTRIBUTE);
+ Exception exception = (Exception)model.get("exception");
+ assertTrue(exception.getClass().equals(PortletException.class));
+ assertTrue(exception.getMessage().indexOf("No adapter for handler") != -1);
+ InternalResourceView view = (InternalResourceView) request.getAttribute(ViewRendererServlet.VIEW_ATTRIBUTE);
+ assertEquals("failed-default-1", view.getBeanName());
+ }
+
+ public void testNoDetectAllHandlerMappingsWithPortletModeActionRequest() throws Exception {
+ DispatcherPortlet complexDispatcherPortlet = new DispatcherPortlet();
+ complexDispatcherPortlet.setContextClass(ComplexPortletApplicationContext.class);
+ complexDispatcherPortlet.setNamespace("test");
+ complexDispatcherPortlet.setDetectAllHandlerMappings(false);
+ complexDispatcherPortlet.init(new MockPortletConfig(getPortletContext(), "complex"));
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ request.setPortletMode(PortletMode.EDIT);
+ complexDispatcherPortlet.processAction(request, response);
+ String exceptionParam = response.getRenderParameter(DispatcherPortlet.ACTION_EXCEPTION_RENDER_PARAMETER);
+ assertNotNull(exceptionParam);
+ assertTrue(exceptionParam.startsWith(UnavailableException.class.getName()));
+ }
+
+ public void testNoDetectAllHandlerMappingsWithParameterRenderRequest() throws Exception {
+ DispatcherPortlet complexDispatcherPortlet = new DispatcherPortlet();
+ complexDispatcherPortlet.setContextClass(ComplexPortletApplicationContext.class);
+ complexDispatcherPortlet.setNamespace("test");
+ complexDispatcherPortlet.setDetectAllHandlerMappings(false);
+ complexDispatcherPortlet.init(new MockPortletConfig(getPortletContext(), "complex"));
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setParameter("myParam", "test1");
+ complexDispatcherPortlet.doDispatch(request, response);
+ Map model = (Map) request.getAttribute(ViewRendererServlet.MODEL_ATTRIBUTE);
+ Exception exception = (Exception) model.get("exception");
+ assertTrue(exception.getClass().equals(UnavailableException.class));
+ InternalResourceView view = (InternalResourceView) request.getAttribute(ViewRendererServlet.VIEW_ATTRIBUTE);
+ assertEquals("failed-unavailable", view.getBeanName());
+ }
+
+ public void testExistingMultipartRequest() throws Exception {
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ request.setPortletMode(PortletMode.EDIT);
+ ComplexPortletApplicationContext.MockMultipartResolver multipartResolver =
+ (ComplexPortletApplicationContext.MockMultipartResolver)
+ complexDispatcherPortlet.getPortletApplicationContext().getBean("portletMultipartResolver");
+ MultipartActionRequest multipartRequest = multipartResolver.resolveMultipart(request);
+ complexDispatcherPortlet.processAction(multipartRequest, response);
+ multipartResolver.cleanupMultipart(multipartRequest);
+ assertNotNull(request.getAttribute("cleanedUp"));
+ }
+
+ public void testMultipartResolutionFailed() throws Exception {
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ request.setPortletMode(PortletMode.EDIT);
+ request.addUserRole("role1");
+ request.setAttribute("fail", Boolean.TRUE);
+ complexDispatcherPortlet.processAction(request, response);
+ String exception = response.getRenderParameter(DispatcherPortlet.ACTION_EXCEPTION_RENDER_PARAMETER);
+ assertTrue(exception.startsWith(MaxUploadSizeExceededException.class.getName()));
+ }
+
+ public void testActionRequestHandledEvent() throws Exception {
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ complexDispatcherPortlet.processAction(request, response);
+ ComplexPortletApplicationContext.TestApplicationListener listener =
+ (ComplexPortletApplicationContext.TestApplicationListener)
+ complexDispatcherPortlet.getPortletApplicationContext().getBean("testListener");
+ assertEquals(1, listener.counter);
+ }
+
+ public void testRenderRequestHandledEvent() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ complexDispatcherPortlet.doDispatch(request, response);
+ ComplexPortletApplicationContext.TestApplicationListener listener =
+ (ComplexPortletApplicationContext.TestApplicationListener)
+ complexDispatcherPortlet.getPortletApplicationContext().getBean("testListener");
+ assertEquals(1, listener.counter);
+ }
+
+ public void testPublishEventsOff() throws Exception {
+ complexDispatcherPortlet.setPublishEvents(false);
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ request.setParameter("action", "checker");
+ complexDispatcherPortlet.processAction(request, response);
+ ComplexPortletApplicationContext.TestApplicationListener listener =
+ (ComplexPortletApplicationContext.TestApplicationListener)
+ complexDispatcherPortlet.getPortletApplicationContext().getBean("testListener");
+ assertEquals(0, listener.counter);
+ }
+
+ public void testCorrectLocaleInRequest() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setParameter("myParam", "requestLocaleChecker");
+ request.addPreferredLocale(Locale.CANADA);
+ complexDispatcherPortlet.doDispatch(request, response);
+ assertEquals("locale-ok", response.getContentAsString());
+ }
+
+ public void testIncorrectLocaleInRequest() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setParameter("myParam", "requestLocaleChecker");
+ request.addPreferredLocale(Locale.ENGLISH);
+ complexDispatcherPortlet.doDispatch(request, response);
+ Map model = (Map) request.getAttribute(ViewRendererServlet.MODEL_ATTRIBUTE);
+ Exception exception = (Exception) model.get("exception");
+ assertTrue(exception.getClass().equals(PortletException.class));
+ assertEquals("Incorrect Locale in RenderRequest", exception.getMessage());
+ InternalResourceView view = (InternalResourceView) request.getAttribute(ViewRendererServlet.VIEW_ATTRIBUTE);
+ assertEquals("failed-default-1", view.getBeanName());
+ }
+
+ public void testCorrectLocaleInLocaleContextHolder() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setParameter("myParam", "contextLocaleChecker");
+ request.addPreferredLocale(Locale.CANADA);
+ complexDispatcherPortlet.doDispatch(request, response);
+ assertEquals("locale-ok", response.getContentAsString());
+ }
+
+ public void testIncorrectLocaleInLocalContextHolder() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setParameter("myParam", "contextLocaleChecker");
+ request.addPreferredLocale(Locale.ENGLISH);
+ complexDispatcherPortlet.doDispatch(request, response);
+ Map model = (Map) request.getAttribute(ViewRendererServlet.MODEL_ATTRIBUTE);
+ Exception exception = (Exception) model.get("exception");
+ assertTrue(exception.getClass().equals(PortletException.class));
+ assertEquals("Incorrect Locale in LocaleContextHolder", exception.getMessage());
+ InternalResourceView view = (InternalResourceView) request.getAttribute(ViewRendererServlet.VIEW_ATTRIBUTE);
+ assertEquals("failed-default-1", view.getBeanName());
+ }
+
+ public void testHandlerInterceptorNoAbort() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setPortletMode(PortletMode.VIEW);
+ request.addUserRole("role1");
+ request.addParameter("abort", "false");
+ complexDispatcherPortlet.doDispatch(request, response);
+ assertTrue(request.getAttribute("test1-remove-never") != null);
+ assertTrue(request.getAttribute("test1-remove-post") == null);
+ assertTrue(request.getAttribute("test1-remove-after") == null);
+ assertTrue(request.getAttribute("test2-remove-never") != null);
+ assertTrue(request.getAttribute("test2-remove-post") == null);
+ assertTrue(request.getAttribute("test2-remove-after") == null);
+ }
+
+ public void testHandlerInterceptorAbort() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setPortletMode(PortletMode.VIEW);
+ request.addUserRole("role1");
+ request.addParameter("abort", "true");
+ complexDispatcherPortlet.doDispatch(request, response);
+ assertTrue(request.getAttribute("test1-remove-never") != null);
+ assertTrue(request.getAttribute("test1-remove-post") != null);
+ assertTrue(request.getAttribute("test1-remove-after") == null);
+ assertTrue(request.getAttribute("test2-remove-never") == null);
+ assertTrue(request.getAttribute("test2-remove-post") == null);
+ assertTrue(request.getAttribute("test2-remove-after") == null);
+ }
+
+ public void testHandlerInterceptorNotClearingModelAndView() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setPortletMode(PortletMode.VIEW);
+ request.addUserRole("role1");
+ request.addParameter("noView", "false");
+ complexDispatcherPortlet.doDispatch(request, response);
+ Map model = (Map) request.getAttribute(ViewRendererServlet.MODEL_ATTRIBUTE);
+ assertEquals("view was here", model.get("result"));
+ InternalResourceView view = (InternalResourceView) request.getAttribute(ViewRendererServlet.VIEW_ATTRIBUTE);
+ assertEquals("someViewName", view.getBeanName());
+ }
+
+ public void testHandlerInterceptorClearingModelAndView() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setPortletMode(PortletMode.VIEW);
+ request.addUserRole("role1");
+ request.addParameter("noView", "true");
+ complexDispatcherPortlet.doDispatch(request, response);
+ Map model = (Map) request.getAttribute(ViewRendererServlet.MODEL_ATTRIBUTE);
+ assertNull(model);
+ InternalResourceView view = (InternalResourceView) request.getAttribute(ViewRendererServlet.VIEW_ATTRIBUTE);
+ assertNull(view);
+ }
+
+ public void testParameterMappingInterceptorWithCorrectParam() throws Exception {
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ request.setPortletMode(PortletMode.VIEW);
+ request.addUserRole("role1");
+ request.addParameter("interceptingParam", "test1");
+ complexDispatcherPortlet.processAction(request, response);
+ assertEquals("test1", response.getRenderParameter("interceptingParam"));
+ }
+
+ public void testParameterMappingInterceptorWithIncorrectParam() throws Exception {
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ request.setPortletMode(PortletMode.VIEW);
+ request.addUserRole("role1");
+ request.addParameter("incorrect", "test1");
+ complexDispatcherPortlet.processAction(request, response);
+ assertNull(response.getRenderParameter("incorrect"));
+ assertNull(response.getRenderParameter("interceptingParam"));
+ }
+
+ public void testPortletHandlerAdapterActionRequest() throws Exception {
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ request.setParameter("myParam", "myPortlet");
+ complexDispatcherPortlet.processAction(request, response);
+ assertEquals("myPortlet action called", response.getRenderParameter("result"));
+ ComplexPortletApplicationContext.MyPortlet myPortlet =
+ (ComplexPortletApplicationContext.MyPortlet) complexDispatcherPortlet.getPortletApplicationContext().getBean("myPortlet");
+ assertEquals("complex", myPortlet.getPortletConfig().getPortletName());
+ assertEquals(getPortletContext(), myPortlet.getPortletConfig().getPortletContext());
+ assertEquals(complexDispatcherPortlet.getPortletContext(), myPortlet.getPortletConfig().getPortletContext());
+ complexDispatcherPortlet.destroy();
+ assertNull(myPortlet.getPortletConfig());
+ }
+
+ public void testPortletHandlerAdapterRenderRequest() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setParameter("myParam", "myPortlet");
+ complexDispatcherPortlet.doDispatch(request, response);
+ assertEquals("myPortlet was here", response.getContentAsString());
+ ComplexPortletApplicationContext.MyPortlet myPortlet =
+ (ComplexPortletApplicationContext.MyPortlet)
+ complexDispatcherPortlet.getPortletApplicationContext().getBean("myPortlet");
+ assertEquals("complex", myPortlet.getPortletConfig().getPortletName());
+ assertEquals(getPortletContext(), myPortlet.getPortletConfig().getPortletContext());
+ assertEquals(complexDispatcherPortlet.getPortletContext(),
+ myPortlet.getPortletConfig().getPortletContext());
+ complexDispatcherPortlet.destroy();
+ assertNull(myPortlet.getPortletConfig());
+ }
+
+ public void testModelAndViewDefiningExceptionInMappedHandler() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ request.setPortletMode(PortletMode.HELP);
+ request.addParameter("myParam", "exception1");
+ request.addParameter("fail", "yes");
+ MockRenderResponse response = new MockRenderResponse();
+ complexDispatcherPortlet.doDispatch(request, response);
+ InternalResourceView view = (InternalResourceView) request.getAttribute(ViewRendererServlet.VIEW_ATTRIBUTE);
+ assertEquals("failed-modelandview", view.getBeanName());
+ }
+
+ public void testModelAndViewDefiningExceptionInUnmappedHandler() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ request.setPortletMode(PortletMode.HELP);
+ request.addParameter("myParam", "exception2");
+ request.addParameter("fail", "yes");
+ MockRenderResponse response = new MockRenderResponse();
+ complexDispatcherPortlet.doDispatch(request, response);
+ InternalResourceView view = (InternalResourceView) request.getAttribute(ViewRendererServlet.VIEW_ATTRIBUTE);
+ assertEquals("failed-modelandview", view.getBeanName());
+ }
+
+ public void testIllegalAccessExceptionInMappedHandler() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ request.setPortletMode(PortletMode.HELP);
+ request.addParameter("myParam", "exception1");
+ request.addParameter("access", "illegal");
+ MockRenderResponse response = new MockRenderResponse();
+ complexDispatcherPortlet.doDispatch(request, response);
+ InternalResourceView view = (InternalResourceView) request.getAttribute(ViewRendererServlet.VIEW_ATTRIBUTE);
+ assertEquals("failed-exception", view.getBeanName());
+ }
+
+ public void testIllegalAccessExceptionInUnmappedHandler() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ request.setPortletMode(PortletMode.HELP);
+ request.addParameter("myParam", "exception2");
+ request.addParameter("access", "illegal");
+ MockRenderResponse response = new MockRenderResponse();
+ complexDispatcherPortlet.doDispatch(request, response);
+ InternalResourceView view = (InternalResourceView) request.getAttribute(ViewRendererServlet.VIEW_ATTRIBUTE);
+ assertEquals("failed-illegalaccess", view.getBeanName());
+ }
+
+ public void testPortletRequestBindingExceptionInMappedHandler() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ request.setPortletMode(PortletMode.HELP);
+ request.addParameter("myParam", "exception1");
+ request.addParameter("binding", "should fail");
+ MockRenderResponse response = new MockRenderResponse();
+ complexDispatcherPortlet.doDispatch(request, response);
+ InternalResourceView view = (InternalResourceView) request.getAttribute(ViewRendererServlet.VIEW_ATTRIBUTE);
+ assertEquals("failed-exception", view.getBeanName());
+ }
+
+ public void testPortletRequestBindingExceptionInUnmappedHandler() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ request.setPortletMode(PortletMode.HELP);
+ request.addParameter("myParam", "exception2");
+ request.addParameter("binding", "should fail");
+ MockRenderResponse response = new MockRenderResponse();
+ complexDispatcherPortlet.doDispatch(request, response);
+ InternalResourceView view = (InternalResourceView) request.getAttribute(ViewRendererServlet.VIEW_ATTRIBUTE);
+ assertEquals("failed-binding", view.getBeanName());
+ }
+
+ public void testIllegalArgumentExceptionInMappedHandler() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ request.setPortletMode(PortletMode.HELP);
+ request.addParameter("myParam", "exception1");
+ request.addParameter("unknown", "");
+ MockRenderResponse response = new MockRenderResponse();
+ complexDispatcherPortlet.doDispatch(request, response);
+ InternalResourceView view = (InternalResourceView) request.getAttribute(ViewRendererServlet.VIEW_ATTRIBUTE);
+ assertEquals("failed-runtime", view.getBeanName());
+ }
+
+ public void testIllegalArgumentExceptionInUnmappedHandler() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ request.setPortletMode(PortletMode.HELP);
+ request.addParameter("myParam", "exception2");
+ request.addParameter("unknown", "");
+ MockRenderResponse response = new MockRenderResponse();
+ complexDispatcherPortlet.doDispatch(request, response);
+ InternalResourceView view = (InternalResourceView) request.getAttribute(ViewRendererServlet.VIEW_ATTRIBUTE);
+ assertEquals("failed-default-1", view.getBeanName());
+ }
+
+ public void testExceptionInMappedHandler() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ request.setPortletMode(PortletMode.HELP);
+ request.addParameter("myParam", "exception1");
+ request.addParameter("generic", "123");
+ MockRenderResponse response = new MockRenderResponse();
+ complexDispatcherPortlet.doDispatch(request, response);
+ InternalResourceView view = (InternalResourceView) request.getAttribute(ViewRendererServlet.VIEW_ATTRIBUTE);
+ assertEquals("failed-exception", view.getBeanName());
+ }
+
+ public void testExceptionInUnmappedHandler() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ request.setPortletMode(PortletMode.HELP);
+ request.addParameter("myParam", "exception2");
+ request.addParameter("generic", "123");
+ MockRenderResponse response = new MockRenderResponse();
+ complexDispatcherPortlet.doDispatch(request, response);
+ InternalResourceView view = (InternalResourceView) request.getAttribute(ViewRendererServlet.VIEW_ATTRIBUTE);
+ assertEquals("failed-default-1", view.getBeanName());
+ }
+
+ public void testRuntimeExceptionInMappedHandler() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ request.setPortletMode(PortletMode.HELP);
+ request.addParameter("myParam", "exception1");
+ request.addParameter("runtime", "true");
+ MockRenderResponse response = new MockRenderResponse();
+ complexDispatcherPortlet.doDispatch(request, response);
+ InternalResourceView view = (InternalResourceView) request.getAttribute(ViewRendererServlet.VIEW_ATTRIBUTE);
+ assertEquals("failed-runtime", view.getBeanName());
+ }
+
+ public void testRuntimeExceptionInUnmappedHandler() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ request.setPortletMode(PortletMode.HELP);
+ request.addParameter("myParam", "exception2");
+ request.addParameter("runtime", "true");
+ MockRenderResponse response = new MockRenderResponse();
+ complexDispatcherPortlet.doDispatch(request, response);
+ InternalResourceView view = (InternalResourceView) request.getAttribute(ViewRendererServlet.VIEW_ATTRIBUTE);
+ assertEquals("failed-default-1", view.getBeanName());
+ }
+
+ public void testGetMessage() {
+ String message = complexDispatcherPortlet.getPortletApplicationContext().getMessage("test", null, Locale.ENGLISH);
+ assertEquals("test message", message);
+ }
+
+ public void testGetMessageOtherLocale() {
+ String message = complexDispatcherPortlet.getPortletApplicationContext().getMessage("test", null, Locale.CANADA);
+ assertEquals("Canadian & test message", message);
+ }
+
+ public void testGetMessageWithArgs() {
+ Object[] args = new String[] {"this", "that"};
+ String message = complexDispatcherPortlet.getPortletApplicationContext().getMessage("test.args", args, Locale.ENGLISH);
+ assertEquals("test this and that", message);
+ }
+
+ public void testPortletApplicationContextLookup() {
+ MockPortletContext portletContext = new MockPortletContext();
+ ApplicationContext ac = PortletApplicationContextUtils.getWebApplicationContext(portletContext);
+ assertNull(ac);
+ try {
+ ac = PortletApplicationContextUtils.getRequiredWebApplicationContext(portletContext);
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ portletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,
+ new StaticWebApplicationContext());
+ try {
+ ac = PortletApplicationContextUtils.getRequiredWebApplicationContext(portletContext);
+ assertNotNull(ac);
+ }
+ catch (IllegalStateException ex) {
+ fail("Should not have thrown IllegalStateException: " + ex.getMessage());
+ }
+ }
+
+ public void testValidActionRequestWithExistingThreadLocalRequestContext() throws IOException, PortletException {
+ MockServletContext servletContext = new MockServletContext();
+ MockHttpServletRequest httpRequest = new MockHttpServletRequest(servletContext);
+ httpRequest.addPreferredLocale(Locale.GERMAN);
+
+ // see RequestContextListener.requestInitialized()
+ try {
+ LocaleContextHolder.setLocale(httpRequest.getLocale());
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpRequest));
+
+ LocaleContext servletLocaleContext = LocaleContextHolder.getLocaleContext();
+ RequestAttributes servletRequestAttrs = RequestContextHolder.getRequestAttributes();
+
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ request.setParameter("action", "form");
+ request.setParameter("age", "29");
+ simpleDispatcherPortlet.processAction(request, response);
+
+ assertSame(servletLocaleContext, LocaleContextHolder.getLocaleContext());
+ assertSame(servletRequestAttrs, RequestContextHolder.getRequestAttributes());
+ }
+ finally {
+ RequestContextHolder.resetRequestAttributes();
+ LocaleContextHolder.resetLocaleContext();
+ }
+ }
+
+ public void testValidRenderRequestWithExistingThreadLocalRequestContext() throws IOException, PortletException {
+ MockServletContext servletContext = new MockServletContext();
+ MockHttpServletRequest httpRequest = new MockHttpServletRequest(servletContext);
+ httpRequest.addPreferredLocale(Locale.GERMAN);
+
+ // see RequestContextListener.requestInitialized()
+ try {
+ LocaleContextHolder.setLocale(httpRequest.getLocale());
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpRequest));
+
+ LocaleContext servletLocaleContext = LocaleContextHolder.getLocaleContext();
+ RequestAttributes servletRequestAttrs = RequestContextHolder.getRequestAttributes();
+
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setParameter("action", "form");
+ request.setParameter("age", "29");
+ simpleDispatcherPortlet.doDispatch(request, response);
+
+ assertSame(servletLocaleContext, LocaleContextHolder.getLocaleContext());
+ assertSame(servletRequestAttrs, RequestContextHolder.getRequestAttributes());
+ }
+ finally {
+ RequestContextHolder.resetRequestAttributes();
+ LocaleContextHolder.resetLocaleContext();
+ }
+ }
+
+ public void testInvalidActionRequestWithExistingThreadLocalRequestContext() throws IOException, PortletException {
+ MockServletContext servletContext = new MockServletContext();
+ MockHttpServletRequest httpRequest = new MockHttpServletRequest(servletContext);
+ httpRequest.addPreferredLocale(Locale.GERMAN);
+
+ // see RequestContextListener.requestInitialized()
+ try {
+ LocaleContextHolder.setLocale(httpRequest.getLocale());
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpRequest));
+
+ LocaleContext servletLocaleContext = LocaleContextHolder.getLocaleContext();
+ RequestAttributes servletRequestAttrs = RequestContextHolder.getRequestAttributes();
+
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ request.setParameter("action", "invalid");
+ simpleDispatcherPortlet.processAction(request, response);
+ String exceptionParam = response.getRenderParameter(DispatcherPortlet.ACTION_EXCEPTION_RENDER_PARAMETER);
+ assertNotNull(exceptionParam); // ensure that an exceptional condition occured
+
+ assertSame(servletLocaleContext, LocaleContextHolder.getLocaleContext());
+ assertSame(servletRequestAttrs, RequestContextHolder.getRequestAttributes());
+ }
+ finally {
+ RequestContextHolder.resetRequestAttributes();
+ LocaleContextHolder.resetLocaleContext();
+ }
+ }
+
+ public void testInvalidRenderRequestWithExistingThreadLocalRequestContext() throws IOException, PortletException {
+ MockServletContext servletContext = new MockServletContext();
+ MockHttpServletRequest httpRequest = new MockHttpServletRequest(servletContext);
+ httpRequest.addPreferredLocale(Locale.GERMAN);
+
+ // see RequestContextListener.requestInitialized()
+ try {
+ LocaleContextHolder.setLocale(httpRequest.getLocale());
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpRequest));
+
+ LocaleContext servletLocaleContext = LocaleContextHolder.getLocaleContext();
+ RequestAttributes servletRequestAttrs = RequestContextHolder.getRequestAttributes();
+
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ try {
+ simpleDispatcherPortlet.doDispatch(request, response);
+ fail("should have failed to find a handler and raised an UnavailableException");
+ }
+ catch (UnavailableException ex) {
+ // expected
+ }
+
+ assertSame(servletLocaleContext, LocaleContextHolder.getLocaleContext());
+ assertSame(servletRequestAttrs, RequestContextHolder.getRequestAttributes());
+ }
+ finally {
+ RequestContextHolder.resetRequestAttributes();
+ LocaleContextHolder.resetLocaleContext();
+ }
+ }
+
+ public void testDispatcherPortletRefresh() throws PortletException {
+ MockPortletContext portletContext = new MockPortletContext("org/springframework/web/portlet/context");
+ DispatcherPortlet portlet = new DispatcherPortlet();
+
+ portlet.init(new MockPortletConfig(portletContext, "empty"));
+ PortletContextAwareBean contextBean = (PortletContextAwareBean)
+ portlet.getPortletApplicationContext().getBean("portletContextAwareBean");
+ PortletConfigAwareBean configBean = (PortletConfigAwareBean)
+ portlet.getPortletApplicationContext().getBean("portletConfigAwareBean");
+ assertSame(portletContext, contextBean.getPortletContext());
+ assertSame(portlet.getPortletConfig(), configBean.getPortletConfig());
+ PortletMultipartResolver multipartResolver = portlet.getMultipartResolver();
+ assertNotNull(multipartResolver);
+
+ portlet.refresh();
+
+ PortletContextAwareBean contextBean2 = (PortletContextAwareBean)
+ portlet.getPortletApplicationContext().getBean("portletContextAwareBean");
+ PortletConfigAwareBean configBean2 = (PortletConfigAwareBean)
+ portlet.getPortletApplicationContext().getBean("portletConfigAwareBean");
+ assertSame(portletContext, contextBean.getPortletContext());
+ assertSame(portlet.getPortletConfig(), configBean.getPortletConfig());
+ assertTrue(contextBean != contextBean2);
+ assertTrue(configBean != configBean2);
+ PortletMultipartResolver multipartResolver2 = portlet.getMultipartResolver();
+ assertTrue(multipartResolver != multipartResolver2);
+
+ portlet.destroy();
+ }
+
+ public void testDispatcherPortletContextRefresh() throws PortletException {
+ MockPortletContext portletContext = new MockPortletContext("org/springframework/web/portlet/context");
+ DispatcherPortlet portlet = new DispatcherPortlet();
+
+ portlet.init(new MockPortletConfig(portletContext, "empty"));
+ PortletContextAwareBean contextBean = (PortletContextAwareBean)
+ portlet.getPortletApplicationContext().getBean("portletContextAwareBean");
+ PortletConfigAwareBean configBean = (PortletConfigAwareBean)
+ portlet.getPortletApplicationContext().getBean("portletConfigAwareBean");
+ assertSame(portletContext, contextBean.getPortletContext());
+ assertSame(portlet.getPortletConfig(), configBean.getPortletConfig());
+ PortletMultipartResolver multipartResolver = portlet.getMultipartResolver();
+ assertNotNull(multipartResolver);
+
+ ((ConfigurableApplicationContext) portlet.getPortletApplicationContext()).refresh();
+
+ PortletContextAwareBean contextBean2 = (PortletContextAwareBean)
+ portlet.getPortletApplicationContext().getBean("portletContextAwareBean");
+ PortletConfigAwareBean configBean2 = (PortletConfigAwareBean)
+ portlet.getPortletApplicationContext().getBean("portletConfigAwareBean");
+ assertSame(portletContext, contextBean.getPortletContext());
+ assertSame(portlet.getPortletConfig(), configBean.getPortletConfig());
+ assertTrue(contextBean != contextBean2);
+ assertTrue(configBean != configBean2);
+ PortletMultipartResolver multipartResolver2 = portlet.getMultipartResolver();
+ assertTrue(multipartResolver != multipartResolver2);
+
+ portlet.destroy();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/GenericPortletBeanTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/GenericPortletBeanTests.java
new file mode 100644
index 00000000000..dd6f8006c01
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/GenericPortletBeanTests.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.portlet;
+
+import javax.portlet.PortletContext;
+import javax.portlet.PortletException;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.portlet.MockPortletConfig;
+import org.springframework.mock.web.portlet.MockPortletContext;
+
+/**
+ * @author Mark Fisher
+ */
+public class GenericPortletBeanTests extends TestCase {
+
+ public void testInitParameterSet() throws Exception {
+ PortletContext portletContext = new MockPortletContext();
+ MockPortletConfig portletConfig = new MockPortletConfig(portletContext);
+ String testValue = "testValue";
+ portletConfig.addInitParameter("testParam", testValue);
+ TestPortletBean portletBean = new TestPortletBean();
+ assertNull(portletBean.getTestParam());
+ portletBean.init(portletConfig);
+ assertNotNull(portletBean.getTestParam());
+ assertEquals(testValue, portletBean.getTestParam());
+ }
+
+ public void testInitParameterNotSet() throws Exception {
+ PortletContext portletContext = new MockPortletContext();
+ MockPortletConfig portletConfig = new MockPortletConfig(portletContext);
+ TestPortletBean portletBean = new TestPortletBean();
+ assertNull(portletBean.getTestParam());
+ portletBean.init(portletConfig);
+ assertNull(portletBean.getTestParam());
+ }
+
+ public void testMultipleInitParametersSet() throws Exception {
+ PortletContext portletContext = new MockPortletContext();
+ MockPortletConfig portletConfig = new MockPortletConfig(portletContext);
+ String testValue = "testValue";
+ String anotherValue = "anotherValue";
+ portletConfig.addInitParameter("testParam", testValue);
+ portletConfig.addInitParameter("anotherParam", anotherValue);
+ portletConfig.addInitParameter("unknownParam", "unknownValue");
+ TestPortletBean portletBean = new TestPortletBean();
+ assertNull(portletBean.getTestParam());
+ assertNull(portletBean.getAnotherParam());
+ portletBean.init(portletConfig);
+ assertNotNull(portletBean.getTestParam());
+ assertNotNull(portletBean.getAnotherParam());
+ assertEquals(testValue, portletBean.getTestParam());
+ assertEquals(anotherValue, portletBean.getAnotherParam());
+ }
+
+ public void testMultipleInitParametersOnlyOneSet() throws Exception {
+ PortletContext portletContext = new MockPortletContext();
+ MockPortletConfig portletConfig = new MockPortletConfig(portletContext);
+ String testValue = "testValue";
+ portletConfig.addInitParameter("testParam", testValue);
+ portletConfig.addInitParameter("unknownParam", "unknownValue");
+ TestPortletBean portletBean = new TestPortletBean();
+ assertNull(portletBean.getTestParam());
+ assertNull(portletBean.getAnotherParam());
+ portletBean.init(portletConfig);
+ assertNotNull(portletBean.getTestParam());
+ assertEquals(testValue, portletBean.getTestParam());
+ assertNull(portletBean.getAnotherParam());
+ }
+
+ public void testRequiredInitParameterSet() throws Exception {
+ PortletContext portletContext = new MockPortletContext();
+ MockPortletConfig portletConfig = new MockPortletConfig(portletContext);
+ String testParam = "testParam";
+ String testValue = "testValue";
+ portletConfig.addInitParameter(testParam, testValue);
+ TestPortletBean portletBean = new TestPortletBean();
+ portletBean.addRequiredProperty(testParam);
+ assertNull(portletBean.getTestParam());
+ portletBean.init(portletConfig);
+ assertNotNull(portletBean.getTestParam());
+ assertEquals(testValue, portletBean.getTestParam());
+ }
+
+ public void testRequiredInitParameterNotSet() throws Exception {
+ PortletContext portletContext = new MockPortletContext();
+ MockPortletConfig portletConfig = new MockPortletConfig(portletContext);
+ String testParam = "testParam";
+ TestPortletBean portletBean = new TestPortletBean();
+ portletBean.addRequiredProperty(testParam);
+ assertNull(portletBean.getTestParam());
+ try {
+ portletBean.init(portletConfig);
+ fail("should have thrown PortletException");
+ }
+ catch (PortletException ex) {
+ // expected
+ }
+ }
+
+ public void testRequiredInitParameterNotSetOtherParameterNotSet() throws Exception {
+ PortletContext portletContext = new MockPortletContext();
+ MockPortletConfig portletConfig = new MockPortletConfig(portletContext);
+ String testParam = "testParam";
+ String testValue = "testValue";
+ portletConfig.addInitParameter(testParam, testValue);
+ TestPortletBean portletBean = new TestPortletBean();
+ portletBean.addRequiredProperty("anotherParam");
+ assertNull(portletBean.getTestParam());
+ try {
+ portletBean.init(portletConfig);
+ fail("should have thrown PortletException");
+ }
+ catch (PortletException ex) {
+ // expected
+ }
+ assertNull(portletBean.getTestParam());
+ }
+
+ public void testUnknownRequiredInitParameter() throws Exception {
+ PortletContext portletContext = new MockPortletContext();
+ MockPortletConfig portletConfig = new MockPortletConfig(portletContext);
+ String testParam = "testParam";
+ String testValue = "testValue";
+ portletConfig.addInitParameter(testParam, testValue);
+ TestPortletBean portletBean = new TestPortletBean();
+ portletBean.addRequiredProperty("unknownParam");
+ assertNull(portletBean.getTestParam());
+ try {
+ portletBean.init(portletConfig);
+ fail("should have thrown PortletException");
+ }
+ catch (PortletException ex) {
+ // expected
+ }
+ assertNull(portletBean.getTestParam());
+ }
+
+
+ private static class TestPortletBean extends GenericPortletBean {
+
+ private String testParam;
+ private String anotherParam;
+
+ public void setTestParam(String value) {
+ this.testParam = value;
+ }
+
+ public String getTestParam() {
+ return this.testParam;
+ }
+
+ public void setAnotherParam(String value) {
+ this.anotherParam = value;
+ }
+
+ public String getAnotherParam() {
+ return this.anotherParam;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/SimplePortletApplicationContext.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/SimplePortletApplicationContext.java
new file mode 100644
index 00000000000..98039953d88
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/SimplePortletApplicationContext.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.portlet;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.PropertyValue;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
+import org.springframework.beans.factory.support.ManagedMap;
+import org.springframework.validation.BindException;
+import org.springframework.web.portlet.context.StaticPortletApplicationContext;
+import org.springframework.web.portlet.handler.ParameterHandlerMapping;
+import org.springframework.web.portlet.mvc.SimpleFormController;
+
+/**
+ * @author Mark Fisher
+ */
+public class SimplePortletApplicationContext extends StaticPortletApplicationContext {
+
+ private String renderCommandSessionAttributeName;
+ private String formSessionAttributeName;
+
+ public void refresh() throws BeansException {
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ registerSingleton("controller1", TestFormController.class, pvs);
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("bindOnNewForm", "true");
+ registerSingleton("controller2", TestFormController.class, pvs);
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("requireSession", "true");
+ pvs.addPropertyValue("sessionForm", "true");
+ pvs.addPropertyValue("bindOnNewForm", "true");
+ registerSingleton("controller3", TestFormController.class, pvs);
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("requireSession", "true");
+ pvs.addPropertyValue("sessionForm", "true");
+ pvs.addPropertyValue("bindOnNewForm", "false");
+ registerSingleton("controller4", TestFormController.class, pvs);
+
+ pvs = new MutablePropertyValues();
+ Map parameterMap = new ManagedMap();
+ parameterMap.put("form", new RuntimeBeanReference("controller1"));
+ parameterMap.put("form-bind", new RuntimeBeanReference("controller2"));
+ parameterMap.put("form-session-bind", new RuntimeBeanReference("controller3"));
+ parameterMap.put("form-session-nobind", new RuntimeBeanReference("controller4"));
+ pvs.addPropertyValue(new PropertyValue("parameterMap", parameterMap));
+ registerSingleton("handlerMapping", ParameterHandlerMapping.class, pvs);
+
+ super.refresh();
+
+ TestFormController controller1 = (TestFormController) getBean("controller1");
+ this.renderCommandSessionAttributeName = controller1.getRenderCommandName();
+ this.formSessionAttributeName = controller1.getFormSessionName();
+ }
+
+ public String getRenderCommandSessionAttributeName() {
+ return this.renderCommandSessionAttributeName;
+ }
+
+ public String getFormSessionAttributeName() {
+ return this.formSessionAttributeName;
+ }
+
+
+ public static class TestFormController extends SimpleFormController {
+
+ TestFormController() {
+ super();
+ this.setCommandClass(TestBean.class);
+ this.setCommandName("testBean");
+ this.setFormView("form");
+ }
+
+ public void doSubmitAction(Object command) {
+ TestBean testBean = (TestBean) command;
+ testBean.setAge(testBean.getAge() + 10);
+ }
+
+ public ModelAndView showForm(RenderRequest request, RenderResponse response, BindException errors) throws Exception {
+ TestBean testBean = (TestBean) errors.getModel().get(getCommandName());
+ this.writeResponse(response, testBean, false);
+ return null;
+ }
+
+ public ModelAndView onSubmitRender(RenderRequest request, RenderResponse response, Object command, BindException errors)
+ throws IOException {
+ TestBean testBean = (TestBean) command;
+ this.writeResponse(response, testBean, true);
+ return null;
+ }
+
+ private String getRenderCommandName() {
+ return this.getRenderCommandSessionAttributeName();
+ }
+
+ private String getFormSessionName() {
+ return this.getFormSessionAttributeName();
+ }
+
+ private void writeResponse(RenderResponse response, TestBean testBean, boolean finished) throws IOException {
+ response.getWriter().write((finished ? "finished" : "") + (testBean.getAge() + 5));
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/bind/PortletRequestDataBinderTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/bind/PortletRequestDataBinderTests.java
new file mode 100644
index 00000000000..da9b841c1b0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/bind/PortletRequestDataBinderTests.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.portlet.bind;
+
+import java.beans.PropertyEditorSupport;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.propertyeditors.CustomDateEditor;
+import org.springframework.beans.propertyeditors.StringArrayPropertyEditor;
+import org.springframework.core.CollectionFactory;
+import org.springframework.mock.web.portlet.MockPortletRequest;
+import org.springframework.validation.BindingResult;
+
+/**
+ * @author Mark Fisher
+ */
+public class PortletRequestDataBinderTests extends TestCase {
+
+ public void testSimpleBind() {
+ TestBean bean = new TestBean();
+
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("age", "35");
+ request.addParameter("name", "test");
+
+ PortletRequestDataBinder binder = new PortletRequestDataBinder(bean);
+ binder.bind(request);
+
+ assertEquals(35, bean.getAge());
+ assertEquals("test", bean.getName());
+ }
+
+ public void testNestedBind() {
+ TestBean bean = new TestBean();
+ bean.setSpouse(new TestBean());
+
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("spouse.name", "test");
+
+ PortletRequestDataBinder binder = new PortletRequestDataBinder(bean);
+ binder.bind(request);
+
+ assertNotNull(bean.getSpouse());
+ assertEquals("test", bean.getSpouse().getName());
+ }
+
+ public void testNestedBindWithPropertyEditor() {
+ TestBean bean = new TestBean();
+
+ PortletRequestDataBinder binder = new PortletRequestDataBinder(bean);
+ binder.registerCustomEditor(ITestBean.class, new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue(new TestBean(text));
+ }
+ });
+
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("spouse", "test");
+ request.addParameter("spouse.age", "32");
+ binder.bind(request);
+
+ assertNotNull(bean.getSpouse());
+ assertEquals("test", bean.getSpouse().getName());
+ assertEquals(32, bean.getSpouse().getAge());
+ }
+
+ public void testBindingMismatch() {
+ TestBean bean = new TestBean();
+ bean.setAge(30);
+
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("age", "zzz");
+
+ PortletRequestDataBinder binder = new PortletRequestDataBinder(bean);
+ binder.bind(request);
+
+ BindingResult error = binder.getBindingResult();
+ assertNotNull(error.getFieldError("age"));
+ assertEquals("typeMismatch", error.getFieldError("age").getCode());
+ assertEquals(30, bean.getAge());
+ }
+
+ public void testBindingStringWithCommaSeparatedValue() throws Exception {
+ TestBean bean = new TestBean();
+
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("stringArray", "test1,test2");
+
+ PortletRequestDataBinder binder = new PortletRequestDataBinder(bean);
+ binder.bind(request);
+
+ assertNotNull(bean.getStringArray());
+ assertEquals(1, bean.getStringArray().length);
+ assertEquals("test1,test2", bean.getStringArray()[0]);
+ }
+
+ public void testBindingStringArrayWithSplitting() {
+ TestBean bean = new TestBean();
+
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("stringArray", "test1,test2");
+
+ PortletRequestDataBinder binder = new PortletRequestDataBinder(bean);
+ binder.registerCustomEditor(String[].class, new StringArrayPropertyEditor());
+ binder.bind(request);
+
+ assertNotNull(bean.getStringArray());
+ assertEquals(2, bean.getStringArray().length);
+ assertEquals("test1", bean.getStringArray()[0]);
+ assertEquals("test2", bean.getStringArray()[1]);
+ }
+
+ public void testBindingList() {
+ TestBean bean = new TestBean();
+
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("someList[0]", "test1");
+ request.addParameter("someList[1]", "test2");
+
+ PortletRequestDataBinder binder = new PortletRequestDataBinder(bean);
+ binder.bind(request);
+
+ assertNotNull(bean.getSomeList());
+ assertEquals(2, bean.getSomeList().size());
+ assertEquals("test1", bean.getSomeList().get(0));
+ assertEquals("test2", bean.getSomeList().get(1));
+ }
+
+ public void testBindingMap() {
+ TestBean bean = new TestBean();
+
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("someMap['key1']", "val1");
+ request.addParameter("someMap['key2']", "val2");
+
+ PortletRequestDataBinder binder = new PortletRequestDataBinder(bean);
+ binder.bind(request);
+
+ assertNotNull(bean.getSomeMap());
+ assertEquals(2, bean.getSomeMap().size());
+ assertEquals("val1", bean.getSomeMap().get("key1"));
+ assertEquals("val2", bean.getSomeMap().get("key2"));
+ }
+
+ public void testBindingSet() {
+ TestBean bean = new TestBean();
+ Set set = CollectionFactory.createLinkedSetIfPossible(2);
+ set.add(new TestBean("test1"));
+ set.add(new TestBean("test2"));
+ bean.setSomeSet(set);
+
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("someSet[0].age", "35");
+ request.addParameter("someSet[1].age", "36");
+
+ PortletRequestDataBinder binder = new PortletRequestDataBinder(bean);
+ binder.bind(request);
+
+ assertNotNull(bean.getSomeSet());
+ assertEquals(2, bean.getSomeSet().size());
+
+ Iterator iter = bean.getSomeSet().iterator();
+
+ TestBean bean1 = (TestBean) iter.next();
+ assertEquals("test1", bean1.getName());
+ assertEquals(35, bean1.getAge());
+
+ TestBean bean2 = (TestBean) iter.next();
+ assertEquals("test2", bean2.getName());
+ assertEquals(36, bean2.getAge());
+ }
+
+ public void testBindingDate() throws Exception {
+ TestBean bean = new TestBean();
+ SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
+ Date expected = dateFormat.parse("06-03-2006");
+
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("date", "06-03-2006");
+
+ PortletRequestDataBinder binder = new PortletRequestDataBinder(bean);
+ binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
+ binder.bind(request);
+
+ assertEquals(expected, bean.getDate());
+ }
+
+ public void testBindingFailsWhenMissingRequiredParam() {
+ TestBean bean = new TestBean();
+ PortletRequestDataBinder binder = new PortletRequestDataBinder(bean);
+ binder.setRequiredFields(new String[] {"age", "name"});
+
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("age", "35");
+ binder.bind(request);
+
+ BindingResult error = binder.getBindingResult();
+ assertNotNull(error.getFieldError("name"));
+ assertEquals("required", error.getFieldError("name").getCode());
+ }
+
+ public void testBindingExcludesDisallowedParam() {
+ TestBean bean = new TestBean();
+ PortletRequestDataBinder binder = new PortletRequestDataBinder(bean);
+ binder.setAllowedFields(new String[] {"age"});
+
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("age", "35");
+ request.addParameter("name", "test");
+ binder.bind(request);
+
+ assertEquals(35, bean.getAge());
+ assertNull(bean.getName());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/bind/PortletRequestParameterPropertyValuesTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/bind/PortletRequestParameterPropertyValuesTests.java
new file mode 100644
index 00000000000..54166c7e91a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/bind/PortletRequestParameterPropertyValuesTests.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.portlet.bind;
+
+import org.springframework.mock.web.portlet.MockPortletRequest;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Mark Fisher
+ */
+public class PortletRequestParameterPropertyValuesTests extends TestCase {
+
+ public void testWithNoParams() {
+ MockPortletRequest request = new MockPortletRequest();
+ PortletRequestParameterPropertyValues pvs = new PortletRequestParameterPropertyValues(request);
+ assertTrue("Should not have any property values", pvs.getPropertyValues().length == 0);
+ }
+
+ public void testWithNoPrefix() {
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("param", "value");
+ PortletRequestParameterPropertyValues pvs = new PortletRequestParameterPropertyValues(request);
+ assertEquals("value", pvs.getPropertyValue("param").getValue());
+ }
+
+ public void testWithPrefix() {
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("test_param", "value");
+ PortletRequestParameterPropertyValues pvs = new PortletRequestParameterPropertyValues(request, "test");
+ assertTrue(pvs.contains("param"));
+ assertFalse(pvs.contains("test_param"));
+ assertEquals("value", pvs.getPropertyValue("param").getValue());
+ }
+
+ public void testWithPrefixAndOverridingSeparator() {
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("test.param", "value");
+ request.addParameter("test_another", "anotherValue");
+ request.addParameter("some.other", "someValue");
+ PortletRequestParameterPropertyValues pvs = new PortletRequestParameterPropertyValues(request, "test", ".");
+ assertFalse(pvs.contains("test.param"));
+ assertFalse(pvs.contains("test_another"));
+ assertFalse(pvs.contains("some.other"));
+ assertFalse(pvs.contains("another"));
+ assertFalse(pvs.contains("other"));
+ assertTrue(pvs.contains("param"));
+ assertEquals("value", pvs.getPropertyValue("param").getValue());
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/bind/PortletRequestUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/bind/PortletRequestUtilsTests.java
new file mode 100644
index 00000000000..35be90f849e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/bind/PortletRequestUtilsTests.java
@@ -0,0 +1,437 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.portlet.bind;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.portlet.MockPortletRequest;
+import org.springframework.util.StopWatch;
+
+/**
+ * @author Juergen Hoeller
+ * @author Mark Fisher
+ */
+public class PortletRequestUtilsTests extends TestCase {
+
+ public void testIntParameter() throws PortletRequestBindingException {
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("param1", "5");
+ request.addParameter("param2", "e");
+ request.addParameter("paramEmpty", "");
+
+ assertEquals(PortletRequestUtils.getIntParameter(request, "param1"), new Integer(5));
+ assertEquals(PortletRequestUtils.getIntParameter(request, "param1", 6), 5);
+ assertEquals(PortletRequestUtils.getRequiredIntParameter(request, "param1"), 5);
+
+ assertEquals(PortletRequestUtils.getIntParameter(request, "param2", 6), 6);
+ try {
+ PortletRequestUtils.getRequiredIntParameter(request, "param2");
+ fail("Should have thrown PortletRequestBindingException");
+ }
+ catch (PortletRequestBindingException ex) {
+ // expected
+ }
+
+ assertEquals(PortletRequestUtils.getIntParameter(request, "param3"), null);
+ assertEquals(PortletRequestUtils.getIntParameter(request, "param3", 6), 6);
+ try {
+ PortletRequestUtils.getRequiredIntParameter(request, "param3");
+ fail("Should have thrown PortletRequestBindingException");
+ }
+ catch (PortletRequestBindingException ex) {
+ // expected
+ }
+
+ try {
+ PortletRequestUtils.getRequiredIntParameter(request, "paramEmpty");
+ fail("Should have thrown PortletRequestBindingException");
+ }
+ catch (PortletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testIntParameters() throws PortletRequestBindingException {
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("param", new String[] {"1", "2", "3"});
+
+ request.addParameter("param2", "1");
+ request.addParameter("param2", "2");
+ request.addParameter("param2", "bogus");
+
+ int[] array = new int[] { 1, 2, 3 };
+ int[] values = PortletRequestUtils.getRequiredIntParameters(request, "param");
+ assertEquals(3, values.length);
+ for (int i = 0; i < array.length; i++) {
+ assertEquals(array[i], values[i]);
+ }
+
+ try {
+ PortletRequestUtils.getRequiredIntParameters(request, "param2");
+ fail("Should have thrown PortletRequestBindingException");
+ }
+ catch (PortletRequestBindingException ex) {
+ // expected
+ }
+
+ }
+
+ public void testLongParameter() throws PortletRequestBindingException {
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("param1", "5");
+ request.addParameter("param2", "e");
+ request.addParameter("paramEmpty", "");
+
+ assertEquals(PortletRequestUtils.getLongParameter(request, "param1"), new Long(5L));
+ assertEquals(PortletRequestUtils.getLongParameter(request, "param1", 6L), 5L);
+ assertEquals(PortletRequestUtils.getRequiredIntParameter(request, "param1"), 5L);
+ assertEquals(PortletRequestUtils.getLongParameter(request, "param2", 6L), 6L);
+
+ try {
+ PortletRequestUtils.getRequiredLongParameter(request, "param2");
+ fail("Should have thrown PortletRequestBindingException");
+ }
+ catch (PortletRequestBindingException ex) {
+ // expected
+ }
+
+ assertEquals(PortletRequestUtils.getLongParameter(request, "param3"), null);
+ assertEquals(PortletRequestUtils.getLongParameter(request, "param3", 6L), 6L);
+ try {
+ PortletRequestUtils.getRequiredLongParameter(request, "param3");
+ fail("Should have thrown PortletRequestBindingException");
+ }
+ catch (PortletRequestBindingException ex) {
+ // expected
+ }
+
+ try {
+ PortletRequestUtils.getRequiredLongParameter(request, "paramEmpty");
+ fail("Should have thrown PortletRequestBindingException");
+ }
+ catch (PortletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testLongParameters() throws PortletRequestBindingException {
+ MockPortletRequest request = new MockPortletRequest();
+ request.setParameter("param", new String[] {"1", "2", "3"});
+
+ request.setParameter("param2", "0");
+ request.setParameter("param2", "1");
+ request.addParameter("param2", "2");
+ request.addParameter("param2", "bogus");
+
+ long[] array = new long[] { 1L, 2L, 3L };
+ long[] values = PortletRequestUtils.getRequiredLongParameters(request, "param");
+ assertEquals(3, values.length);
+ for (int i = 0; i < array.length; i++) {
+ assertEquals(array[i], values[i]);
+ }
+
+ try {
+ PortletRequestUtils.getRequiredLongParameters(request, "param2");
+ fail("Should have thrown PortletRequestBindingException");
+ }
+ catch (PortletRequestBindingException ex) {
+ // expected
+ }
+
+ request.setParameter("param2", new String[] {"1", "2"});
+ values = PortletRequestUtils.getRequiredLongParameters(request, "param2");
+ assertEquals(2, values.length);
+ assertEquals(1, values[0]);
+ assertEquals(2, values[1]);
+ }
+
+ public void testFloatParameter() throws PortletRequestBindingException {
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("param1", "5.5");
+ request.addParameter("param2", "e");
+ request.addParameter("paramEmpty", "");
+
+ assertTrue(PortletRequestUtils.getFloatParameter(request, "param1").equals(new Float(5.5f)));
+ assertTrue(PortletRequestUtils.getFloatParameter(request, "param1", 6.5f) == 5.5f);
+ assertTrue(PortletRequestUtils.getRequiredFloatParameter(request, "param1") == 5.5f);
+
+ assertTrue(PortletRequestUtils.getFloatParameter(request, "param2", 6.5f) == 6.5f);
+ try {
+ PortletRequestUtils.getRequiredFloatParameter(request, "param2");
+ fail("Should have thrown PortletRequestBindingException");
+ }
+ catch (PortletRequestBindingException ex) {
+ // expected
+ }
+
+ assertTrue(PortletRequestUtils.getFloatParameter(request, "param3") == null);
+ assertTrue(PortletRequestUtils.getFloatParameter(request, "param3", 6.5f) == 6.5f);
+ try {
+ PortletRequestUtils.getRequiredFloatParameter(request, "param3");
+ fail("Should have thrown PortletRequestBindingException");
+ }
+ catch (PortletRequestBindingException ex) {
+ // expected
+ }
+
+ try {
+ PortletRequestUtils.getRequiredFloatParameter(request, "paramEmpty");
+ fail("Should have thrown PortletRequestBindingException");
+ }
+ catch (PortletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testFloatParameters() throws PortletRequestBindingException {
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("param", new String[] {"1.5", "2.5", "3"});
+
+ request.addParameter("param2", "1.5");
+ request.addParameter("param2", "2");
+ request.addParameter("param2", "bogus");
+
+ float[] array = new float[] { 1.5F, 2.5F, 3 };
+ float[] values = PortletRequestUtils.getRequiredFloatParameters(request, "param");
+ assertEquals(3, values.length);
+ for (int i = 0; i < array.length; i++) {
+ assertEquals(array[i], values[i], 0);
+ }
+
+ try {
+ PortletRequestUtils.getRequiredFloatParameters(request, "param2");
+ fail("Should have thrown PortletRequestBindingException");
+ }
+ catch (PortletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testDoubleParameter() throws PortletRequestBindingException {
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("param1", "5.5");
+ request.addParameter("param2", "e");
+ request.addParameter("paramEmpty", "");
+
+ assertTrue(PortletRequestUtils.getDoubleParameter(request, "param1").equals(new Double(5.5)));
+ assertTrue(PortletRequestUtils.getDoubleParameter(request, "param1", 6.5) == 5.5);
+ assertTrue(PortletRequestUtils.getRequiredDoubleParameter(request, "param1") == 5.5);
+
+ assertTrue(PortletRequestUtils.getDoubleParameter(request, "param2", 6.5) == 6.5);
+ try {
+ PortletRequestUtils.getRequiredDoubleParameter(request, "param2");
+ fail("Should have thrown PortletRequestBindingException");
+ }
+ catch (PortletRequestBindingException ex) {
+ // expected
+ }
+
+ assertTrue(PortletRequestUtils.getDoubleParameter(request, "param3") == null);
+ assertTrue(PortletRequestUtils.getDoubleParameter(request, "param3", 6.5) == 6.5);
+ try {
+ PortletRequestUtils.getRequiredDoubleParameter(request, "param3");
+ fail("Should have thrown PortletRequestBindingException");
+ }
+ catch (PortletRequestBindingException ex) {
+ // expected
+ }
+
+ try {
+ PortletRequestUtils.getRequiredDoubleParameter(request, "paramEmpty");
+ fail("Should have thrown PortletRequestBindingException");
+ }
+ catch (PortletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testDoubleParameters() throws PortletRequestBindingException {
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("param", new String[] {"1.5", "2.5", "3"});
+
+ request.addParameter("param2", "1.5");
+ request.addParameter("param2", "2");
+ request.addParameter("param2", "bogus");
+
+ double[] array = new double[] { 1.5, 2.5, 3 };
+ double[] values = PortletRequestUtils.getRequiredDoubleParameters(request, "param");
+ assertEquals(3, values.length);
+ for (int i = 0; i < array.length; i++) {
+ assertEquals(array[i], values[i], 0);
+ }
+
+ try {
+ PortletRequestUtils.getRequiredDoubleParameters(request, "param2");
+ fail("Should have thrown PortletRequestBindingException");
+ }
+ catch (PortletRequestBindingException ex) {
+ // expected
+ }
+ }
+
+ public void testBooleanParameter() throws PortletRequestBindingException {
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("param1", "true");
+ request.addParameter("param2", "e");
+ request.addParameter("param4", "yes");
+ request.addParameter("param5", "1");
+ request.addParameter("paramEmpty", "");
+
+ assertTrue(PortletRequestUtils.getBooleanParameter(request, "param1").equals(Boolean.TRUE));
+ assertTrue(PortletRequestUtils.getBooleanParameter(request, "param1", false));
+ assertTrue(PortletRequestUtils.getRequiredBooleanParameter(request, "param1"));
+
+ assertFalse(PortletRequestUtils.getBooleanParameter(request, "param2", true));
+ assertFalse(PortletRequestUtils.getRequiredBooleanParameter(request, "param2"));
+
+ assertTrue(PortletRequestUtils.getBooleanParameter(request, "param3") == null);
+ assertTrue(PortletRequestUtils.getBooleanParameter(request, "param3", true));
+ try {
+ PortletRequestUtils.getRequiredBooleanParameter(request, "param3");
+ fail("Should have thrown PortletRequestBindingException");
+ }
+ catch (PortletRequestBindingException ex) {
+ // expected
+ }
+
+ assertTrue(PortletRequestUtils.getBooleanParameter(request, "param4", false));
+ assertTrue(PortletRequestUtils.getRequiredBooleanParameter(request, "param4"));
+
+ assertTrue(PortletRequestUtils.getBooleanParameter(request, "param5", false));
+ assertTrue(PortletRequestUtils.getRequiredBooleanParameter(request, "param5"));
+ assertFalse(PortletRequestUtils.getRequiredBooleanParameter(request, "paramEmpty"));
+ }
+
+ public void testBooleanParameters() throws PortletRequestBindingException {
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("param", new String[] {"true", "yes", "off", "1", "bogus"});
+
+ request.addParameter("param2", "false");
+ request.addParameter("param2", "true");
+ request.addParameter("param2", "");
+
+ boolean[] array = new boolean[] { true, true, false, true, false };
+ boolean[] values = PortletRequestUtils.getRequiredBooleanParameters(request, "param");
+ assertEquals(5, values.length);
+ for (int i = 0; i < array.length; i++) {
+ assertEquals(array[i], values[i]);
+ }
+
+ array = new boolean[] { false, true, false };
+ values = PortletRequestUtils.getRequiredBooleanParameters(request, "param2");
+ assertEquals(array.length, values.length);
+ for (int i = 0; i < array.length; i++) {
+ assertEquals(array[i], values[i]);
+ }
+ }
+
+ public void testStringParameter() throws PortletRequestBindingException {
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("param1", "str");
+ request.addParameter("paramEmpty", "");
+
+ assertEquals("str", PortletRequestUtils.getStringParameter(request, "param1"));
+ assertEquals("str", PortletRequestUtils.getStringParameter(request, "param1", "string"));
+ assertEquals("str", PortletRequestUtils.getRequiredStringParameter(request, "param1"));
+
+ assertEquals(null, PortletRequestUtils.getStringParameter(request, "param3"));
+ assertEquals("string", PortletRequestUtils.getStringParameter(request, "param3", "string"));
+ try {
+ PortletRequestUtils.getRequiredStringParameter(request, "param3");
+ fail("Should have thrown PortletRequestBindingException");
+ }
+ catch (PortletRequestBindingException ex) {
+ // expected
+ }
+
+ assertEquals("", PortletRequestUtils.getStringParameter(request, "paramEmpty"));
+ assertEquals("", PortletRequestUtils.getRequiredStringParameter(request, "paramEmpty"));
+ }
+
+ public void testGetIntParameterWithDefaultValueHandlingIsFastEnough() {
+ MockPortletRequest request = new MockPortletRequest();
+ StopWatch sw = new StopWatch();
+ sw.start();
+ for (int i = 0; i < 1000000; i++) {
+ PortletRequestUtils.getIntParameter(request, "nonExistingParam", 0);
+ }
+ sw.stop();
+ System.out.println(sw.getTotalTimeMillis());
+ assertTrue("getStringParameter took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 250);
+ }
+
+ public void testGetLongParameterWithDefaultValueHandlingIsFastEnough() {
+ MockPortletRequest request = new MockPortletRequest();
+ StopWatch sw = new StopWatch();
+ sw.start();
+ for (int i = 0; i < 1000000; i++) {
+ PortletRequestUtils.getLongParameter(request, "nonExistingParam", 0);
+ }
+ sw.stop();
+ System.out.println(sw.getTotalTimeMillis());
+ assertTrue("getStringParameter took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 250);
+ }
+
+ public void testGetFloatParameterWithDefaultValueHandlingIsFastEnough() {
+ MockPortletRequest request = new MockPortletRequest();
+ StopWatch sw = new StopWatch();
+ sw.start();
+ for (int i = 0; i < 1000000; i++) {
+ PortletRequestUtils.getFloatParameter(request, "nonExistingParam", 0f);
+ }
+ sw.stop();
+ System.out.println(sw.getTotalTimeMillis());
+ assertTrue("getStringParameter took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 250);
+ }
+
+ public void testGetDoubleParameterWithDefaultValueHandlingIsFastEnough() {
+ MockPortletRequest request = new MockPortletRequest();
+ StopWatch sw = new StopWatch();
+ sw.start();
+ for (int i = 0; i < 1000000; i++) {
+ PortletRequestUtils.getDoubleParameter(request, "nonExistingParam", 0d);
+ }
+ sw.stop();
+ System.out.println(sw.getTotalTimeMillis());
+ assertTrue("getStringParameter took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 250);
+ }
+
+ public void testGetBooleanParameterWithDefaultValueHandlingIsFastEnough() {
+ MockPortletRequest request = new MockPortletRequest();
+ StopWatch sw = new StopWatch();
+ sw.start();
+ for (int i = 0; i < 1000000; i++) {
+ PortletRequestUtils.getBooleanParameter(request, "nonExistingParam", false);
+ }
+ sw.stop();
+ System.out.println(sw.getTotalTimeMillis());
+ assertTrue("getStringParameter took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 250);
+ }
+
+ public void testGetStringParameterWithDefaultValueHandlingIsFastEnough() {
+ MockPortletRequest request = new MockPortletRequest();
+ StopWatch sw = new StopWatch();
+ sw.start();
+ for (int i = 0; i < 1000000; i++) {
+ PortletRequestUtils.getStringParameter(request, "nonExistingParam", "defaultValue");
+ }
+ sw.stop();
+ System.out.println(sw.getTotalTimeMillis());
+ assertTrue("getStringParameter took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 250);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/PortletConfigAwareBean.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/PortletConfigAwareBean.java
new file mode 100644
index 00000000000..2b22f26bd7e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/PortletConfigAwareBean.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.portlet.context;
+
+import javax.portlet.PortletConfig;
+
+/**
+ * @author Mark Fisher
+ */
+public class PortletConfigAwareBean implements PortletConfigAware {
+
+ private PortletConfig portletConfig;
+
+ public void setPortletConfig(PortletConfig portletConfig) {
+ this.portletConfig = portletConfig;
+ }
+
+ public PortletConfig getPortletConfig() {
+ return portletConfig;
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/PortletContextAwareBean.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/PortletContextAwareBean.java
new file mode 100644
index 00000000000..87bbe58758e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/PortletContextAwareBean.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.portlet.context;
+
+import javax.portlet.PortletContext;
+
+/**
+ * @author Mark Fisher
+ */
+public class PortletContextAwareBean implements PortletContextAware {
+
+ private PortletContext portletContext;
+
+ public void setPortletContext(PortletContext portletContext) {
+ this.portletContext = portletContext;
+ }
+
+ public PortletContext getPortletContext() {
+ return portletContext;
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/PortletContextAwareProcessorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/PortletContextAwareProcessorTests.java
new file mode 100644
index 00000000000..d2ad1dd355c
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/PortletContextAwareProcessorTests.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.portlet.context;
+
+import javax.portlet.PortletConfig;
+import javax.portlet.PortletContext;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.portlet.MockPortletConfig;
+import org.springframework.mock.web.portlet.MockPortletContext;
+
+/**
+ * @author Mark Fisher
+ */
+public class PortletContextAwareProcessorTests extends TestCase {
+
+ public void testPortletContextAwareWithPortletContext() {
+ PortletContext portletContext = new MockPortletContext();
+ PortletContextAwareProcessor processor = new PortletContextAwareProcessor(portletContext);
+ PortletContextAwareBean bean = new PortletContextAwareBean();
+ assertNull(bean.getPortletContext());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNotNull("PortletContext should have been set", bean.getPortletContext());
+ assertEquals(portletContext, bean.getPortletContext());
+ }
+
+ public void testPortletContextAwareWithPortletConfig() {
+ PortletContext portletContext = new MockPortletContext();
+ PortletConfig portletConfig = new MockPortletConfig(portletContext);
+ PortletContextAwareProcessor processor = new PortletContextAwareProcessor(portletConfig);
+ PortletContextAwareBean bean = new PortletContextAwareBean();
+ assertNull(bean.getPortletContext());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNotNull("PortletContext should have been set", bean.getPortletContext());
+ assertEquals(portletContext, bean.getPortletContext());
+ }
+
+ public void testPortletContextAwareWithPortletContextAndPortletConfig() {
+ PortletContext portletContext = new MockPortletContext();
+ PortletConfig portletConfig = new MockPortletConfig(portletContext);
+ PortletContextAwareProcessor processor = new PortletContextAwareProcessor(portletContext, portletConfig);
+ PortletContextAwareBean bean = new PortletContextAwareBean();
+ assertNull(bean.getPortletContext());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNotNull("PortletContext should have been set", bean.getPortletContext());
+ assertEquals(portletContext, bean.getPortletContext());
+ }
+
+ public void testPortletContextAwareWithNullPortletContextAndNonNullPortletConfig() {
+ PortletContext portletContext = new MockPortletContext();
+ PortletConfig portletConfig = new MockPortletConfig(portletContext);
+ PortletContextAwareProcessor processor = new PortletContextAwareProcessor(null, portletConfig);
+ PortletContextAwareBean bean = new PortletContextAwareBean();
+ assertNull(bean.getPortletContext());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNotNull("PortletContext should have been set", bean.getPortletContext());
+ assertEquals(portletContext, bean.getPortletContext());
+ }
+
+ public void testPortletContextAwareWithNonNullPortletContextAndNullPortletConfig() {
+ PortletContext portletContext = new MockPortletContext();
+ PortletContextAwareProcessor processor = new PortletContextAwareProcessor(portletContext, null);
+ PortletContextAwareBean bean = new PortletContextAwareBean();
+ assertNull(bean.getPortletContext());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNotNull("PortletContext should have been set", bean.getPortletContext());
+ assertEquals(portletContext, bean.getPortletContext());
+ }
+
+ public void testPortletContextAwareWithNullPortletContext() {
+ PortletContext portletContext = null;
+ PortletContextAwareProcessor processor = new PortletContextAwareProcessor(portletContext);
+ PortletContextAwareBean bean = new PortletContextAwareBean();
+ assertNull(bean.getPortletContext());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNull(bean.getPortletContext());
+ }
+
+ public void testPortletConfigAwareWithPortletContextOnly() {
+ PortletContext portletContext = new MockPortletContext();
+ PortletContextAwareProcessor processor = new PortletContextAwareProcessor(portletContext);
+ PortletConfigAwareBean bean = new PortletConfigAwareBean();
+ assertNull(bean.getPortletConfig());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNull(bean.getPortletConfig());
+ }
+
+ public void testPortletConfigAwareWithPortletConfig() {
+ PortletContext portletContext = new MockPortletContext();
+ PortletConfig portletConfig = new MockPortletConfig(portletContext);
+ PortletContextAwareProcessor processor = new PortletContextAwareProcessor(portletConfig);
+ PortletConfigAwareBean bean = new PortletConfigAwareBean();
+ assertNull(bean.getPortletConfig());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNotNull("PortletConfig should have been set", bean.getPortletConfig());
+ assertEquals(portletConfig, bean.getPortletConfig());
+ }
+
+ public void testPortletConfigAwareWithPortletContextAndPortletConfig() {
+ PortletContext portletContext = new MockPortletContext();
+ PortletConfig portletConfig = new MockPortletConfig(portletContext);
+ PortletContextAwareProcessor processor = new PortletContextAwareProcessor(portletContext, portletConfig);
+ PortletConfigAwareBean bean = new PortletConfigAwareBean();
+ assertNull(bean.getPortletConfig());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNotNull("PortletConfig should have been set", bean.getPortletConfig());
+ assertEquals(portletConfig, bean.getPortletConfig());
+ }
+
+ public void testPortletConfigAwareWithNullPortletContextAndNonNullPortletConfig() {
+ PortletContext portletContext = new MockPortletContext();
+ PortletConfig portletConfig = new MockPortletConfig(portletContext);
+ PortletContextAwareProcessor processor = new PortletContextAwareProcessor(null, portletConfig);
+ PortletConfigAwareBean bean = new PortletConfigAwareBean();
+ assertNull(bean.getPortletConfig());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNotNull("PortletConfig should have been set", bean.getPortletConfig());
+ assertEquals(portletConfig, bean.getPortletConfig());
+ }
+
+ public void testPortletConfigAwareWithNonNullPortletContextAndNullPortletConfig() {
+ PortletContext portletContext = new MockPortletContext();
+ PortletContextAwareProcessor processor = new PortletContextAwareProcessor(portletContext, null);
+ PortletConfigAwareBean bean = new PortletConfigAwareBean();
+ assertNull(bean.getPortletConfig());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNull(bean.getPortletConfig());
+ }
+
+ public void testPortletConfigAwareWithNullPortletContext() {
+ PortletContext portletContext = null;
+ PortletContextAwareProcessor processor = new PortletContextAwareProcessor(portletContext);
+ PortletConfigAwareBean bean = new PortletConfigAwareBean();
+ assertNull(bean.getPortletConfig());
+ processor.postProcessBeforeInitialization(bean, "testBean");
+ assertNull(bean.getPortletConfig());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/PortletRequestAttributesTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/PortletRequestAttributesTests.java
new file mode 100644
index 00000000000..5454bf007e0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/PortletRequestAttributesTests.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.web.portlet.context;
+
+import java.io.Serializable;
+
+import javax.portlet.PortletRequest;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.mock.web.portlet.MockPortletRequest;
+import org.springframework.mock.web.portlet.MockPortletSession;
+import org.springframework.test.AssertThrows;
+import org.springframework.web.context.request.RequestAttributes;
+
+/**
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class PortletRequestAttributesTests extends TestCase {
+
+ private static final String KEY = "ThatThingThatThing";
+
+
+ private static final Serializable VALUE = new Serializable() {
+ };
+
+
+ public void testCtorRejectsNullArg() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ new PortletRequestAttributes(null);
+ }
+ }.runTest();
+ }
+
+ public void testUpdateAccessedAttributes() throws Exception {
+ MockPortletSession session = new MockPortletSession();
+ session.setAttribute(KEY, VALUE);
+ MockPortletRequest request = new MockPortletRequest();
+ request.setSession(session);
+ PortletRequestAttributes attrs = new PortletRequestAttributes(request);
+ Object value = attrs.getAttribute(KEY, RequestAttributes.SCOPE_SESSION);
+ assertSame(VALUE, value);
+ attrs.requestCompleted();
+ }
+
+ public void testSetRequestScopedAttribute() throws Exception {
+ MockPortletRequest request = new MockPortletRequest();
+ PortletRequestAttributes attrs = new PortletRequestAttributes(request);
+ attrs.setAttribute(KEY, VALUE, RequestAttributes.SCOPE_REQUEST);
+ Object value = request.getAttribute(KEY);
+ assertSame(VALUE, value);
+ }
+
+ public void testSetRequestScopedAttributeAfterCompletion() throws Exception {
+ MockPortletRequest request = new MockPortletRequest();
+ PortletRequestAttributes attrs = new PortletRequestAttributes(request);
+ request.close();
+ try {
+ attrs.setAttribute(KEY, VALUE, RequestAttributes.SCOPE_REQUEST);
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ public void testSetSessionScopedAttribute() throws Exception {
+ MockPortletSession session = new MockPortletSession();
+ session.setAttribute(KEY, VALUE);
+ MockPortletRequest request = new MockPortletRequest();
+ request.setSession(session);
+ PortletRequestAttributes attrs = new PortletRequestAttributes(request);
+ attrs.setAttribute(KEY, VALUE, RequestAttributes.SCOPE_SESSION);
+ Object value = session.getAttribute(KEY);
+ assertSame(VALUE, value);
+ }
+
+ public void testSetSessionScopedAttributeAfterCompletion() throws Exception {
+ MockPortletSession session = new MockPortletSession();
+ session.setAttribute(KEY, VALUE);
+ MockPortletRequest request = new MockPortletRequest();
+ request.setSession(session);
+ PortletRequestAttributes attrs = new PortletRequestAttributes(request);
+ attrs.requestCompleted();
+ request.close();
+ attrs.setAttribute(KEY, VALUE, RequestAttributes.SCOPE_SESSION);
+ Object value = session.getAttribute(KEY);
+ assertSame(VALUE, value);
+ }
+
+ public void testSetGlobalSessionScopedAttribute() throws Exception {
+ MockPortletSession session = new MockPortletSession();
+ session.setAttribute(KEY, VALUE);
+ MockPortletRequest request = new MockPortletRequest();
+ request.setSession(session);
+ PortletRequestAttributes attrs = new PortletRequestAttributes(request);
+ attrs.setAttribute(KEY, VALUE, RequestAttributes.SCOPE_GLOBAL_SESSION);
+ Object value = session.getAttribute(KEY);
+ assertSame(VALUE, value);
+ }
+
+ public void testSetGlobalSessionScopedAttributeAfterCompletion() throws Exception {
+ MockPortletSession session = new MockPortletSession();
+ session.setAttribute(KEY, VALUE);
+ MockPortletRequest request = new MockPortletRequest();
+ request.setSession(session);
+ PortletRequestAttributes attrs = new PortletRequestAttributes(request);
+ attrs.requestCompleted();
+ request.close();
+ attrs.setAttribute(KEY, VALUE, RequestAttributes.SCOPE_GLOBAL_SESSION);
+ Object value = session.getAttribute(KEY);
+ assertSame(VALUE, value);
+ }
+
+ public void testGetSessionScopedAttributeDoesNotForceCreationOfSession() throws Exception {
+ MockControl mockRequest = MockControl.createControl(PortletRequest.class);
+ PortletRequest request = (PortletRequest) mockRequest.getMock();
+ request.getPortletSession(false);
+ mockRequest.setReturnValue(null, 1);
+ mockRequest.replay();
+
+ PortletRequestAttributes attrs = new PortletRequestAttributes(request);
+ Object value = attrs.getAttribute(KEY, RequestAttributes.SCOPE_SESSION);
+ assertNull(value);
+
+ mockRequest.verify();
+ }
+
+ public void testRemoveSessionScopedAttribute() throws Exception {
+ MockPortletSession session = new MockPortletSession();
+ session.setAttribute(KEY, VALUE);
+ MockPortletRequest request = new MockPortletRequest();
+ request.setSession(session);
+ PortletRequestAttributes attrs = new PortletRequestAttributes(request);
+ attrs.removeAttribute(KEY, RequestAttributes.SCOPE_SESSION);
+ Object value = session.getAttribute(KEY);
+ assertNull(value);
+ }
+
+ public void testRemoveSessionScopedAttributeDoesNotForceCreationOfSession() throws Exception {
+ MockControl mockRequest = MockControl.createControl(PortletRequest.class);
+ PortletRequest request = (PortletRequest) mockRequest.getMock();
+ request.getPortletSession(false);
+ mockRequest.setReturnValue(null, 1);
+ mockRequest.replay();
+
+ PortletRequestAttributes attrs = new PortletRequestAttributes(request);
+ attrs.removeAttribute(KEY, RequestAttributes.SCOPE_SESSION);
+
+ mockRequest.verify();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/PortletWebRequestTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/PortletWebRequestTests.java
new file mode 100644
index 00000000000..193dde60be9
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/PortletWebRequestTests.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.portlet.context;
+
+import java.util.Locale;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.portlet.MockPortletRequest;
+
+/**
+ * @author Juergen Hoeller
+ * @since 26.07.2006
+ */
+public class PortletWebRequestTests extends TestCase {
+
+ public void testParameters() {
+ MockPortletRequest portletRequest = new MockPortletRequest();
+ portletRequest.addParameter("param1", "value1");
+ portletRequest.addParameter("param2", "value2");
+ portletRequest.addParameter("param2", "value2a");
+
+ PortletWebRequest request = new PortletWebRequest(portletRequest);
+ assertEquals("value1", request.getParameter("param1"));
+ assertEquals(1, request.getParameterValues("param1").length);
+ assertEquals("value1", request.getParameterValues("param1")[0]);
+ assertEquals("value2", request.getParameter("param2"));
+ assertEquals(2, request.getParameterValues("param2").length);
+ assertEquals("value2", request.getParameterValues("param2")[0]);
+ assertEquals("value2a", request.getParameterValues("param2")[1]);
+
+ Map paramMap = request.getParameterMap();
+ assertEquals(2, paramMap.size());
+ assertEquals(1, ((String[]) paramMap.get("param1")).length);
+ assertEquals("value1", ((String[]) paramMap.get("param1"))[0]);
+ assertEquals(2, ((String[]) paramMap.get("param2")).length);
+ assertEquals("value2", ((String[]) paramMap.get("param2"))[0]);
+ assertEquals("value2a", ((String[]) paramMap.get("param2"))[1]);
+ }
+
+ public void testLocale() {
+ MockPortletRequest portletRequest = new MockPortletRequest();
+ portletRequest.addPreferredLocale(Locale.UK);
+
+ PortletWebRequest request = new PortletWebRequest(portletRequest);
+ assertEquals(Locale.UK, request.getLocale());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/WEB-INF/empty-portlet.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/WEB-INF/empty-portlet.xml
new file mode 100644
index 00000000000..0ae01091c42
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/WEB-INF/empty-portlet.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/WEB-INF/test-portlet.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/WEB-INF/test-portlet.xml
new file mode 100644
index 00000000000..247ad1986a0
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/WEB-INF/test-portlet.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/XmlPortletApplicationContextTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/XmlPortletApplicationContextTests.java
new file mode 100644
index 00000000000..9014bc59f14
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/context/XmlPortletApplicationContextTests.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.portlet.context;
+
+import java.util.Locale;
+
+import javax.portlet.PortletConfig;
+import javax.portlet.PortletContext;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.NoSuchMessageException;
+import org.springframework.mock.web.portlet.MockPortletConfig;
+import org.springframework.mock.web.portlet.MockPortletContext;
+import org.springframework.web.context.XmlWebApplicationContextTests;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @author Mark Fisher
+ */
+public class XmlPortletApplicationContextTests extends XmlWebApplicationContextTests {
+
+ private ConfigurablePortletApplicationContext root;
+
+ protected ConfigurableApplicationContext createContext() throws Exception {
+ root = new XmlPortletApplicationContext();
+ PortletContext portletContext = new MockPortletContext();
+ PortletConfig portletConfig = new MockPortletConfig(portletContext);
+ root.setPortletConfig(portletConfig);
+ root.setConfigLocations(new String[] {"/org/springframework/web/context/WEB-INF/applicationContext.xml"});
+ root.addBeanFactoryPostProcessor(new BeanFactoryPostProcessor() {
+ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
+ beanFactory.addBeanPostProcessor(new BeanPostProcessor() {
+ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+ if(bean instanceof TestBean) {
+ ((TestBean) bean).getFriends().add("myFriend");
+ }
+ return bean;
+ }
+
+ public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+ return bean;
+ }
+ });
+ }
+ });
+ root.refresh();
+ XmlPortletApplicationContext pac = new XmlPortletApplicationContext();
+ pac.setParent(root);
+ pac.setPortletConfig(portletConfig);
+ pac.setNamespace("test-portlet");
+ pac.setConfigLocations(new String[] {"/org/springframework/web/portlet/context/WEB-INF/test-portlet.xml"});
+ pac.refresh();
+ return pac;
+ }
+
+ /**
+ * Overridden in order to use MockPortletConfig
+ * @see org.springframework.web.context.XmlWebApplicationContextTests#testWithoutMessageSource()
+ */
+ public void testWithoutMessageSource() throws Exception {
+ MockPortletContext portletContext = new MockPortletContext("");
+ MockPortletConfig portletConfig = new MockPortletConfig(portletContext);
+ XmlPortletApplicationContext pac = new XmlPortletApplicationContext();
+ pac.setParent(root);
+ pac.setPortletConfig(portletConfig);
+ pac.setNamespace("testNamespace");
+ pac.setConfigLocations(new String[] {"/org/springframework/web/portlet/context/WEB-INF/test-portlet.xml"});
+ pac.refresh();
+ try {
+ pac.getMessage("someMessage", null, Locale.getDefault());
+ fail("Should have thrown NoSuchMessageException");
+ }
+ catch (NoSuchMessageException ex) {
+ // expected;
+ }
+ String msg = pac.getMessage("someMessage", null, "default", Locale.getDefault());
+ assertTrue("Default message returned", "default".equals(msg));
+ }
+
+ /**
+ * Overridden in order to access the root ApplicationContext
+ * @see org.springframework.web.context.XmlWebApplicationContextTests#testContextNesting()
+ */
+ public void testContextNesting() {
+ TestBean father = (TestBean) this.applicationContext.getBean("father");
+ assertTrue("Bean from root context", father != null);
+ assertTrue("Custom BeanPostProcessor applied", father.getFriends().contains("myFriend"));
+
+ TestBean rod = (TestBean) this.applicationContext.getBean("rod");
+ assertTrue("Bean from child context", "Rod".equals(rod.getName()));
+ assertTrue("Bean has external reference", rod.getSpouse() == father);
+ assertTrue("Custom BeanPostProcessor not applied", !rod.getFriends().contains("myFriend"));
+
+ rod = (TestBean) this.root.getBean("rod");
+ assertTrue("Bean from root context", "Roderick".equals(rod.getName()));
+ assertTrue("Custom BeanPostProcessor applied", rod.getFriends().contains("myFriend"));
+ }
+
+ public void testCount() {
+ assertTrue("should have 16 beans, not "+ this.applicationContext.getBeanDefinitionCount(),
+ this.applicationContext.getBeanDefinitionCount() == 16);
+ }
+
+ public void testPortletContextAwareBean() {
+ PortletContextAwareBean bean = (PortletContextAwareBean)this.applicationContext.getBean("portletContextAwareBean");
+ assertNotNull(bean.getPortletContext());
+ }
+
+ public void testPortletConfigAwareBean() {
+ PortletConfigAwareBean bean = (PortletConfigAwareBean)this.applicationContext.getBean("portletConfigAwareBean");
+ assertNotNull(bean.getPortletConfig());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/ParameterHandlerMappingTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/ParameterHandlerMappingTests.java
new file mode 100644
index 00000000000..fbacd30f1f6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/ParameterHandlerMappingTests.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.portlet.handler;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.portlet.MockPortletContext;
+import org.springframework.mock.web.portlet.MockPortletRequest;
+import org.springframework.web.portlet.HandlerMapping;
+import org.springframework.web.portlet.context.ConfigurablePortletApplicationContext;
+import org.springframework.web.portlet.context.XmlPortletApplicationContext;
+
+/**
+ * @author Mark Fisher
+ */
+public class ParameterHandlerMappingTests extends TestCase {
+
+ public static final String CONF = "/org/springframework/web/portlet/handler/parameterMapping.xml";
+
+ private ConfigurablePortletApplicationContext pac;
+
+ public void setUp() throws Exception {
+ MockPortletContext portletContext = new MockPortletContext();
+ pac = new XmlPortletApplicationContext();
+ pac.setPortletContext(portletContext);
+ pac.setConfigLocations(new String[] {CONF});
+ pac.refresh();
+ }
+
+ public void testParameterMapping() throws Exception {
+ HandlerMapping hm = (HandlerMapping)pac.getBean("handlerMapping");
+
+ MockPortletRequest addRequest = new MockPortletRequest();
+ addRequest.addParameter("action", "add");
+
+ MockPortletRequest removeRequest = new MockPortletRequest();
+ removeRequest.addParameter("action", "remove");
+
+ Object addHandler = hm.getHandler(addRequest).getHandler();
+ Object removeHandler = hm.getHandler(removeRequest).getHandler();
+
+ assertEquals(pac.getBean("addItemHandler"), addHandler);
+ assertEquals(pac.getBean("removeItemHandler"), removeHandler);
+ }
+
+ public void testUnregisteredHandlerWithNoDefault() throws Exception {
+ HandlerMapping hm = (HandlerMapping)pac.getBean("handlerMapping");
+
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("action", "modify");
+
+ assertNull(hm.getHandler(request));
+ }
+
+ public void testUnregisteredHandlerWithDefault() throws Exception {
+ ParameterHandlerMapping hm = (ParameterHandlerMapping)pac.getBean("handlerMapping");
+ Object defaultHandler = new Object();
+ hm.setDefaultHandler(defaultHandler);
+
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("action", "modify");
+
+ assertNotNull(hm.getHandler(request));
+ assertEquals(defaultHandler, hm.getHandler(request).getHandler());
+ }
+
+ public void testConfiguredParameterName() throws Exception {
+ ParameterHandlerMapping hm = (ParameterHandlerMapping)pac.getBean("handlerMapping");
+ hm.setParameterName("someParam");
+
+ MockPortletRequest request = new MockPortletRequest();
+ request.addParameter("someParam", "add");
+
+ Object handler = hm.getHandler(request).getHandler();
+ assertEquals(pac.getBean("addItemHandler"), handler);
+ }
+
+ public void testDuplicateMappingAttempt() {
+ ParameterHandlerMapping hm = (ParameterHandlerMapping)pac.getBean("handlerMapping");
+ try {
+ hm.registerHandler("add", new Object());
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/ParameterMappingInterceptorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/ParameterMappingInterceptorTests.java
new file mode 100644
index 00000000000..644786283c7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/ParameterMappingInterceptorTests.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.portlet.handler;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.portlet.MockActionRequest;
+import org.springframework.mock.web.portlet.MockActionResponse;
+import org.springframework.mock.web.portlet.MockRenderRequest;
+import org.springframework.mock.web.portlet.MockRenderResponse;
+
+/**
+ * @author Mark Fisher
+ */
+public class ParameterMappingInterceptorTests extends TestCase {
+
+ public void testDefaultParameterMapped() throws Exception {
+ ParameterMappingInterceptor interceptor = new ParameterMappingInterceptor();
+ Object handler = new Object();
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ String param = ParameterHandlerMapping.DEFAULT_PARAMETER_NAME;
+ String value = "someValue";
+ request.setParameter(param, value);
+ assertNull(response.getRenderParameter(param));
+ boolean shouldProceed = interceptor.preHandleAction(request, response, handler);
+ assertTrue(shouldProceed);
+ assertNotNull(response.getRenderParameter(param));
+ assertEquals(value, response.getRenderParameter(param));
+ }
+
+ public void testNonDefaultParameterNotMapped() throws Exception {
+ ParameterMappingInterceptor interceptor = new ParameterMappingInterceptor();
+ Object handler = new Object();
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ String param = "myParam";
+ String value = "someValue";
+ request.setParameter(param, value);
+ assertNull(response.getRenderParameter(param));
+ boolean shouldProceed = interceptor.preHandle(request, response, handler);
+ assertTrue(shouldProceed);
+ assertNull(response.getRenderParameter(param));
+ assertNull(response.getRenderParameter(ParameterHandlerMapping.DEFAULT_PARAMETER_NAME));
+ }
+
+ public void testNonDefaultParameterMappedWhenHandlerMappingProvided() throws Exception {
+ String param = "myParam";
+ String value = "someValue";
+ ParameterHandlerMapping handlerMapping = new ParameterHandlerMapping();
+ handlerMapping.setParameterName(param);
+ ParameterMappingInterceptor interceptor = new ParameterMappingInterceptor();
+ interceptor.setParameterName(param);
+ Object handler = new Object();
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ request.setParameter(param, value);
+ assertNull(response.getRenderParameter(param));
+ boolean shouldProceed = interceptor.preHandleAction(request, response, handler);
+ assertTrue(shouldProceed);
+ assertNull(response.getRenderParameter(ParameterHandlerMapping.DEFAULT_PARAMETER_NAME));
+ assertNotNull(response.getRenderParameter(param));
+ assertEquals(value, response.getRenderParameter(param));
+ }
+
+ public void testNoEffectForRenderRequest() throws Exception {
+ ParameterMappingInterceptor interceptor = new ParameterMappingInterceptor();
+ Object handler = new Object();
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ String param = ParameterHandlerMapping.DEFAULT_PARAMETER_NAME;
+ String value = "someValue";
+ request.setParameter(param, value);
+ boolean shouldProceed = interceptor.preHandle(request, response, handler);
+ assertTrue(shouldProceed);
+ }
+
+ public void testNoParameterValueSetWithDefaultParameterName() throws Exception {
+ ParameterMappingInterceptor interceptor = new ParameterMappingInterceptor();
+ Object handler = new Object();
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ String param = ParameterHandlerMapping.DEFAULT_PARAMETER_NAME;
+ assertNull(response.getRenderParameter(param));
+ boolean shouldProceed = interceptor.preHandle(request, response, handler);
+ assertTrue(shouldProceed);
+ assertNull(response.getRenderParameter(param));
+ }
+
+ public void testNoParameterValueSetWithNonDefaultParameterName() throws Exception {
+ ParameterMappingInterceptor interceptor = new ParameterMappingInterceptor();
+ Object handler = new Object();
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ String param = "myParam";
+ assertNull(response.getRenderParameter(param));
+ boolean shouldProceed = interceptor.preHandle(request, response, handler);
+ assertTrue(shouldProceed);
+ assertNull(response.getRenderParameter(param));
+ }
+
+ public void testNoParameterValueSetWithNonDefaultParameterNameWhenHandlerMappingProvided() throws Exception {
+ String param = "myParam";
+ ParameterHandlerMapping handlerMapping = new ParameterHandlerMapping();
+ handlerMapping.setParameterName(param);
+ ParameterMappingInterceptor interceptor = new ParameterMappingInterceptor();
+ interceptor.setParameterName(param);
+ Object handler = new Object();
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ assertNull(response.getRenderParameter(param));
+ boolean shouldProceed = interceptor.preHandle(request, response, handler);
+ assertTrue(shouldProceed);
+ assertNull(response.getRenderParameter(param));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/PortletModeHandlerMappingTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/PortletModeHandlerMappingTests.java
new file mode 100644
index 00000000000..f1bda016299
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/PortletModeHandlerMappingTests.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.portlet.handler;
+
+import javax.portlet.PortletMode;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.portlet.MockPortletContext;
+import org.springframework.mock.web.portlet.MockPortletRequest;
+import org.springframework.web.portlet.HandlerMapping;
+import org.springframework.web.portlet.context.ConfigurablePortletApplicationContext;
+import org.springframework.web.portlet.context.XmlPortletApplicationContext;
+
+/**
+ * @author Mark Fisher
+ */
+public class PortletModeHandlerMappingTests extends TestCase {
+
+ public static final String CONF = "/org/springframework/web/portlet/handler/portletModeMapping.xml";
+
+ private ConfigurablePortletApplicationContext pac;
+
+ public void setUp() throws Exception {
+ MockPortletContext portletContext = new MockPortletContext();
+ pac = new XmlPortletApplicationContext();
+ pac.setPortletContext(portletContext);
+ pac.setConfigLocations(new String[] {CONF});
+ pac.refresh();
+ }
+
+ public void testPortletModeView() throws Exception {
+ HandlerMapping hm = (HandlerMapping)pac.getBean("handlerMapping");
+
+ MockPortletRequest request = new MockPortletRequest();
+ request.setPortletMode(PortletMode.VIEW);
+
+ Object handler = hm.getHandler(request).getHandler();
+ assertEquals(pac.getBean("viewHandler"), handler);
+ }
+
+ public void testPortletModeEdit() throws Exception {
+ HandlerMapping hm = (HandlerMapping)pac.getBean("handlerMapping");
+
+ MockPortletRequest request = new MockPortletRequest();
+ request.setPortletMode(PortletMode.EDIT);
+
+ Object handler = hm.getHandler(request).getHandler();
+ assertEquals(pac.getBean("editHandler"), handler);
+ }
+
+ public void testPortletModeHelp() throws Exception {
+ HandlerMapping hm = (HandlerMapping)pac.getBean("handlerMapping");
+
+ MockPortletRequest request = new MockPortletRequest();
+ request.setPortletMode(PortletMode.HELP);
+
+ Object handler = hm.getHandler(request).getHandler();
+ assertEquals(pac.getBean("helpHandler"), handler);
+ }
+
+ public void testDuplicateMappingAttempt() {
+ PortletModeHandlerMapping hm = (PortletModeHandlerMapping)pac.getBean("handlerMapping");
+ try {
+ hm.registerHandler(PortletMode.VIEW, new Object());
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/PortletModeParameterHandlerMappingTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/PortletModeParameterHandlerMappingTests.java
new file mode 100644
index 00000000000..1bf68e45fa4
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/PortletModeParameterHandlerMappingTests.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.portlet.handler;
+
+import javax.portlet.PortletMode;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.portlet.MockPortletContext;
+import org.springframework.mock.web.portlet.MockPortletRequest;
+import org.springframework.web.portlet.HandlerMapping;
+import org.springframework.web.portlet.context.ConfigurablePortletApplicationContext;
+import org.springframework.web.portlet.context.XmlPortletApplicationContext;
+
+/**
+ * @author Mark Fisher
+ */
+public class PortletModeParameterHandlerMappingTests extends TestCase {
+
+ public static final String CONF = "/org/springframework/web/portlet/handler/portletModeParameterMapping.xml";
+
+ private ConfigurablePortletApplicationContext pac;
+
+ public void setUp() throws Exception {
+ MockPortletContext portletContext = new MockPortletContext();
+ pac = new XmlPortletApplicationContext();
+ pac.setPortletContext(portletContext);
+ pac.setConfigLocations(new String[] {CONF});
+ pac.refresh();
+ }
+
+ public void testPortletModeViewWithParameter() throws Exception {
+ HandlerMapping hm = (HandlerMapping)pac.getBean("handlerMapping");
+
+ MockPortletRequest addRequest = new MockPortletRequest();
+ addRequest.setPortletMode(PortletMode.VIEW);
+ addRequest.setParameter("action", "add");
+
+ MockPortletRequest removeRequest = new MockPortletRequest();
+ removeRequest.setPortletMode(PortletMode.VIEW);
+ removeRequest.setParameter("action", "remove");
+
+ Object addHandler = hm.getHandler(addRequest).getHandler();
+ Object removeHandler = hm.getHandler(removeRequest).getHandler();
+
+ assertEquals(pac.getBean("addItemHandler"), addHandler);
+ assertEquals(pac.getBean("removeItemHandler"), removeHandler);
+ }
+
+ public void testPortletModeEditWithParameter() throws Exception {
+ HandlerMapping hm = (HandlerMapping)pac.getBean("handlerMapping");
+
+ MockPortletRequest request = new MockPortletRequest();
+ request.setPortletMode(PortletMode.EDIT);
+ request.setParameter("action", "prefs");
+
+ Object handler = hm.getHandler(request).getHandler();
+ assertEquals(pac.getBean("preferencesHandler"), handler);
+ }
+
+ public void testDuplicateMappingInSamePortletMode() {
+ PortletModeParameterHandlerMapping hm = (PortletModeParameterHandlerMapping)pac.getBean("handlerMapping");
+ try {
+ hm.registerHandler(PortletMode.VIEW, "remove", new Object());
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ public void testDuplicateMappingInDifferentPortletMode() {
+ PortletModeParameterHandlerMapping hm = (PortletModeParameterHandlerMapping)pac.getBean("handlerMapping");
+ try {
+ hm.registerHandler(PortletMode.EDIT, "remove", new Object());
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+ public void testAllowDuplicateMappingInDifferentPortletMode() throws Exception {
+ PortletModeParameterHandlerMapping hm = (PortletModeParameterHandlerMapping)pac.getBean("handlerMapping");
+ hm.setAllowDuplicateParameters(true);
+
+ Object editRemoveHandler = new Object();
+ hm.registerHandler(PortletMode.EDIT, "remove", editRemoveHandler);
+
+ MockPortletRequest request = new MockPortletRequest();
+ request.setPortletMode(PortletMode.EDIT);
+ request.setParameter("action", "remove");
+
+ Object handler = hm.getHandler(request).getHandler();
+ assertEquals(editRemoveHandler, handler);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/SimpleMappingExceptionResolverTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/SimpleMappingExceptionResolverTests.java
new file mode 100644
index 00000000000..8cc1ec1fe93
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/SimpleMappingExceptionResolverTests.java
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.portlet.handler;
+
+import java.util.Collections;
+import java.util.Properties;
+
+import javax.portlet.WindowState;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.portlet.MockRenderRequest;
+import org.springframework.mock.web.portlet.MockRenderResponse;
+import org.springframework.web.portlet.ModelAndView;
+
+/**
+ * @author Seth Ladd
+ * @author Mark Fisher
+ * @author Juergen Hoeller
+ */
+public class SimpleMappingExceptionResolverTests extends TestCase {
+
+ private static final String DEFAULT_VIEW = "default-view";
+
+ private SimpleMappingExceptionResolver exceptionResolver;
+ private MockRenderRequest request;
+ private MockRenderResponse response;
+ private Object handler1;
+ private Object handler2;
+ private Exception genericException;
+
+ protected void setUp() {
+ exceptionResolver = new SimpleMappingExceptionResolver();
+ request = new MockRenderRequest();
+ response = new MockRenderResponse();
+ handler1 = new String();
+ handler2 = new Object();
+ genericException = new Exception();
+ }
+
+ public void testSetOrder() {
+ exceptionResolver.setOrder(2);
+ assertEquals(2, exceptionResolver.getOrder());
+ }
+
+ public void testDefaultErrorView() {
+ exceptionResolver.setDefaultErrorView(DEFAULT_VIEW);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertEquals(DEFAULT_VIEW, mav.getViewName());
+ assertEquals(genericException, mav.getModel().get(SimpleMappingExceptionResolver.DEFAULT_EXCEPTION_ATTRIBUTE));
+ }
+
+ public void testDefaultErrorViewDifferentHandler() {
+ exceptionResolver.setDefaultErrorView(DEFAULT_VIEW);
+ exceptionResolver.setMappedHandlers(Collections.singleton(handler1));
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler2, genericException);
+ assertNull("Handler not mapped - ModelAndView should be null", mav);
+ }
+
+ public void testDefaultErrorViewDifferentHandlerClass() {
+ exceptionResolver.setDefaultErrorView(DEFAULT_VIEW);
+ exceptionResolver.setMappedHandlerClasses(new Class[] {String.class});
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler2, genericException);
+ assertNull("Handler not mapped - ModelAndView should be null", mav);
+ }
+
+ public void testNullDefaultErrorView() {
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertNull("No default error view set - ModelAndView should be null", mav);
+ }
+
+ public void testNullExceptionAttribute() {
+ exceptionResolver.setDefaultErrorView(DEFAULT_VIEW);
+ exceptionResolver.setExceptionAttribute(null);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertEquals(DEFAULT_VIEW, mav.getViewName());
+ assertNull(mav.getModel().get(SimpleMappingExceptionResolver.DEFAULT_EXCEPTION_ATTRIBUTE));
+ }
+
+ public void testNullExceptionMappings() {
+ exceptionResolver.setExceptionMappings(null);
+ exceptionResolver.setDefaultErrorView(DEFAULT_VIEW);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertEquals(DEFAULT_VIEW, mav.getViewName());
+ }
+
+ public void testDefaultNoRenderWhenMinimized() {
+ exceptionResolver.setDefaultErrorView(DEFAULT_VIEW);
+ request.setWindowState(WindowState.MINIMIZED);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertNull("Should not render when WindowState is MINIMIZED", mav);
+ }
+
+ public void testDoRenderWhenMinimized() {
+ exceptionResolver.setDefaultErrorView(DEFAULT_VIEW);
+ exceptionResolver.setRenderWhenMinimized(true);
+ request.setWindowState(WindowState.MINIMIZED);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertNotNull("ModelAndView should not be null", mav);
+ assertEquals(DEFAULT_VIEW, mav.getViewName());
+ }
+
+ public void testSimpleExceptionMapping() {
+ Properties props = new Properties();
+ props.setProperty("Exception", "error");
+ exceptionResolver.setWarnLogCategory("HANDLER_EXCEPTION");
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertEquals("error", mav.getViewName());
+ }
+
+ public void testExactExceptionMappingWithHandlerSpecified() {
+ Properties props = new Properties();
+ props.setProperty("java.lang.Exception", "error");
+ exceptionResolver.setMappedHandlers(Collections.singleton(handler1));
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertEquals("error", mav.getViewName());
+ }
+
+ public void testExactExceptionMappingWithHandlerClassSpecified() {
+ Properties props = new Properties();
+ props.setProperty("java.lang.Exception", "error");
+ exceptionResolver.setMappedHandlerClasses(new Class[] {String.class});
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertEquals("error", mav.getViewName());
+ }
+
+ public void testExactExceptionMappingWithHandlerInterfaceSpecified() {
+ Properties props = new Properties();
+ props.setProperty("java.lang.Exception", "error");
+ exceptionResolver.setMappedHandlerClasses(new Class[] {Comparable.class});
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertEquals("error", mav.getViewName());
+ }
+
+ public void testSimpleExceptionMappingWithHandlerSpecifiedButWrongHandler() {
+ Properties props = new Properties();
+ props.setProperty("Exception", "error");
+ exceptionResolver.setMappedHandlers(Collections.singleton(handler1));
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler2, genericException);
+ assertNull("Handler not mapped - ModelAndView should be null", mav);
+ }
+
+ public void testSimpleExceptionMappingWithHandlerSpecifiedButWrongHandlerClass() {
+ Properties props = new Properties();
+ props.setProperty("Exception", "error");
+ exceptionResolver.setMappedHandlerClasses(new Class[] {String.class});
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler2, genericException);
+ assertNull("Handler not mapped - ModelAndView should be null", mav);
+ }
+
+ public void testMissingExceptionInMapping() {
+ Properties props = new Properties();
+ props.setProperty("SomeFooThrowable", "error");
+ exceptionResolver.setWarnLogCategory("HANDLER_EXCEPTION");
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertNull("Exception not mapped - ModelAndView should be null", mav);
+ }
+
+ public void testTwoMappings() {
+ Properties props = new Properties();
+ props.setProperty("java.lang.Exception", "error");
+ props.setProperty("AnotherException", "another-error");
+ exceptionResolver.setMappedHandlers(Collections.singleton(handler1));
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertEquals("error", mav.getViewName());
+ }
+
+ public void testTwoMappingsOneShortOneLong() {
+ Properties props = new Properties();
+ props.setProperty("Exception", "error");
+ props.setProperty("AnotherException", "another-error");
+ exceptionResolver.setMappedHandlers(Collections.singleton(handler1));
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertEquals("error", mav.getViewName());
+ }
+
+ public void testTwoMappingsOneShortOneLongThrowOddException() {
+ Exception oddException = new SomeOddException();
+ Properties props = new Properties();
+ props.setProperty("Exception", "error");
+ props.setProperty("SomeOddException", "another-error");
+ exceptionResolver.setMappedHandlers(Collections.singleton(handler1));
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, oddException);
+ assertEquals("error", mav.getViewName());
+ }
+
+ public void testTwoMappingsThrowOddExceptionUseLongExceptionMapping() {
+ Exception oddException = new SomeOddException();
+ Properties props = new Properties();
+ props.setProperty("java.lang.Exception", "error");
+ props.setProperty("SomeOddException", "another-error");
+ exceptionResolver.setMappedHandlers(Collections.singleton(handler1));
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, oddException);
+ assertEquals("another-error", mav.getViewName());
+ }
+
+ public void testThreeMappings() {
+ Exception oddException = new AnotherOddException();
+ Properties props = new Properties();
+ props.setProperty("java.lang.Exception", "error");
+ props.setProperty("SomeOddException", "another-error");
+ props.setProperty("AnotherOddException", "another-some-error");
+ exceptionResolver.setMappedHandlers(Collections.singleton(handler1));
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, oddException);
+ assertEquals("another-some-error", mav.getViewName());
+ }
+
+ public void testExceptionWithSubstringMatchingParent() {
+ Exception oddException = new SomeOddExceptionChild();
+ Properties props = new Properties();
+ props.setProperty("java.lang.Exception", "error");
+ props.setProperty("SomeOddException", "parent-error");
+ props.setProperty("SomeOddExceptionChild", "child-error");
+ exceptionResolver.setMappedHandlers(Collections.singleton(handler1));
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, oddException);
+ assertEquals("child-error", mav.getViewName());
+ }
+
+ public void testMostSpecificExceptionInHierarchyWins() {
+ Exception oddException = new NoSubstringMatchesThisException();
+ Properties props = new Properties();
+ props.setProperty("java.lang.Exception", "error");
+ props.setProperty("SomeOddException", "parent-error");
+ exceptionResolver.setMappedHandlers(Collections.singleton(handler1));
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, oddException);
+ assertEquals("parent-error", mav.getViewName());
+ }
+
+
+ private static class SomeOddException extends Exception {
+
+ }
+
+
+ private static class SomeOddExceptionChild extends SomeOddException {
+
+ }
+
+
+ private static class NoSubstringMatchesThisException extends SomeOddException {
+
+ }
+
+
+ private static class AnotherOddException extends Exception {
+
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/UserRoleAuthorizationInterceptorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/UserRoleAuthorizationInterceptorTests.java
new file mode 100644
index 00000000000..7185dee9860
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/UserRoleAuthorizationInterceptorTests.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.portlet.handler;
+
+import javax.portlet.PortletSecurityException;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.portlet.MockRenderRequest;
+import org.springframework.mock.web.portlet.MockRenderResponse;
+
+/**
+ * @author Mark Fisher
+ */
+public class UserRoleAuthorizationInterceptorTests extends TestCase {
+
+ public void testAuthorizedUser() throws Exception {
+ UserRoleAuthorizationInterceptor interceptor = new UserRoleAuthorizationInterceptor();
+ String validRole = "allowed";
+ interceptor.setAuthorizedRoles(new String[] {validRole});
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ Object handler = new Object();
+ request.addUserRole(validRole);
+ assertTrue(request.isUserInRole(validRole));
+ boolean shouldProceed = interceptor.preHandle(request, response, handler);
+ assertTrue(shouldProceed);
+ }
+
+ public void testAuthorizedUserWithMultipleRoles() throws Exception {
+ UserRoleAuthorizationInterceptor interceptor = new UserRoleAuthorizationInterceptor();
+ String validRole1 = "allowed1";
+ String validRole2 = "allowed2";
+ interceptor.setAuthorizedRoles(new String[] {validRole1, validRole2});
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ Object handler = new Object();
+ request.addUserRole(validRole2);
+ request.addUserRole("someOtherRole");
+ assertFalse(request.isUserInRole(validRole1));
+ assertTrue(request.isUserInRole(validRole2));
+ boolean shouldProceed = interceptor.preHandle(request, response, handler);
+ assertTrue(shouldProceed);
+ }
+
+ public void testUnauthorizedUser() throws Exception {
+ UserRoleAuthorizationInterceptor interceptor = new UserRoleAuthorizationInterceptor();
+ String validRole = "allowed";
+ interceptor.setAuthorizedRoles(new String[] {validRole});
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ Object handler = new Object();
+ request.addUserRole("someOtherRole");
+ assertFalse(request.isUserInRole(validRole));
+ try {
+ interceptor.preHandle(request, response, handler);
+ fail("should have thrown PortletSecurityException");
+ }
+ catch (PortletSecurityException ex) {
+ // expected
+ }
+ }
+
+ public void testRequestWithNoUserRoles() throws Exception {
+ UserRoleAuthorizationInterceptor interceptor = new UserRoleAuthorizationInterceptor();
+ String validRole = "allowed";
+ interceptor.setAuthorizedRoles(new String[] {validRole});
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ Object handler = new Object();
+ assertFalse(request.isUserInRole(validRole));
+ try {
+ interceptor.preHandle(request, response, handler);
+ fail("should have thrown PortletSecurityException");
+ }
+ catch (PortletSecurityException ex) {
+ // expected
+ }
+ }
+
+ public void testInterceptorWithNoAuthorizedRoles() throws Exception {
+ UserRoleAuthorizationInterceptor interceptor = new UserRoleAuthorizationInterceptor();
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ Object handler = new Object();
+ request.addUserRole("someRole");
+ try {
+ interceptor.preHandle(request, response, handler);
+ fail("should have thrown PortletSecurityException");
+ }
+ catch (PortletSecurityException ex) {
+ // expected
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/parameterMapping.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/parameterMapping.xml
new file mode 100644
index 00000000000..f3fddf0d76f
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/parameterMapping.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/portletModeMapping.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/portletModeMapping.xml
new file mode 100644
index 00000000000..fc62e717e8e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/portletModeMapping.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/portletModeParameterMapping.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/portletModeParameterMapping.xml
new file mode 100644
index 00000000000..066d1a88c21
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/handler/portletModeParameterMapping.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/mvc/CommandControllerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/mvc/CommandControllerTests.java
new file mode 100644
index 00000000000..52a566fd398
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/mvc/CommandControllerTests.java
@@ -0,0 +1,461 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.portlet.mvc;
+
+import java.beans.PropertyEditorSupport;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.PortletRequest;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+import javax.portlet.WindowState;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.propertyeditors.CustomDateEditor;
+import org.springframework.mock.web.portlet.MockActionRequest;
+import org.springframework.mock.web.portlet.MockActionResponse;
+import org.springframework.mock.web.portlet.MockRenderRequest;
+import org.springframework.mock.web.portlet.MockRenderResponse;
+import org.springframework.validation.BindException;
+import org.springframework.validation.Errors;
+import org.springframework.validation.FieldError;
+import org.springframework.validation.ObjectError;
+import org.springframework.validation.ValidationUtils;
+import org.springframework.validation.Validator;
+import org.springframework.web.portlet.ModelAndView;
+import org.springframework.web.portlet.bind.PortletRequestDataBinder;
+import org.springframework.web.portlet.handler.PortletSessionRequiredException;
+
+/**
+ * @author Mark Fisher
+ */
+public class CommandControllerTests extends TestCase {
+
+ private static final String ERRORS_KEY = "errors";
+
+ public void testRenderRequestWithNoParams() throws Exception {
+ TestController tc = new TestController();
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setContextPath("test");
+ ModelAndView mav = tc.handleRenderRequest(request, response);
+ assertEquals("test-view", mav.getViewName());
+ assertNotNull(mav.getModel().get(tc.getCommandName()));
+ BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
+ assertNotNull(errors);
+ assertEquals("There should be no errors", 0, errors.getErrorCount());
+ }
+
+ public void testRenderRequestWithParams() throws Exception {
+ TestController tc = new TestController();
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ String name = "test";
+ int age = 30;
+ request.addParameter("name", name);
+ request.addParameter("age", "" + age);
+ request.setContextPath("test");
+ ModelAndView mav = tc.handleRenderRequest(request, response);
+ assertEquals("test-view", mav.getViewName());
+ TestBean command = (TestBean)mav.getModel().get(tc.getCommandName());
+ assertEquals("Name should be bound", name, command.getName());
+ assertEquals("Age should be bound", age, command.getAge());
+ BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
+ assertNotNull(errors);
+ assertEquals("There should be no errors", 0, errors.getErrorCount());
+ }
+
+ public void testRenderRequestWithMismatch() throws Exception {
+ TestController tc = new TestController();
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ String name = "test";
+ request.addParameter("name", name);
+ request.addParameter("age", "zzz");
+ request.setContextPath("test");
+ ModelAndView mav = tc.handleRenderRequest(request, response);
+ assertEquals("test-view", mav.getViewName());
+ TestBean command = (TestBean)mav.getModel().get(tc.getCommandName());
+ assertNotNull(command);
+ assertEquals("Name should be bound", name, command.getName());
+ BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
+ assertEquals("There should be 1 error", 1, errors.getErrorCount());
+ assertNotNull(errors.getFieldError("age"));
+ assertEquals("typeMismatch", errors.getFieldError("age").getCode());
+ }
+
+ public void testRenderWhenMinimizedReturnsNull() throws Exception {
+ TestController tc = new TestController();
+ assertFalse(tc.isRenderWhenMinimized());
+ MockRenderRequest request = new MockRenderRequest();
+ request.setWindowState(WindowState.MINIMIZED);
+ MockRenderResponse response = new MockRenderResponse();
+ ModelAndView mav = tc.handleRenderRequest(request, response);
+ assertNull("ModelAndView should be null", mav);
+ }
+
+ public void testAllowRenderWhenMinimized() throws Exception {
+ TestController tc = new TestController();
+ tc.setRenderWhenMinimized(true);
+ MockRenderRequest request = new MockRenderRequest();
+ request.setWindowState(WindowState.MINIMIZED);
+ request.setContextPath("test");
+ MockRenderResponse response = new MockRenderResponse();
+ ModelAndView mav = tc.handleRenderRequest(request, response);
+ assertNotNull("ModelAndView should not be null", mav);
+ assertEquals("test-view", mav.getViewName());
+ assertNotNull(mav.getModel().get(tc.getCommandName()));
+ BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
+ assertEquals("There should be no errors", 0, errors.getErrorCount());
+ }
+
+ public void testRequiresSessionWithoutSession() throws Exception {
+ TestController tc = new TestController();
+ tc.setRequireSession(true);
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ try {
+ tc.handleRenderRequest(request, response);
+ fail("Should have thrown PortletSessionRequiredException");
+ }
+ catch (PortletSessionRequiredException ex) {
+ // expected
+ }
+ }
+
+ public void testRequiresSessionWithSession() throws Exception {
+ TestController tc = new TestController();
+ tc.setRequireSession(true);
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+
+ // create the session
+ request.getPortletSession(true);
+ try {
+ tc.handleRenderRequest(request, response);
+ }
+ catch (PortletSessionRequiredException ex) {
+ fail("Should not have thrown PortletSessionRequiredException");
+ }
+ }
+
+ public void testRenderRequestWithoutCacheSetting() throws Exception {
+ TestController tc = new TestController();
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ tc.handleRenderRequest(request, response);
+ String cacheProperty = response.getProperty(RenderResponse.EXPIRATION_CACHE);
+ assertNull("Expiration-cache should be null", cacheProperty);
+ }
+
+ public void testRenderRequestWithNegativeCacheSetting() throws Exception {
+ TestController tc = new TestController();
+ tc.setCacheSeconds(-99);
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ tc.handleRenderRequest(request, response);
+ String cacheProperty = response.getProperty(RenderResponse.EXPIRATION_CACHE);
+ assertNull("Expiration-cache should be null", cacheProperty);
+ }
+
+ public void testRenderRequestWithZeroCacheSetting() throws Exception {
+ TestController tc = new TestController();
+ tc.setCacheSeconds(0);
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ tc.handleRenderRequest(request, response);
+ String cacheProperty = response.getProperty(RenderResponse.EXPIRATION_CACHE);
+ assertEquals("Expiration-cache should be set to 0 seconds", "0", cacheProperty);
+ }
+
+ public void testRenderRequestWithPositiveCacheSetting() throws Exception {
+ TestController tc = new TestController();
+ tc.setCacheSeconds(30);
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ tc.handleRenderRequest(request, response);
+ String cacheProperty = response.getProperty(RenderResponse.EXPIRATION_CACHE);
+ assertEquals("Expiration-cache should be set to 30 seconds", "30", cacheProperty);
+ }
+
+ public void testActionRequest() throws Exception {
+ TestController tc = new TestController();
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ tc.handleActionRequest(request, response);
+ TestBean command = (TestBean)request.getPortletSession().getAttribute(tc.getRenderCommandSessionAttributeName());
+ assertTrue(command.isJedi());
+ }
+
+ public void testSuppressBinding() throws Exception {
+ TestController tc = new TestController() {
+ protected boolean suppressBinding(PortletRequest request) {
+ return true;
+ }
+ };
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ String name = "test";
+ int age = 30;
+ request.addParameter("name", name);
+ request.addParameter("age", "" + age);
+ request.setContextPath("test");
+ ModelAndView mav = tc.handleRenderRequest(request, response);
+ assertEquals("test-view", mav.getViewName());
+ TestBean command = (TestBean)mav.getModel().get(tc.getCommandName());
+ assertNotNull(command);
+ assertTrue("Name should not have been bound", name != command.getName());
+ assertTrue("Age should not have been bound", age != command.getAge());
+ BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
+ assertEquals("There should be no errors", 0, errors.getErrorCount());
+ }
+
+ public void testWithCustomDateEditor() throws Exception {
+ final DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
+ TestController tc = new TestController() {
+ protected void initBinder(PortletRequest request, PortletRequestDataBinder binder) {
+ binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
+ }
+ };
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ String name = "test";
+ int age = 30;
+ request.addParameter("name", name);
+ request.addParameter("age", "" + age);
+ String dateString = "07-03-2006";
+ Date expectedDate = dateFormat.parse(dateString);
+ request.addParameter("date", dateString);
+ ModelAndView mav = tc.handleRenderRequest(request, response);
+ TestBean command = (TestBean)mav.getModel().get(tc.getCommandName());
+ assertEquals(name, command.getName());
+ assertEquals(age, command.getAge());
+ assertEquals(expectedDate, command.getDate());
+ BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
+ assertEquals("There should be no errors", 0, errors.getErrorCount());
+ }
+
+ public void testWithCustomDateEditorEmptyNotAllowed() throws Exception {
+ final DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
+ TestController tc = new TestController() {
+ protected void initBinder(PortletRequest request, PortletRequestDataBinder binder) {
+ binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
+ }
+ };
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ String name = "test";
+ int age = 30;
+ request.addParameter("name", name);
+ request.addParameter("age", "" + age);
+ String emptyString = "";
+ request.addParameter("date", emptyString);
+ ModelAndView mav = tc.handleRenderRequest(request, response);
+ TestBean command = (TestBean)mav.getModel().get(tc.getCommandName());
+ assertEquals(name, command.getName());
+ assertEquals(age, command.getAge());
+ BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
+ assertEquals("There should be 1 error", 1, errors.getErrorCount());
+ assertNotNull(errors.getFieldError("date"));
+ assertEquals("typeMismatch", errors.getFieldError("date").getCode());
+ assertEquals(emptyString, errors.getFieldError("date").getRejectedValue());
+ }
+
+ public void testWithCustomDateEditorEmptyAllowed() throws Exception {
+ final DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
+ TestController tc = new TestController() {
+ protected void initBinder(PortletRequest request, PortletRequestDataBinder binder) {
+ binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
+ }
+ };
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ String name = "test";
+ int age = 30;
+ request.addParameter("name", name);
+ request.addParameter("age", "" + age);
+ String dateString = "";
+ request.addParameter("date", dateString);
+ ModelAndView mav = tc.handleRenderRequest(request, response);
+ TestBean command = (TestBean)mav.getModel().get(tc.getCommandName());
+ assertEquals(name, command.getName());
+ assertEquals(age, command.getAge());
+ BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
+ assertEquals("There should be 0 errors", 0, errors.getErrorCount());
+ assertNull("date should be null", command.getDate());
+ }
+
+ public void testNestedBindingWithPropertyEditor() throws Exception {
+ TestController tc = new TestController() {
+ protected void initBinder(PortletRequest request, PortletRequestDataBinder binder) {
+ binder.registerCustomEditor(ITestBean.class, new PropertyEditorSupport() {
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue(new TestBean(text));
+ }
+ });
+ }
+ };
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ String name = "test";
+ String spouseName = "testSpouse";
+ int age = 30;
+ int spouseAge = 31;
+ request.addParameter("name", name);
+ request.addParameter("age", "" + age);
+ request.addParameter("spouse", spouseName);
+ request.addParameter("spouse.age", "" + spouseAge);
+ ModelAndView mav = tc.handleRenderRequest(request, response);
+ TestBean command = (TestBean)mav.getModel().get(tc.getCommandName());
+ assertEquals(name, command.getName());
+ assertEquals(age, command.getAge());
+ assertNotNull(command.getSpouse());
+ assertEquals(spouseName, command.getSpouse().getName());
+ assertEquals(spouseAge, command.getSpouse().getAge());
+ BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
+ assertEquals("There should be no errors", 0, errors.getErrorCount());
+ }
+
+ public void testWithValidatorNotSupportingCommandClass() throws Exception {
+ Validator v = new Validator() {
+ public boolean supports(Class c) {
+ return false;
+ }
+ public void validate(Object o, Errors e) {}
+ };
+ TestController tc = new TestController();
+ tc.setValidator(v);
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ try {
+ tc.handleRenderRequest(request, response);
+ fail("Should have thrown IllegalArgumentException");
+ }
+ catch(IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testWithValidatorAddingGlobalError() throws Exception {
+ final String errorCode = "someCode";
+ final String defaultMessage = "validation error!";
+ TestController tc = new TestController();
+ tc.setValidator(new Validator() {
+ public boolean supports(Class c) {
+ return TestBean.class.isAssignableFrom(c);
+ }
+ public void validate(Object o, Errors e) {
+ e.reject(errorCode, defaultMessage);
+ }
+ });
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ ModelAndView mav = tc.handleRenderRequest(request, response);
+ BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
+ assertEquals("There should be 1 error", 1, errors.getErrorCount());
+ ObjectError error = errors.getGlobalError();
+ assertEquals(error.getCode(), errorCode);
+ assertEquals(error.getDefaultMessage(), defaultMessage);
+ }
+
+ public void testWithValidatorAndNullFieldError() throws Exception {
+ final String errorCode = "someCode";
+ final String defaultMessage = "validation error!";
+ TestController tc = new TestController();
+ tc.setValidator(new Validator() {
+ public boolean supports(Class c) {
+ return TestBean.class.isAssignableFrom(c);
+ }
+ public void validate(Object o, Errors e) {
+ ValidationUtils.rejectIfEmpty(e, "name", errorCode, defaultMessage);
+ }
+ });
+ MockRenderRequest request = new MockRenderRequest();
+ int age = 32;
+ request.setParameter("age", "" + age);
+ MockRenderResponse response = new MockRenderResponse();
+ ModelAndView mav = tc.handleRenderRequest(request, response);
+ TestBean command = (TestBean)mav.getModel().get(tc.getCommandName());
+ assertNull("name should be null", command.getName());
+ assertEquals(age, command.getAge());
+ BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
+ assertEquals("There should be 1 error", 1, errors.getErrorCount());
+ FieldError error = errors.getFieldError("name");
+ assertEquals(error.getCode(), errorCode);
+ assertEquals(error.getDefaultMessage(), defaultMessage);
+ }
+
+ public void testWithValidatorAndWhitespaceFieldError() throws Exception {
+ final String errorCode = "someCode";
+ final String defaultMessage = "validation error!";
+ TestController tc = new TestController();
+ tc.setValidator(new Validator() {
+ public boolean supports(Class c) {
+ return TestBean.class.isAssignableFrom(c);
+ }
+ public void validate(Object o, Errors e) {
+ ValidationUtils.rejectIfEmptyOrWhitespace(e, "name", errorCode, defaultMessage);
+ }
+ });
+ MockRenderRequest request = new MockRenderRequest();
+ int age = 32;
+ String whitespace = " \t ";
+ request.setParameter("age", "" + age);
+ request.setParameter("name", whitespace);
+ MockRenderResponse response = new MockRenderResponse();
+ ModelAndView mav = tc.handleRenderRequest(request, response);
+ TestBean command = (TestBean)mav.getModel().get(tc.getCommandName());
+ assertTrue(command.getName().equals(whitespace));
+ assertEquals(age, command.getAge());
+ BindException errors = (BindException)mav.getModel().get(ERRORS_KEY);
+ assertEquals("There should be 1 error", 1, errors.getErrorCount());
+ FieldError error = errors.getFieldError("name");
+ assertEquals("rejected value should contain whitespace", whitespace, error.getRejectedValue());
+ assertEquals(error.getCode(), errorCode);
+ assertEquals(error.getDefaultMessage(), defaultMessage);
+ }
+
+ private static class TestController extends AbstractCommandController {
+
+ private TestController() {
+ super(TestBean.class, "testBean");
+ }
+
+ protected void handleAction(ActionRequest request, ActionResponse response, Object command, BindException errors) {
+ ((TestBean)command).setJedi(true);
+ }
+
+ protected ModelAndView handleRender(RenderRequest request, RenderResponse response, Object command, BindException errors) {
+ assertNotNull(command);
+ assertNotNull(errors);
+ Map model = new HashMap();
+ model.put(getCommandName(), command);
+ model.put(ERRORS_KEY, errors);
+ return new ModelAndView(request.getContextPath() + "-view", model);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/mvc/ParameterizableViewControllerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/mvc/ParameterizableViewControllerTests.java
new file mode 100644
index 00000000000..cef2df048c5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/mvc/ParameterizableViewControllerTests.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.portlet.mvc;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.PortletException;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.portlet.MockActionRequest;
+import org.springframework.mock.web.portlet.MockActionResponse;
+import org.springframework.mock.web.portlet.MockRenderRequest;
+import org.springframework.mock.web.portlet.MockRenderResponse;
+import org.springframework.web.portlet.ModelAndView;
+import org.springframework.web.portlet.context.StaticPortletApplicationContext;
+
+/**
+ * @author Mark Fisher
+ */
+public class ParameterizableViewControllerTests extends TestCase {
+
+ public void testRenderRequestWithViewNameSet() throws Exception {
+ ParameterizableViewController controller = new ParameterizableViewController();
+ String viewName = "testView";
+ controller.setViewName(viewName);
+ RenderRequest request = new MockRenderRequest();
+ RenderResponse response = new MockRenderResponse();
+ ModelAndView mav = controller.handleRenderRequest(request, response);
+ assertEquals(viewName, mav.getViewName());
+ }
+
+ public void testInitApplicationContextWithNoViewNameSet() throws Exception {
+ ParameterizableViewController controller = new ParameterizableViewController();
+ try {
+ controller.setApplicationContext(new StaticPortletApplicationContext());
+ fail("should have thrown IllegalArgumentException");
+ }
+ catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ public void testActionRequestNotHandled() throws Exception {
+ ParameterizableViewController controller = new ParameterizableViewController();
+ ActionRequest request = new MockActionRequest();
+ ActionResponse response = new MockActionResponse();
+ try {
+ controller.handleActionRequest(request, response);
+ fail("should have thrown PortletException");
+ }
+ catch (PortletException ex) {
+ // expected
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/mvc/PortletModeNameViewControllerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/mvc/PortletModeNameViewControllerTests.java
new file mode 100644
index 00000000000..5fa8569bb67
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/mvc/PortletModeNameViewControllerTests.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.portlet.mvc;
+
+import javax.portlet.PortletException;
+import javax.portlet.PortletMode;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.portlet.MockActionRequest;
+import org.springframework.mock.web.portlet.MockActionResponse;
+import org.springframework.mock.web.portlet.MockRenderRequest;
+import org.springframework.mock.web.portlet.MockRenderResponse;
+import org.springframework.web.portlet.ModelAndView;
+
+/**
+ * @author Mark Fisher
+ */
+public class PortletModeNameViewControllerTests extends TestCase {
+
+ private PortletModeNameViewController controller;
+
+ public void setUp() {
+ controller = new PortletModeNameViewController();
+ }
+
+ public void testEditPortletMode() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setPortletMode(PortletMode.EDIT);
+ ModelAndView mav = controller.handleRenderRequest(request, response);
+ assertEquals("edit", mav.getViewName());
+ }
+
+ public void testHelpPortletMode() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setPortletMode(PortletMode.HELP);
+ ModelAndView mav = controller.handleRenderRequest(request, response);
+ assertEquals("help", mav.getViewName());
+ }
+
+ public void testViewPortletMode() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ request.setPortletMode(PortletMode.VIEW);
+ ModelAndView mav = controller.handleRenderRequest(request, response);
+ assertEquals("view", mav.getViewName());
+ }
+
+ public void testActionRequest() throws Exception {
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ try {
+ controller.handleActionRequest(request, response);
+ fail("Should have thrown PortletException");
+ }
+ catch(PortletException ex) {
+ // expected
+ }
+ }
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/mvc/PortletWrappingControllerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/mvc/PortletWrappingControllerTests.java
new file mode 100644
index 00000000000..10e0ffe1256
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/mvc/PortletWrappingControllerTests.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.portlet.mvc;
+
+import junit.framework.TestCase;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.mock.web.portlet.*;
+import org.springframework.test.AssertThrows;
+import org.springframework.web.portlet.context.ConfigurablePortletApplicationContext;
+import org.springframework.web.portlet.context.StaticPortletApplicationContext;
+
+import javax.portlet.*;
+import java.io.IOException;
+
+/**
+ * Unit tests for the {@link PortletWrappingController} class.
+ *
+ * @author Mark Fisher
+ * @author Rick Evans
+ */
+public final class PortletWrappingControllerTests extends TestCase {
+
+ private static final String RESULT_RENDER_PARAMETER_NAME = "result";
+ private static final String PORTLET_WRAPPING_CONTROLLER_BEAN_NAME = "controller";
+ private static final String RENDERED_RESPONSE_CONTENT = "myPortlet-view";
+ private static final String PORTLET_NAME_ACTION_REQUEST_PARAMETER_NAME = "portletName";
+
+
+ private PortletWrappingController controller;
+
+
+ public void setUp() {
+ ConfigurablePortletApplicationContext applicationContext = new MyApplicationContext();
+ MockPortletConfig config = new MockPortletConfig(new MockPortletContext(), "wrappedPortlet");
+ applicationContext.setPortletConfig(config);
+ applicationContext.refresh();
+ controller = (PortletWrappingController) applicationContext.getBean(PORTLET_WRAPPING_CONTROLLER_BEAN_NAME);
+ }
+
+
+ public void testActionRequest() throws Exception {
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ request.setParameter("test", "test");
+ controller.handleActionRequest(request, response);
+ String result = response.getRenderParameter(RESULT_RENDER_PARAMETER_NAME);
+ assertEquals("myPortlet-action", result);
+ }
+
+ public void testRenderRequest() throws Exception {
+ MockRenderRequest request = new MockRenderRequest();
+ MockRenderResponse response = new MockRenderResponse();
+ controller.handleRenderRequest(request, response);
+ String result = response.getContentAsString();
+ assertEquals(RENDERED_RESPONSE_CONTENT, result);
+ }
+
+ public void testActionRequestWithNoParameters() throws Exception {
+ final MockActionRequest request = new MockActionRequest();
+ final MockActionResponse response = new MockActionResponse();
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ controller.handleActionRequest(request, response);
+ }
+ }.runTest();
+ }
+
+ public void testRejectsPortletClassThatDoesNotImplementPortletInterface() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ PortletWrappingController controller = new PortletWrappingController();
+ controller.setPortletClass(String.class);
+ controller.afterPropertiesSet();
+ }
+ }.runTest();
+ }
+
+ public void testRejectsIfPortletClassIsNotSupplied() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ PortletWrappingController controller = new PortletWrappingController();
+ controller.setPortletClass(null);
+ controller.afterPropertiesSet();
+ }
+ }.runTest();
+ }
+
+ public void testDestroyingTheControllerPropagatesDestroyToWrappedPortlet() throws Exception {
+ final PortletWrappingController controller = new PortletWrappingController();
+ controller.setPortletClass(MyPortlet.class);
+ controller.afterPropertiesSet();
+ // test for destroy() call being propagated via exception being thrown :(
+ new AssertThrows(IllegalStateException.class) {
+ public void test() throws Exception {
+ controller.destroy();
+ }
+ }.runTest();
+ }
+
+ public void testPortletName() throws Exception {
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+ request.setParameter(PORTLET_NAME_ACTION_REQUEST_PARAMETER_NAME, "test");
+ controller.handleActionRequest(request, response);
+ String result = response.getRenderParameter(RESULT_RENDER_PARAMETER_NAME);
+ assertEquals("wrappedPortlet", result);
+ }
+
+ public void testDelegationToMockPortletConfigIfSoConfigured() throws Exception {
+
+ final String BEAN_NAME = "Sixpence None The Richer";
+
+ MockActionRequest request = new MockActionRequest();
+ MockActionResponse response = new MockActionResponse();
+
+ PortletWrappingController controller = new PortletWrappingController();
+ controller.setPortletClass(MyPortlet.class);
+ controller.setUseSharedPortletConfig(false);
+ controller.setBeanName(BEAN_NAME);
+ controller.afterPropertiesSet();
+
+ request.setParameter(PORTLET_NAME_ACTION_REQUEST_PARAMETER_NAME, "true");
+ controller.handleActionRequest(request, response);
+
+ String result = response.getRenderParameter(RESULT_RENDER_PARAMETER_NAME);
+ assertEquals(BEAN_NAME, result);
+ }
+
+
+ public static final class MyPortlet implements Portlet {
+
+ private PortletConfig portletConfig;
+
+
+ public void init(PortletConfig portletConfig) {
+ this.portletConfig = portletConfig;
+ }
+
+ public void processAction(ActionRequest request, ActionResponse response) throws PortletException {
+ if (request.getParameter("test") != null) {
+ response.setRenderParameter(RESULT_RENDER_PARAMETER_NAME, "myPortlet-action");
+ } else if (request.getParameter(PORTLET_NAME_ACTION_REQUEST_PARAMETER_NAME) != null) {
+ response.setRenderParameter(RESULT_RENDER_PARAMETER_NAME, getPortletConfig().getPortletName());
+ } else {
+ throw new IllegalArgumentException("no request parameters");
+ }
+ }
+
+ public void render(RenderRequest request, RenderResponse response) throws IOException {
+ response.getWriter().write(RENDERED_RESPONSE_CONTENT);
+ }
+
+ public PortletConfig getPortletConfig() {
+ return this.portletConfig;
+ }
+
+ public void destroy() {
+ throw new IllegalStateException("Being destroyed...");
+ }
+
+ }
+
+ private static final class MyApplicationContext extends StaticPortletApplicationContext {
+
+ public void refresh() throws BeansException {
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("portletClass", MyPortlet.class);
+ registerSingleton(PORTLET_WRAPPING_CONTROLLER_BEAN_NAME, PortletWrappingController.class, pvs);
+ super.refresh();
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/util/PortletUtilsTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/util/PortletUtilsTests.java
new file mode 100644
index 00000000000..7fcd2f294ee
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/portlet/util/PortletUtilsTests.java
@@ -0,0 +1,605 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.portlet.util;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.portlet.PortletContext;
+import javax.portlet.PortletRequest;
+import javax.portlet.PortletSession;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.beans.ITestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.mock.easymock.AbstractScalarMockTemplate;
+import org.springframework.mock.web.portlet.MockActionRequest;
+import org.springframework.mock.web.portlet.MockActionResponse;
+import org.springframework.mock.web.portlet.MockPortletContext;
+import org.springframework.mock.web.portlet.MockPortletRequest;
+import org.springframework.mock.web.portlet.MockPortletSession;
+import org.springframework.test.AssertThrows;
+import org.springframework.web.util.WebUtils;
+
+/**
+ * @author Rick Evans
+ */
+public final class PortletUtilsTests extends TestCase {
+
+ public void testGetTempDirWithNullPortletContext() throws Exception {
+ new AssertThrows(IllegalArgumentException.class, "null PortletContext passed as argument") {
+ public void test() throws Exception {
+ PortletUtils.getTempDir(null);
+ }
+ }.runTest();
+ }
+
+ public void testGetTempDirSunnyDay() throws Exception {
+ MockPortletContext ctx = new MockPortletContext();
+ Object expectedTempDir = new File("doesn't exist but that's ok in the context of this test");
+ ctx.setAttribute(WebUtils.TEMP_DIR_CONTEXT_ATTRIBUTE, expectedTempDir);
+ assertSame(expectedTempDir, PortletUtils.getTempDir(ctx));
+ }
+
+ public void testGetRealPathInterpretsLocationAsRelativeToWebAppRootIfPathDoesNotBeginWithALeadingSlash() throws Exception {
+ final String originalPath = "web/foo";
+ final String expectedRealPath = "/" + originalPath;
+ new AbstractScalarMockTemplate(PortletContext.class) {
+ public void setupExpectations(MockControl mockControl, Object mockObject) throws Exception {
+ PortletContext ctx = (PortletContext) mockObject;
+ ctx.getRealPath(expectedRealPath);
+ mockControl.setReturnValue(expectedRealPath);
+ }
+ public void doTest(Object mockObject) throws Exception {
+ PortletContext ctx = (PortletContext) mockObject;
+ String actualRealPath = PortletUtils.getRealPath(ctx, originalPath);
+ assertEquals(expectedRealPath, actualRealPath);
+ }
+ }.test();
+ }
+
+ public void testGetRealPathWithNullPortletContext() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ PortletUtils.getRealPath(null, "/foo");
+ }
+ }.runTest();
+ }
+
+ public void testGetRealPathWithNullPath() throws Exception {
+ new AssertThrows(NullPointerException.class) {
+ public void test() throws Exception {
+ PortletUtils.getRealPath(new MockPortletContext(), null);
+ }
+ }.runTest();
+ }
+
+ public void testGetRealPathWithPathThatCannotBeResolvedToFile() throws Exception {
+ new AssertThrows(FileNotFoundException.class) {
+ public void test() throws Exception {
+ PortletUtils.getRealPath(new MockPortletContext() {
+ public String getRealPath(String path) {
+ return null;
+ }
+ }, "/rubbish");
+ }
+ }.runTest();
+ }
+
+ public void testPassAllParametersToRenderPhase() throws Exception {
+ MockActionRequest request = new MockActionRequest();
+ request.setParameter("William", "Baskerville");
+ request.setParameter("Adso", "Melk");
+ MockActionResponse response = new MockActionResponse();
+ PortletUtils.passAllParametersToRenderPhase(request, response);
+ assertEquals("The render parameters map is obviously not being populated with the request parameters.",
+ request.getParameterMap().size(), response.getRenderParameterMap().size());
+ }
+
+ public void testGetParametersStartingWith() throws Exception {
+ final String targetPrefix = "francisan_";
+ final String badKey = "dominican_Bernard";
+ MockPortletRequest request = new MockPortletRequest();
+ request.setParameter(targetPrefix + "William", "Baskerville");
+ request.setParameter(targetPrefix + "Adso", "Melk");
+ request.setParameter(badKey, "Gui");
+ Map actualParameters = PortletUtils.getParametersStartingWith(request, targetPrefix);
+ assertNotNull("PortletUtils.getParametersStartingWith(..) must never return a null Map", actualParameters);
+ assertEquals("Obviously not finding all of the correct parameters", 2, actualParameters.size());
+ assertTrue("Obviously not finding all of the correct parameters", actualParameters.containsKey("William"));
+ assertTrue("Obviously not finding all of the correct parameters", actualParameters.containsKey("Adso"));
+ assertFalse("Obviously not finding all of the correct parameters (is returning a parameter whose name does not start with the desired prefix",
+ actualParameters.containsKey(badKey));
+ }
+
+ public void testGetParametersStartingWithUnpicksScalarParameterValues() throws Exception {
+ final String targetPrefix = "francisan_";
+ final String badKey = "dominican_Bernard";
+ MockPortletRequest request = new MockPortletRequest();
+ request.setParameter(targetPrefix + "William", "Baskerville");
+ request.setParameter(targetPrefix + "Adso", new String[]{"Melk", "Of Melk"});
+ request.setParameter(badKey, "Gui");
+ Map actualParameters = PortletUtils.getParametersStartingWith(request, targetPrefix);
+ assertNotNull("PortletUtils.getParametersStartingWith(..) must never return a null Map", actualParameters);
+ assertEquals("Obviously not finding all of the correct parameters", 2, actualParameters.size());
+ assertTrue("Obviously not finding all of the correct parameters", actualParameters.containsKey("William"));
+ assertEquals("Not picking scalar parameter value out correctly",
+ "Baskerville", actualParameters.get("William"));
+ assertTrue("Obviously not finding all of the correct parameters", actualParameters.containsKey("Adso"));
+ assertFalse("Obviously not finding all of the correct parameters (is returning a parameter whose name does not start with the desired prefix",
+ actualParameters.containsKey(badKey));
+ }
+
+ public void testGetParametersStartingWithYieldsEverythingIfTargetPrefixIsNull() throws Exception {
+ MockPortletRequest request = new MockPortletRequest();
+ request.setParameter("William", "Baskerville");
+ request.setParameter("Adso", "Melk");
+ request.setParameter("dominican_Bernard", "Gui");
+ Map actualParameters = PortletUtils.getParametersStartingWith(request, null);
+ assertNotNull("PortletUtils.getParametersStartingWith(..) must never return a null Map", actualParameters);
+ assertEquals("Obviously not finding all of the correct parameters", request.getParameterMap().size(), actualParameters.size());
+ assertTrue("Obviously not finding all of the correct parameters", actualParameters.containsKey("William"));
+ assertTrue("Obviously not finding all of the correct parameters", actualParameters.containsKey("Adso"));
+ assertTrue("Obviously not finding all of the correct parameters", actualParameters.containsKey("dominican_Bernard"));
+ }
+
+ public void testGetParametersStartingWithYieldsEverythingIfTargetPrefixIsTheEmptyString() throws Exception {
+ MockPortletRequest request = new MockPortletRequest();
+ request.setParameter("William", "Baskerville");
+ request.setParameter("Adso", "Melk");
+ request.setParameter("dominican_Bernard", "Gui");
+ Map actualParameters = PortletUtils.getParametersStartingWith(request, "");
+ assertNotNull("PortletUtils.getParametersStartingWith(..) must never return a null Map", actualParameters);
+ assertEquals("Obviously not finding all of the correct parameters", request.getParameterMap().size(), actualParameters.size());
+ assertTrue("Obviously not finding all of the correct parameters", actualParameters.containsKey("William"));
+ assertTrue("Obviously not finding all of the correct parameters", actualParameters.containsKey("Adso"));
+ assertTrue("Obviously not finding all of the correct parameters", actualParameters.containsKey("dominican_Bernard"));
+ }
+
+ public void testGetParametersStartingWithYieldsEmptyNonNullMapWhenNoParamaterExistInRequest() throws Exception {
+ MockPortletRequest request = new MockPortletRequest();
+ Map actualParameters = PortletUtils.getParametersStartingWith(request, null);
+ assertNotNull("PortletUtils.getParametersStartingWith(..) must never return a null Map", actualParameters);
+ assertEquals("Obviously finding some parameters from somewhere (incorrectly)",
+ request.getParameterMap().size(), actualParameters.size());
+ }
+
+ public void testGetSubmitParameterWithStraightNameMatch() throws Exception {
+ final String targetSubmitParameter = "William";
+ MockPortletRequest request = new MockPortletRequest();
+ request.setParameter(targetSubmitParameter, "Baskerville");
+ request.setParameter("Adso", "Melk");
+ request.setParameter("dominican_Bernard", "Gui");
+ String submitParameter = PortletUtils.getSubmitParameter(request, targetSubmitParameter);
+ assertNotNull(submitParameter);
+ assertEquals(targetSubmitParameter, submitParameter);
+ }
+
+ public void testGetSubmitParameterWithPrefixedParameterMatch() throws Exception {
+ final String bareParameterName = "William";
+ final String targetParameterName = bareParameterName + WebUtils.SUBMIT_IMAGE_SUFFIXES[0];
+ MockPortletRequest request = new MockPortletRequest();
+ request.setParameter(targetParameterName, "Baskerville");
+ request.setParameter("Adso", "Melk");
+ String submitParameter = PortletUtils.getSubmitParameter(request, bareParameterName);
+ assertNotNull(submitParameter);
+ assertEquals(targetParameterName, submitParameter);
+ }
+
+ public void testGetSubmitParameterWithNoParameterMatchJustReturnsNull() throws Exception {
+ MockPortletRequest request = new MockPortletRequest();
+ request.setParameter("Bill", "Baskerville");
+ request.setParameter("Adso", "Melk");
+ String submitParameter = PortletUtils.getSubmitParameter(request, "William");
+ assertNull(submitParameter);
+ }
+
+ public void testGetSubmitParameterWithNullRequest() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ final String targetSubmitParameter = "William";
+ MockPortletRequest request = new MockPortletRequest();
+ request.setParameter(targetSubmitParameter, "Baskerville");
+ request.setParameter("Adso", "Melk");
+ PortletUtils.getSubmitParameter(null, targetSubmitParameter);
+ }
+ }.runTest();
+ }
+
+ public void testPassAllParametersToRenderPhaseDoesNotPropagateExceptionIfRedirectAlreadySentAtTimeOfCall() throws Exception {
+ MockActionRequest request = new MockActionRequest();
+ request.setParameter("William", "Baskerville");
+ request.setParameter("Adso", "Melk");
+ MockActionResponse response = new MockActionResponse() {
+ public void setRenderParameter(String key, String[] values) {
+ throw new IllegalStateException();
+ }
+ };
+ PortletUtils.passAllParametersToRenderPhase(request, response);
+ assertEquals("The render parameters map must not be being populated with the request parameters (Action.sendRedirect(..) aleady called).",
+ 0, response.getRenderParameterMap().size());
+ }
+
+ public void testClearAllRenderParameters() throws Exception {
+ MockActionResponse response = new MockActionResponse();
+ response.setRenderParameter("William", "Baskerville");
+ response.setRenderParameter("Adso", "Melk");
+ PortletUtils.clearAllRenderParameters(response);
+ assertEquals("The render parameters map is obviously not being cleared out.",
+ 0, response.getRenderParameterMap().size());
+ }
+
+ public void testClearAllRenderParametersDoesNotPropagateExceptionIfRedirectAlreadySentAtTimeOfCall() throws Exception {
+ MockActionResponse response = new MockActionResponse() {
+ public void setRenderParameters(Map parameters) {
+ throw new IllegalStateException();
+ }
+ };
+ response.setRenderParameter("William", "Baskerville");
+ response.setRenderParameter("Adso", "Melk");
+ PortletUtils.clearAllRenderParameters(response);
+ assertEquals("The render parameters map must not be cleared if ActionResponse.sendRedirect() has been called (already).",
+ 2, response.getRenderParameterMap().size());
+ }
+
+ public void testHasSubmitParameterWithStraightNameMatch() throws Exception {
+ final String targetSubmitParameter = "William";
+ MockPortletRequest request = new MockPortletRequest();
+ request.setParameter(targetSubmitParameter, "Baskerville");
+ request.setParameter("Adso", "Melk");
+ request.setParameter("dominican_Bernard", "Gui");
+ assertTrue(PortletUtils.hasSubmitParameter(request, targetSubmitParameter));
+ }
+
+ public void testHasSubmitParameterWithPrefixedParameterMatch() throws Exception {
+ final String bareParameterName = "William";
+ final String targetParameterName = bareParameterName + WebUtils.SUBMIT_IMAGE_SUFFIXES[0];
+ MockPortletRequest request = new MockPortletRequest();
+ request.setParameter(targetParameterName, "Baskerville");
+ request.setParameter("Adso", "Melk");
+ assertTrue(PortletUtils.hasSubmitParameter(request, bareParameterName));
+ }
+
+ public void testHasSubmitParameterWithNoParameterMatch() throws Exception {
+ MockPortletRequest request = new MockPortletRequest();
+ request.setParameter("Bill", "Baskerville");
+ request.setParameter("Adso", "Melk");
+ assertFalse(PortletUtils.hasSubmitParameter(request, "William"));
+ }
+
+ public void testHasSubmitParameterWithNullRequest() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ PortletUtils.hasSubmitParameter(null, "bingo");
+ }
+ }.runTest();
+ }
+
+ public void testExposeRequestAttributesWithNullRequest() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ PortletUtils.exposeRequestAttributes(null, Collections.EMPTY_MAP);
+ }
+ }.runTest();
+ }
+
+ public void testExposeRequestAttributesWithNullAttributesMap() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ PortletUtils.exposeRequestAttributes(new MockPortletRequest(), null);
+ }
+ }.runTest();
+ }
+
+ public void testExposeRequestAttributesWithAttributesMapContainingBadKeyType() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ MockPortletRequest request = new MockPortletRequest();
+ Map attributes = new HashMap();
+ attributes.put(new Object(), "bad key type");
+ PortletUtils.exposeRequestAttributes(request, attributes);
+ }
+ }.runTest();
+ }
+
+ public void testExposeRequestAttributesSunnyDay() throws Exception {
+ MockPortletRequest request = new MockPortletRequest();
+ Map attributes = new HashMap();
+ attributes.put("ace", "Rick Hunter");
+ attributes.put("mentor", "Roy Fokker");
+ PortletUtils.exposeRequestAttributes(request, attributes);
+ assertEquals("Obviously all of the entries in the supplied attributes Map are not being copied over (exposed)",
+ attributes.size(), countElementsIn(request.getAttributeNames()));
+ assertEquals("Rick Hunter", request.getAttribute("ace"));
+ assertEquals("Roy Fokker", request.getAttribute("mentor"));
+ }
+
+ public void testExposeRequestAttributesWithEmptyAttributesMapIsAnIdempotentOperation() throws Exception {
+ MockPortletRequest request = new MockPortletRequest();
+ Map attributes = new HashMap();
+ PortletUtils.exposeRequestAttributes(request, attributes);
+ assertEquals("Obviously all of the entries in the supplied attributes Map are not being copied over (exposed)",
+ attributes.size(), countElementsIn(request.getAttributeNames()));
+ }
+
+ public void testGetOrCreateSessionAttributeWithNullSession() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ PortletUtils.getOrCreateSessionAttribute(null, "bean", TestBean.class);
+ }
+ }.runTest();
+ }
+
+ public void testGetOrCreateSessionAttributeJustReturnsAttributeIfItAlreadyExists() throws Exception {
+ MockPortletSession session = new MockPortletSession();
+ final TestBean expectedAttribute = new TestBean("Donna Tartt");
+ session.setAttribute("donna", expectedAttribute);
+ Object actualAttribute = PortletUtils.getOrCreateSessionAttribute(session, "donna", TestBean.class);
+ assertSame(expectedAttribute, actualAttribute);
+ }
+
+ public void testGetOrCreateSessionAttributeCreatesAttributeIfItDoesNotAlreadyExist() throws Exception {
+ MockPortletSession session = new MockPortletSession();
+ Object actualAttribute = PortletUtils.getOrCreateSessionAttribute(session, "bean", TestBean.class);
+ assertNotNull(actualAttribute);
+ assertEquals("Wrong type of object being instantiated", TestBean.class, actualAttribute.getClass());
+ }
+
+ public void testGetOrCreateSessionAttributeWithNoExistingAttributeAndNullClass() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ PortletUtils.getOrCreateSessionAttribute(new MockPortletSession(), "bean", null);
+ }
+ }.runTest();
+ }
+
+ public void testGetOrCreateSessionAttributeWithNoExistingAttributeAndClassThatIsAnInterfaceType() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ PortletUtils.getOrCreateSessionAttribute(new MockPortletSession(), "bean", ITestBean.class);
+ }
+ }.runTest();
+ }
+
+ public void testGetOrCreateSessionAttributeWithNoExistingAttributeAndClassWithNoPublicCtor() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ PortletUtils.getOrCreateSessionAttribute(new MockPortletSession(), "bean", NoPublicCtor.class);
+ }
+ }.runTest();
+ }
+
+ public void testGetSessionMutexWithNullSession() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ PortletUtils.getSessionMutex(null);
+ }
+ }.runTest();
+ }
+
+ public void testGetSessionMutexWithNoExistingSessionMutexDefinedJustReturnsTheSessionArgument() throws Exception {
+ MockPortletSession session = new MockPortletSession();
+ Object sessionMutex = PortletUtils.getSessionMutex(session);
+ assertNotNull("PortletUtils.getSessionMutex(..) must never return a null mutex", sessionMutex);
+ assertSame("PortletUtils.getSessionMutex(..) must return the exact same PortletSession supplied as an argument if no mutex has been bound as a Session attribute beforehand",
+ session, sessionMutex);
+ }
+
+ public void testGetSessionMutexWithExistingSessionMutexReturnsTheExistingSessionMutex() throws Exception {
+ MockPortletSession session = new MockPortletSession();
+ Object expectSessionMutex = new Object();
+ session.setAttribute(WebUtils.SESSION_MUTEX_ATTRIBUTE, expectSessionMutex);
+ Object actualSessionMutex = PortletUtils.getSessionMutex(session);
+ assertNotNull("PortletUtils.getSessionMutex(..) must never return a null mutex", actualSessionMutex);
+ assertSame("PortletUtils.getSessionMutex(..) must return the bound mutex attribute if a mutex has been bound as a Session attribute beforehand",
+ expectSessionMutex, actualSessionMutex);
+ }
+
+ public void testGetSessionAttributeWithNullPortletRequest() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ PortletUtils.getSessionAttribute(null, "foo");
+ }
+ }.runTest();
+ }
+
+ public void testGetRequiredSessionAttributeWithNullPortletRequest() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ PortletUtils.getRequiredSessionAttribute(null, "foo");
+ }
+ }.runTest();
+ }
+
+ public void testSetSessionAttributeWithNullPortletRequest() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ PortletUtils.setSessionAttribute(null, "foo", "bar");
+ }
+ }.runTest();
+ }
+
+ public void testGetSessionAttributeDoes_Not_CreateANewSession() throws Exception {
+ MockControl mock = MockControl.createControl(PortletRequest.class);
+ PortletRequest request = (PortletRequest) mock.getMock();
+ request.getPortletSession(false);
+ mock.setReturnValue(null);
+ mock.replay();
+
+ Object sessionAttribute = PortletUtils.getSessionAttribute(request, "foo");
+ assertNull("Must return null if session attribute does not exist (or if Session does not exist)", sessionAttribute);
+ mock.verify();
+ }
+
+ public void testGetSessionAttributeWithExistingSession() throws Exception {
+ MockControl mock = MockControl.createControl(PortletRequest.class);
+ PortletRequest request = (PortletRequest) mock.getMock();
+ request.getPortletSession(false);
+ MockPortletSession session = new MockPortletSession();
+ session.setAttribute("foo", "foo");
+ mock.setReturnValue(session);
+ mock.replay();
+
+ Object sessionAttribute = PortletUtils.getSessionAttribute(request, "foo");
+ assertNotNull("Must not return null if session attribute exists (and Session exists)", sessionAttribute);
+ assertEquals("foo", sessionAttribute);
+ mock.verify();
+ }
+
+ public void testGetRequiredSessionAttributeWithExistingSession() throws Exception {
+ MockControl mock = MockControl.createControl(PortletRequest.class);
+ PortletRequest request = (PortletRequest) mock.getMock();
+ request.getPortletSession(false);
+ MockPortletSession session = new MockPortletSession();
+ session.setAttribute("foo", "foo");
+ mock.setReturnValue(session);
+ mock.replay();
+
+ Object sessionAttribute = PortletUtils.getRequiredSessionAttribute(request, "foo");
+ assertNotNull("Must not return null if session attribute exists (and Session exists)", sessionAttribute);
+ assertEquals("foo", sessionAttribute);
+ mock.verify();
+ }
+
+ public void testGetRequiredSessionAttributeWithExistingSessionAndNoAttribute() throws Exception {
+ MockControl mock = MockControl.createControl(PortletRequest.class);
+ final PortletRequest request = (PortletRequest) mock.getMock();
+ request.getPortletSession(false);
+ MockPortletSession session = new MockPortletSession();
+ mock.setReturnValue(session);
+ mock.replay();
+ new AssertThrows(IllegalStateException.class) {
+ public void test() throws Exception {
+ PortletUtils.getRequiredSessionAttribute(request, "foo");
+ }
+ }.runTest();
+ mock.verify();
+ }
+
+ public void testSetSessionAttributeWithExistingSessionAndNullValue() throws Exception {
+ MockControl mockSession = MockControl.createControl(PortletSession.class);
+ PortletSession session = (PortletSession) mockSession.getMock();
+ MockControl mockRequest = MockControl.createControl(PortletRequest.class);
+ PortletRequest request = (PortletRequest) mockRequest.getMock();
+
+ request.getPortletSession(false); // must not create Session for null value...
+ mockRequest.setReturnValue(session);
+ session.removeAttribute("foo", PortletSession.APPLICATION_SCOPE);
+ mockSession.setVoidCallable();
+ mockRequest.replay();
+ mockSession.replay();
+
+ PortletUtils.setSessionAttribute(request, "foo", null, PortletSession.APPLICATION_SCOPE);
+ mockRequest.verify();
+ mockSession.verify();
+ }
+
+ public void testSetSessionAttributeWithNoExistingSessionAndNullValue() throws Exception {
+ MockControl mockRequest = MockControl.createControl(PortletRequest.class);
+ PortletRequest request = (PortletRequest) mockRequest.getMock();
+
+ request.getPortletSession(false); // must not create Session for null value...
+ mockRequest.setReturnValue(null);
+ mockRequest.replay();
+
+ PortletUtils.setSessionAttribute(request, "foo", null, PortletSession.APPLICATION_SCOPE);
+ mockRequest.verify();
+ }
+
+ public void testSetSessionAttributeWithExistingSessionAndSpecificScope() throws Exception {
+ MockControl mockSession = MockControl.createControl(PortletSession.class);
+ PortletSession session = (PortletSession) mockSession.getMock();
+ MockControl mockRequest = MockControl.createControl(PortletRequest.class);
+ PortletRequest request = (PortletRequest) mockRequest.getMock();
+
+ request.getPortletSession(); // must create Session...
+ mockRequest.setReturnValue(session);
+ session.setAttribute("foo", "foo", PortletSession.APPLICATION_SCOPE);
+ mockSession.setVoidCallable();
+ mockRequest.replay();
+ mockSession.replay();
+
+ PortletUtils.setSessionAttribute(request, "foo", "foo", PortletSession.APPLICATION_SCOPE);
+ mockRequest.verify();
+ mockSession.verify();
+ }
+
+ public void testGetSessionAttributeWithExistingSessionAndSpecificScope() throws Exception {
+ MockControl mockSession = MockControl.createControl(PortletSession.class);
+ PortletSession session = (PortletSession) mockSession.getMock();
+ MockControl mockRequest = MockControl.createControl(PortletRequest.class);
+ PortletRequest request = (PortletRequest) mockRequest.getMock();
+
+ request.getPortletSession(false);
+ mockRequest.setReturnValue(session);
+ session.getAttribute("foo", PortletSession.APPLICATION_SCOPE);
+ mockSession.setReturnValue("foo");
+ mockRequest.replay();
+ mockSession.replay();
+
+ Object sessionAttribute = PortletUtils.getSessionAttribute(request, "foo", PortletSession.APPLICATION_SCOPE);
+ assertNotNull("Must not return null if session attribute exists (and Session exists)", sessionAttribute);
+ assertEquals("foo", sessionAttribute);
+ mockRequest.verify();
+ mockSession.verify();
+ }
+
+ public void testGetSessionAttributeWithExistingSessionDefaultsToPortletScope() throws Exception {
+ MockControl mockSession = MockControl.createControl(PortletSession.class);
+ PortletSession session = (PortletSession) mockSession.getMock();
+ MockControl mockRequest = MockControl.createControl(PortletRequest.class);
+ PortletRequest request = (PortletRequest) mockRequest.getMock();
+
+ request.getPortletSession(false);
+ mockRequest.setReturnValue(session);
+ session.getAttribute("foo", PortletSession.PORTLET_SCOPE);
+ mockSession.setReturnValue("foo");
+ mockRequest.replay();
+ mockSession.replay();
+
+ Object sessionAttribute = PortletUtils.getSessionAttribute(request, "foo");
+ assertNotNull("Must not return null if session attribute exists (and Session exists)", sessionAttribute);
+ assertEquals("foo", sessionAttribute);
+ mockRequest.verify();
+ mockSession.verify();
+ }
+
+
+ private static int countElementsIn(Enumeration enumeration) {
+ int count = 0;
+ while (enumeration.hasMoreElements()) {
+ enumeration.nextElement();
+ ++count;
+ }
+ return count;
+ }
+
+
+ private static final class NoPublicCtor {
+
+ private NoPublicCtor() {
+ throw new IllegalArgumentException("Just for eclipse...");
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/ComplexWebApplicationContext.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/ComplexWebApplicationContext.java
new file mode 100644
index 00000000000..18019c3a270
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/ComplexWebApplicationContext.java
@@ -0,0 +1,461 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.servlet;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
+import org.springframework.beans.factory.support.ManagedList;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.i18n.LocaleContextHolder;
+import org.springframework.context.support.ApplicationObjectSupport;
+import org.springframework.core.Ordered;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.ServletRequestBindingException;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.request.WebRequest;
+import org.springframework.web.context.request.WebRequestInterceptor;
+import org.springframework.web.context.support.RequestHandledEvent;
+import org.springframework.web.context.support.StaticWebApplicationContext;
+import org.springframework.web.multipart.MaxUploadSizeExceededException;
+import org.springframework.web.multipart.MultipartException;
+import org.springframework.web.multipart.MultipartHttpServletRequest;
+import org.springframework.web.multipart.MultipartResolver;
+import org.springframework.web.multipart.support.AbstractMultipartHttpServletRequest;
+import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
+import org.springframework.web.servlet.handler.SimpleServletHandlerAdapter;
+import org.springframework.web.servlet.handler.SimpleServletPostProcessor;
+import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
+import org.springframework.web.servlet.handler.UserRoleAuthorizationInterceptor;
+import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
+import org.springframework.web.servlet.i18n.SessionLocaleResolver;
+import org.springframework.web.servlet.mvc.Controller;
+import org.springframework.web.servlet.mvc.ParameterizableViewController;
+import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter;
+import org.springframework.web.servlet.mvc.SimpleFormController;
+import org.springframework.web.servlet.support.RequestContextUtils;
+import org.springframework.web.servlet.theme.SessionThemeResolver;
+import org.springframework.web.servlet.theme.ThemeChangeInterceptor;
+import org.springframework.web.servlet.view.InternalResourceViewResolver;
+import org.springframework.web.servlet.view.ResourceBundleViewResolver;
+
+/**
+ * @author Juergen Hoeller
+ * @since 21.05.2003
+ */
+public class ComplexWebApplicationContext extends StaticWebApplicationContext {
+
+ public void refresh() throws BeansException {
+ registerSingleton(DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME, SessionLocaleResolver.class);
+ registerSingleton(DispatcherServlet.THEME_RESOLVER_BEAN_NAME, SessionThemeResolver.class);
+
+ LocaleChangeInterceptor interceptor1 = new LocaleChangeInterceptor();
+ LocaleChangeInterceptor interceptor2 = new LocaleChangeInterceptor();
+ interceptor2.setParamName("locale2");
+ ThemeChangeInterceptor interceptor3 = new ThemeChangeInterceptor();
+ ThemeChangeInterceptor interceptor4 = new ThemeChangeInterceptor();
+ interceptor4.setParamName("theme2");
+ UserRoleAuthorizationInterceptor interceptor5 = new UserRoleAuthorizationInterceptor();
+ interceptor5.setAuthorizedRoles(new String[] {"role1", "role2"});
+
+ List interceptors = new ArrayList();
+ interceptors.add(interceptor5);
+ interceptors.add(interceptor1);
+ interceptors.add(interceptor2);
+ interceptors.add(interceptor3);
+ interceptors.add(interceptor4);
+ interceptors.add(new MyHandlerInterceptor1());
+ interceptors.add(new MyHandlerInterceptor2());
+ interceptors.add(new MyWebRequestInterceptor());
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue(
+ "mappings", "/view.do=viewHandler\n/locale.do=localeHandler\nloc.do=anotherLocaleHandler");
+ pvs.addPropertyValue("interceptors", interceptors);
+ registerSingleton("myUrlMapping1", SimpleUrlHandlerMapping.class, pvs);
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue(
+ "mappings", "/form.do=localeHandler\n/unknown.do=unknownHandler\nservlet.do=myServlet");
+ pvs.addPropertyValue("order", "2");
+ registerSingleton("myUrlMapping2", SimpleUrlHandlerMapping.class, pvs);
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue(
+ "mappings", "/form.do=formHandler\n/head.do=headController\n" +
+ "body.do=bodyController\n/noview*=noviewController\n/noview/simple*=noviewController");
+ pvs.addPropertyValue("order", "1");
+ registerSingleton("handlerMapping", SimpleUrlHandlerMapping.class, pvs);
+
+ registerSingleton("myDummyAdapter", MyDummyAdapter.class);
+ registerSingleton("myHandlerAdapter", MyHandlerAdapter.class);
+ registerSingleton("standardHandlerAdapter", SimpleControllerHandlerAdapter.class);
+ registerSingleton("noviewController", NoViewController.class);
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("order", new Integer(0));
+ pvs.addPropertyValue("basename", "org.springframework.web.servlet.complexviews");
+ registerSingleton("viewResolver", ResourceBundleViewResolver.class, pvs);
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("suffix", ".jsp");
+ registerSingleton("viewResolver2", InternalResourceViewResolver.class, pvs);
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("commandClass", "org.springframework.beans.TestBean");
+ pvs.addPropertyValue("formView", "form");
+ registerSingleton("formHandler", SimpleFormController.class, pvs);
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("viewName", "form");
+ registerSingleton("viewHandler", ParameterizableViewController.class, pvs);
+
+ registerSingleton("localeHandler", ComplexLocaleChecker.class);
+ registerSingleton("anotherLocaleHandler", ComplexLocaleChecker.class);
+ registerSingleton("unknownHandler", Object.class);
+
+ registerSingleton("headController", HeadController.class);
+ registerSingleton("bodyController", BodyController.class);
+
+ registerSingleton("servletPostProcessor", SimpleServletPostProcessor.class);
+ registerSingleton("handlerAdapter", SimpleServletHandlerAdapter.class);
+ registerSingleton("myServlet", MyServlet.class);
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("order", "1");
+ pvs.addPropertyValue("exceptionMappings",
+ "java.lang.IllegalAccessException=failed2\n" +
+ "ServletRequestBindingException=failed3");
+ pvs.addPropertyValue("defaultErrorView", "failed0");
+ registerSingleton("exceptionResolver1", SimpleMappingExceptionResolver.class, pvs);
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("order", "0");
+ pvs.addPropertyValue("exceptionMappings", "java.lang.Exception=failed1");
+ List mappedHandlers = new ManagedList();
+ mappedHandlers.add(new RuntimeBeanReference("anotherLocaleHandler"));
+ pvs.addPropertyValue("mappedHandlers", mappedHandlers);
+ pvs.addPropertyValue("defaultStatusCode", "500");
+ pvs.addPropertyValue("defaultErrorView", "failed2");
+ registerSingleton("handlerExceptionResolver", SimpleMappingExceptionResolver.class, pvs);
+
+ registerSingleton("multipartResolver", MockMultipartResolver.class);
+ registerSingleton("testListener", TestApplicationListener.class);
+
+ addMessage("test", Locale.ENGLISH, "test message");
+ addMessage("test", Locale.CANADA, "Canadian & test message");
+
+ super.refresh();
+ }
+
+
+ public static class HeadController implements Controller {
+
+ public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
+ if ("HEAD".equals(request.getMethod())) {
+ response.setContentLength(5);
+ }
+ return null;
+ }
+ }
+
+
+ public static class BodyController implements Controller {
+
+ public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
+ response.getOutputStream().write("body".getBytes());
+ return null;
+ }
+ }
+
+
+ public static class NoViewController implements Controller {
+
+ public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
+ return new ModelAndView();
+ }
+ }
+
+
+ public static class MyServlet implements Servlet {
+
+ private ServletConfig servletConfig;
+
+ public void init(ServletConfig servletConfig) throws ServletException {
+ this.servletConfig = servletConfig;
+ }
+
+ public ServletConfig getServletConfig() {
+ return servletConfig;
+ }
+
+ public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException {
+ servletResponse.getOutputStream().write("body".getBytes());
+ }
+
+ public String getServletInfo() {
+ return null;
+ }
+
+ public void destroy() {
+ this.servletConfig = null;
+ }
+ }
+
+
+ public static interface MyHandler {
+
+ public void doSomething(HttpServletRequest request) throws ServletException, IllegalAccessException;
+
+ public long lastModified();
+ }
+
+
+ public static class MyHandlerAdapter extends ApplicationObjectSupport implements HandlerAdapter, Ordered {
+
+ public int getOrder() {
+ return 99;
+ }
+
+ public boolean supports(Object handler) {
+ return handler != null && MyHandler.class.isAssignableFrom(handler.getClass());
+ }
+
+ public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object delegate)
+ throws ServletException, IllegalAccessException {
+ ((MyHandler) delegate).doSomething(request);
+ return null;
+ }
+
+ public long getLastModified(HttpServletRequest request, Object delegate) {
+ return ((MyHandler) delegate).lastModified();
+ }
+ }
+
+
+ public static class MyDummyAdapter extends ApplicationObjectSupport implements HandlerAdapter {
+
+ public boolean supports(Object handler) {
+ return handler != null && MyHandler.class.isAssignableFrom(handler.getClass());
+ }
+
+ public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object delegate)
+ throws IOException, ServletException {
+ throw new ServletException("dummy");
+ }
+
+ public long getLastModified(HttpServletRequest request, Object delegate) {
+ return -1;
+ }
+ }
+
+
+ public static class MyHandlerInterceptor1 implements HandlerInterceptor {
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws ServletException {
+ if (request.getAttribute("test2") != null) {
+ throw new ServletException("Wrong interceptor order");
+ }
+ request.setAttribute("test1", "test1");
+ request.setAttribute("test1x", "test1x");
+ request.setAttribute("test1y", "test1y");
+ return true;
+ }
+
+ public void postHandle(
+ HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
+ throws ServletException {
+ if (request.getAttribute("test2x") != null) {
+ throw new ServletException("Wrong interceptor order");
+ }
+ if (!"test1x".equals(request.getAttribute("test1x"))) {
+ throw new ServletException("Incorrect request attribute");
+ }
+ request.removeAttribute("test1x");
+ }
+
+ public void afterCompletion(
+ HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
+ throws ServletException {
+ if (request.getAttribute("test2y") != null) {
+ throw new ServletException("Wrong interceptor order");
+ }
+ request.removeAttribute("test1y");
+ }
+ }
+
+
+ public static class MyHandlerInterceptor2 implements HandlerInterceptor {
+
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws ServletException {
+ if (request.getAttribute("test1x") == null) {
+ throw new ServletException("Wrong interceptor order");
+ }
+ if (request.getParameter("abort") != null) {
+ return false;
+ }
+ request.setAttribute("test2", "test2");
+ request.setAttribute("test2x", "test2x");
+ request.setAttribute("test2y", "test2y");
+ return true;
+ }
+
+ public void postHandle(
+ HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
+ throws ServletException {
+ if (request.getParameter("noView") != null) {
+ modelAndView.clear();
+ }
+ if (request.getAttribute("test1x") == null) {
+ throw new ServletException("Wrong interceptor order");
+ }
+ if (!"test2x".equals(request.getAttribute("test2x"))) {
+ throw new ServletException("Incorrect request attribute");
+ }
+ request.removeAttribute("test2x");
+ }
+
+ public void afterCompletion(
+ HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
+ throws Exception {
+ if (request.getAttribute("test1y") == null) {
+ throw new ServletException("Wrong interceptor order");
+ }
+ request.removeAttribute("test2y");
+ }
+ }
+
+
+ public static class MyWebRequestInterceptor implements WebRequestInterceptor {
+
+ public void preHandle(WebRequest request) throws Exception {
+ request.setAttribute("test3", "test3", WebRequest.SCOPE_REQUEST);
+ }
+
+ public void postHandle(WebRequest request, ModelMap model) throws Exception {
+ request.setAttribute("test3x", "test3x", WebRequest.SCOPE_REQUEST);
+ }
+
+ public void afterCompletion(WebRequest request, Exception ex) throws Exception {
+ request.setAttribute("test3y", "test3y", WebRequest.SCOPE_REQUEST);
+ }
+ }
+
+
+ public static class ComplexLocaleChecker implements MyHandler {
+
+ public void doSomething(HttpServletRequest request) throws ServletException, IllegalAccessException {
+ WebApplicationContext wac = RequestContextUtils.getWebApplicationContext(request);
+ if (!(wac instanceof ComplexWebApplicationContext)) {
+ throw new ServletException("Incorrect WebApplicationContext");
+ }
+ if (!(request instanceof MultipartHttpServletRequest)) {
+ throw new ServletException("Not in a MultipartHttpServletRequest");
+ }
+ if (!(RequestContextUtils.getLocaleResolver(request) instanceof SessionLocaleResolver)) {
+ throw new ServletException("Incorrect LocaleResolver");
+ }
+ if (!Locale.CANADA.equals(RequestContextUtils.getLocale(request))) {
+ throw new ServletException("Incorrect Locale");
+ }
+ if (!Locale.CANADA.equals(LocaleContextHolder.getLocale())) {
+ throw new ServletException("Incorrect Locale");
+ }
+ if (!(RequestContextUtils.getThemeResolver(request) instanceof SessionThemeResolver)) {
+ throw new ServletException("Incorrect ThemeResolver");
+ }
+ if (!"theme".equals(RequestContextUtils.getThemeResolver(request).resolveThemeName(request))) {
+ throw new ServletException("Incorrect theme name");
+ }
+ if (request.getParameter("fail") != null) {
+ throw new ModelAndViewDefiningException(new ModelAndView("failed1"));
+ }
+ if (request.getParameter("access") != null) {
+ throw new IllegalAccessException("illegal access");
+ }
+ if (request.getParameter("servlet") != null) {
+ throw new ServletRequestBindingException("servlet");
+ }
+ if (request.getParameter("exception") != null) {
+ throw new RuntimeException("servlet");
+ }
+ }
+
+ public long lastModified() {
+ return 99;
+ }
+ }
+
+
+ public static class MockMultipartResolver implements MultipartResolver {
+
+ public boolean isMultipart(HttpServletRequest request) {
+ return true;
+ }
+
+ public MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException {
+ if (request.getAttribute("fail") != null) {
+ throw new MaxUploadSizeExceededException(1000);
+ }
+ if (request instanceof MultipartHttpServletRequest) {
+ throw new IllegalStateException("Already a multipart request");
+ }
+ if (request.getAttribute("resolved") != null) {
+ throw new IllegalStateException("Already resolved");
+ }
+ request.setAttribute("resolved", Boolean.TRUE);
+ return new AbstractMultipartHttpServletRequest(request) {
+ };
+ }
+
+ public void cleanupMultipart(MultipartHttpServletRequest request) {
+ if (request.getAttribute("cleanedUp") != null) {
+ throw new IllegalStateException("Already cleaned up");
+ }
+ request.setAttribute("cleanedUp", Boolean.TRUE);
+ }
+ }
+
+
+ public static class TestApplicationListener implements ApplicationListener {
+
+ public int counter = 0;
+
+ public void onApplicationEvent(ApplicationEvent event) {
+ if (event instanceof RequestHandledEvent) {
+ this.counter++;
+ }
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/DispatcherServletTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/DispatcherServletTests.java
new file mode 100644
index 00000000000..86b3d0845a7
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/DispatcherServletTests.java
@@ -0,0 +1,866 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.web.servlet;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.PropertyValue;
+import org.springframework.beans.TestBean;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.support.DefaultMessageSourceResolvable;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockServletConfig;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.validation.BindException;
+import org.springframework.web.bind.EscapedErrors;
+import org.springframework.web.context.ServletConfigAwareBean;
+import org.springframework.web.context.ServletContextAwareBean;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.StaticWebApplicationContext;
+import org.springframework.web.multipart.MaxUploadSizeExceededException;
+import org.springframework.web.multipart.MultipartHttpServletRequest;
+import org.springframework.web.multipart.MultipartResolver;
+import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
+import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
+import org.springframework.web.servlet.mvc.BaseCommandController;
+import org.springframework.web.servlet.mvc.Controller;
+import org.springframework.web.servlet.support.RequestContext;
+import org.springframework.web.servlet.support.RequestContextUtils;
+import org.springframework.web.servlet.theme.AbstractThemeResolver;
+import org.springframework.web.servlet.view.InternalResourceViewResolver;
+import org.springframework.web.util.WebUtils;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @author Rob Harrop
+ */
+public class DispatcherServletTests extends TestCase {
+
+ private static final String URL_KNOWN_ONLY_PARENT = "/knownOnlyToParent.do";
+
+ private MockServletConfig servletConfig;
+
+ private DispatcherServlet simpleDispatcherServlet;
+
+ private DispatcherServlet complexDispatcherServlet;
+
+
+ protected void setUp() throws ServletException {
+ servletConfig = new MockServletConfig(new MockServletContext(), "simple");
+ MockServletConfig complexConfig = new MockServletConfig(servletConfig.getServletContext(), "complex");
+ complexConfig.addInitParameter("publishContext", "false");
+ complexConfig.addInitParameter("class", "notWritable");
+ complexConfig.addInitParameter("unknownParam", "someValue");
+
+ simpleDispatcherServlet = new DispatcherServlet();
+ simpleDispatcherServlet.setContextClass(SimpleWebApplicationContext.class);
+ simpleDispatcherServlet.init(servletConfig);
+
+ complexDispatcherServlet = new DispatcherServlet();
+ complexDispatcherServlet.setContextClass(ComplexWebApplicationContext.class);
+ complexDispatcherServlet.setNamespace("test");
+ complexDispatcherServlet.addRequiredProperty("publishContext");
+ complexDispatcherServlet.init(complexConfig);
+ }
+
+ private ServletContext getServletContext() {
+ return servletConfig.getServletContext();
+ }
+
+
+ public void testDispatcherServletGetServletNameDoesNotFailWithoutConfig() {
+ DispatcherServlet ds = new DispatcherServlet();
+ assertEquals(null, ds.getServletConfig());
+ assertEquals(null, ds.getServletName());
+ assertEquals(null, ds.getServletContext());
+ }
+
+ public void testConfiguredDispatcherServlets() {
+ assertTrue("Correct namespace",
+ ("simple" + FrameworkServlet.DEFAULT_NAMESPACE_SUFFIX).equals(simpleDispatcherServlet.getNamespace()));
+ assertTrue("Correct attribute",
+ (FrameworkServlet.SERVLET_CONTEXT_PREFIX + "simple").equals(simpleDispatcherServlet.getServletContextAttributeName()));
+ assertTrue("Context published",
+ simpleDispatcherServlet.getWebApplicationContext() ==
+ getServletContext().getAttribute(FrameworkServlet.SERVLET_CONTEXT_PREFIX + "simple"));
+
+ assertTrue("Correct namespace", "test".equals(complexDispatcherServlet.getNamespace()));
+ assertTrue("Correct attribute",
+ (FrameworkServlet.SERVLET_CONTEXT_PREFIX + "complex").equals(complexDispatcherServlet.getServletContextAttributeName()));
+ assertTrue("Context not published",
+ getServletContext().getAttribute(FrameworkServlet.SERVLET_CONTEXT_PREFIX + "complex") == null);
+
+ simpleDispatcherServlet.destroy();
+ complexDispatcherServlet.destroy();
+ }
+
+ public void testInvalidRequest() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/invalid.do");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ simpleDispatcherServlet.service(request, response);
+ assertTrue("Not forwarded", response.getForwardedUrl() == null);
+ assertTrue("correct error code", response.getStatus() == HttpServletResponse.SC_NOT_FOUND);
+ }
+
+ public void testRequestHandledEvent() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/locale.do");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ ComplexWebApplicationContext.TestApplicationListener listener =
+ (ComplexWebApplicationContext.TestApplicationListener)
+ complexDispatcherServlet.getWebApplicationContext().getBean("testListener");
+ assertEquals(1, listener.counter);
+ }
+
+ public void testPublishEventsOff() throws Exception {
+ complexDispatcherServlet.setPublishEvents(false);
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/locale.do");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ ComplexWebApplicationContext.TestApplicationListener listener =
+ (ComplexWebApplicationContext.TestApplicationListener)
+ complexDispatcherServlet.getWebApplicationContext().getBean("testListener");
+ assertEquals(0, listener.counter);
+ }
+
+ public void testFormRequest() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/form.do");
+ request.addPreferredLocale(Locale.CANADA);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ simpleDispatcherServlet.service(request, response);
+ assertTrue("forwarded to form", "form".equals(response.getForwardedUrl()));
+ DefaultMessageSourceResolvable resolvable = new DefaultMessageSourceResolvable(new String[] {"test"});
+ RequestContext rc = new RequestContext(request);
+
+ assertTrue("hasn't RequestContext attribute", request.getAttribute("rc") == null);
+ assertTrue("Correct WebApplicationContext",
+ RequestContextUtils.getWebApplicationContext(request) instanceof SimpleWebApplicationContext);
+ assertTrue("Correct context path", rc.getContextPath().equals(request.getContextPath()));
+ assertTrue("Correct locale", Locale.CANADA.equals(RequestContextUtils.getLocale(request)));
+ assertTrue("Correct theme",
+ AbstractThemeResolver.ORIGINAL_DEFAULT_THEME_NAME.equals(RequestContextUtils.getTheme(request).getName()));
+ assertTrue("Correct message", "Canadian & test message".equals(rc.getMessage("test")));
+
+ assertTrue("Correct WebApplicationContext", rc.getWebApplicationContext() == simpleDispatcherServlet.getWebApplicationContext());
+ assertTrue("Correct Errors", !(rc.getErrors(BaseCommandController.DEFAULT_COMMAND_NAME) instanceof EscapedErrors));
+ assertTrue("Correct Errors", !(rc.getErrors(BaseCommandController.DEFAULT_COMMAND_NAME, false) instanceof EscapedErrors));
+ assertTrue("Correct Errors", rc.getErrors(BaseCommandController.DEFAULT_COMMAND_NAME, true) instanceof EscapedErrors);
+ assertEquals("Correct message", "Canadian & test message", rc.getMessage("test"));
+ assertEquals("Correct message", "Canadian & test message", rc.getMessage("test", null, false));
+ assertEquals("Correct message", "Canadian & test message", rc.getMessage("test", null, true));
+ assertEquals("Correct message", "Canadian & test message", rc.getMessage(resolvable));
+ assertEquals("Correct message", "Canadian & test message", rc.getMessage(resolvable, false));
+ assertEquals("Correct message", "Canadian & test message", rc.getMessage(resolvable, true));
+ assertEquals("Correct message", "Canadian & test message", rc.getMessage("test", "default"));
+ assertEquals("Correct message", "default", rc.getMessage("testa", "default"));
+ assertEquals("Correct message", "default &", rc.getMessage("testa", null, "default &", true));
+ }
+
+ public void testParameterizableViewController() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/view.do");
+ request.addUserRole("role1");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertTrue("forwarded to form", "myform.jsp".equals(response.getForwardedUrl()));
+ }
+
+ public void testHandlerInterceptorSuppressesView() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/view.do");
+ request.addUserRole("role1");
+ request.addParameter("noView", "true");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertTrue("Not forwarded", response.getForwardedUrl() == null);
+ }
+
+ public void testLocaleRequest() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/locale.do");
+ request.addPreferredLocale(Locale.CANADA);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ assertEquals(98, simpleDispatcherServlet.getLastModified(request));
+ simpleDispatcherServlet.service(request, response);
+ assertTrue("Not forwarded", response.getForwardedUrl() == null);
+ }
+
+ public void testUnknownRequest() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/unknown.do");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertEquals("forwarded to failed", "failed0.jsp", response.getForwardedUrl());
+ assertTrue("Exception exposed", request.getAttribute("exception").getClass().equals(ServletException.class));
+ }
+
+ public void testAnotherFormRequest() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/form.do;jsessionid=xxx");
+ request.addPreferredLocale(Locale.CANADA);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ complexDispatcherServlet.service(request, response);
+ assertTrue("forwarded to form", "myform.jsp".equals(response.getForwardedUrl()));
+ assertTrue("has RequestContext attribute", request.getAttribute("rc") != null);
+ DefaultMessageSourceResolvable resolvable = new DefaultMessageSourceResolvable(new String[] {"test"});
+
+ RequestContext rc = (RequestContext) request.getAttribute("rc");
+ assertTrue("Not in HTML escaping mode", !rc.isDefaultHtmlEscape());
+ assertTrue("Correct WebApplicationContext", rc.getWebApplicationContext() == complexDispatcherServlet.getWebApplicationContext());
+ assertTrue("Correct context path", rc.getContextPath().equals(request.getContextPath()));
+ assertTrue("Correct locale", Locale.CANADA.equals(rc.getLocale()));
+ assertTrue("Correct Errors", !(rc.getErrors(BaseCommandController.DEFAULT_COMMAND_NAME) instanceof EscapedErrors));
+ assertTrue("Correct Errors", !(rc.getErrors(BaseCommandController.DEFAULT_COMMAND_NAME, false) instanceof EscapedErrors));
+ assertTrue("Correct Errors", rc.getErrors(BaseCommandController.DEFAULT_COMMAND_NAME, true) instanceof EscapedErrors);
+ assertEquals("Correct message", "Canadian & test message", rc.getMessage("test"));
+ assertEquals("Correct message", "Canadian & test message", rc.getMessage("test", null, false));
+ assertEquals("Correct message", "Canadian & test message", rc.getMessage("test", null, true));
+ assertEquals("Correct message", "Canadian & test message", rc.getMessage(resolvable));
+ assertEquals("Correct message", "Canadian & test message", rc.getMessage(resolvable, false));
+ assertEquals("Correct message", "Canadian & test message", rc.getMessage(resolvable, true));
+
+ rc.setDefaultHtmlEscape(true);
+ assertTrue("Is in HTML escaping mode", rc.isDefaultHtmlEscape());
+ assertTrue("Correct Errors", rc.getErrors(BaseCommandController.DEFAULT_COMMAND_NAME) instanceof EscapedErrors);
+ assertTrue("Correct Errors", !(rc.getErrors(BaseCommandController.DEFAULT_COMMAND_NAME, false) instanceof EscapedErrors));
+ assertTrue("Correct Errors", rc.getErrors(BaseCommandController.DEFAULT_COMMAND_NAME, true) instanceof EscapedErrors);
+ assertEquals("Correct message", "Canadian & test message", rc.getMessage("test"));
+ assertEquals("Correct message", "Canadian & test message", rc.getMessage("test", null, false));
+ assertEquals("Correct message", "Canadian & test message", rc.getMessage("test", null, true));
+ assertEquals("Correct message", "Canadian & test message", rc.getMessage(resolvable));
+ assertEquals("Correct message", "Canadian & test message", rc.getMessage(resolvable, false));
+ assertEquals("Correct message", "Canadian & test message", rc.getMessage(resolvable, true));
+ }
+
+ public void testAnotherLocaleRequest() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/locale.do;abc=def");
+ request.addPreferredLocale(Locale.CANADA);
+ request.addUserRole("role1");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ assertEquals(99, complexDispatcherServlet.getLastModified(request));
+ complexDispatcherServlet.service(request, response);
+
+ assertTrue("Not forwarded", response.getForwardedUrl() == null);
+ assertTrue(request.getAttribute("test1") != null);
+ assertTrue(request.getAttribute("test1x") == null);
+ assertTrue(request.getAttribute("test1y") == null);
+ assertTrue(request.getAttribute("test2") != null);
+ assertTrue(request.getAttribute("test2x") == null);
+ assertTrue(request.getAttribute("test2y") == null);
+ assertTrue(request.getAttribute("test3") != null);
+ assertTrue(request.getAttribute("test3x") != null);
+ assertTrue(request.getAttribute("test3y") != null);
+ }
+
+ public void testExistingMultipartRequest() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/locale.do;abc=def");
+ request.addPreferredLocale(Locale.CANADA);
+ request.addUserRole("role1");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ComplexWebApplicationContext.MockMultipartResolver multipartResolver =
+ (ComplexWebApplicationContext.MockMultipartResolver)
+ complexDispatcherServlet.getWebApplicationContext().getBean("multipartResolver");
+ MultipartHttpServletRequest multipartRequest = multipartResolver.resolveMultipart(request);
+ complexDispatcherServlet.service(multipartRequest, response);
+ multipartResolver.cleanupMultipart(multipartRequest);
+ assertNotNull(request.getAttribute("cleanedUp"));
+ }
+
+ public void testMultipartResolutionFailed() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/locale.do;abc=def");
+ request.addPreferredLocale(Locale.CANADA);
+ request.addUserRole("role1");
+ request.setAttribute("fail", Boolean.TRUE);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertTrue("forwarded to failed", "failed0.jsp".equals(response.getForwardedUrl()));
+ assertEquals(200, response.getStatus());
+ assertTrue("correct exception",
+ request.getAttribute(SimpleMappingExceptionResolver.DEFAULT_EXCEPTION_ATTRIBUTE) instanceof MaxUploadSizeExceededException);
+ }
+
+ public void testHandlerInterceptorAbort() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/locale.do");
+ request.addParameter("abort", "true");
+ request.addPreferredLocale(Locale.CANADA);
+ request.addUserRole("role1");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertTrue("Not forwarded", response.getForwardedUrl() == null);
+ assertTrue(request.getAttribute("test1") != null);
+ assertTrue(request.getAttribute("test1x") != null);
+ assertTrue(request.getAttribute("test1y") == null);
+ assertTrue(request.getAttribute("test2") == null);
+ assertTrue(request.getAttribute("test2x") == null);
+ assertTrue(request.getAttribute("test2y") == null);
+ }
+
+ public void testModelAndViewDefiningException() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/locale.do");
+ request.addPreferredLocale(Locale.CANADA);
+ request.addUserRole("role1");
+ request.addParameter("fail", "yes");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ try {
+ complexDispatcherServlet.service(request, response);
+ assertEquals(200, response.getStatus());
+ assertTrue("forwarded to failed", "failed1.jsp".equals(response.getForwardedUrl()));
+ }
+ catch (ServletException ex) {
+ fail("Should not have thrown ServletException: " + ex.getMessage());
+ }
+ }
+
+ public void testSimpleMappingExceptionResolverWithSpecificHandler1() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/locale.do");
+ request.addPreferredLocale(Locale.CANADA);
+ request.addUserRole("role1");
+ request.addParameter("access", "yes");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertEquals(200, response.getStatus());
+ assertEquals("forwarded to failed", "failed2.jsp", response.getForwardedUrl());
+ assertTrue("Exception exposed", request.getAttribute("exception") instanceof IllegalAccessException);
+ }
+
+ public void testSimpleMappingExceptionResolverWithSpecificHandler2() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/locale.do");
+ request.addPreferredLocale(Locale.CANADA);
+ request.addUserRole("role1");
+ request.addParameter("servlet", "yes");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertEquals(200, response.getStatus());
+ assertEquals("forwarded to failed", "failed3.jsp", response.getForwardedUrl());
+ assertTrue("Exception exposed", request.getAttribute("exception") instanceof ServletException);
+ }
+
+ public void testSimpleMappingExceptionResolverWithAllHandlers1() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/loc.do");
+ request.addPreferredLocale(Locale.CANADA);
+ request.addUserRole("role1");
+ request.addParameter("access", "yes");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertEquals(500, response.getStatus());
+ assertEquals("forwarded to failed", "failed1.jsp", response.getForwardedUrl());
+ assertTrue("Exception exposed", request.getAttribute("exception") instanceof IllegalAccessException);
+ }
+
+ public void testSimpleMappingExceptionResolverWithAllHandlers2() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/loc.do");
+ request.addPreferredLocale(Locale.CANADA);
+ request.addUserRole("role1");
+ request.addParameter("servlet", "yes");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertEquals(500, response.getStatus());
+ assertEquals("forwarded to failed", "failed1.jsp", response.getForwardedUrl());
+ assertTrue("Exception exposed", request.getAttribute("exception") instanceof ServletException);
+ }
+
+ public void testSimpleMappingExceptionResolverWithDefaultErrorView() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/locale.do");
+ request.addPreferredLocale(Locale.CANADA);
+ request.addUserRole("role1");
+ request.addParameter("exception", "yes");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertEquals(200, response.getStatus());
+ assertEquals("forwarded to failed", "failed0.jsp", response.getForwardedUrl());
+ assertTrue("Exception exposed", request.getAttribute("exception").getClass().equals(RuntimeException.class));
+ }
+
+ public void testLocaleChangeInterceptor1() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/locale.do");
+ request.addPreferredLocale(Locale.GERMAN);
+ request.addUserRole("role2");
+ request.addParameter("locale", "en");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertEquals(200, response.getStatus());
+ assertEquals("forwarded to failed", "failed0.jsp", response.getForwardedUrl());
+ assertTrue("Exception exposed", request.getAttribute("exception").getClass().equals(ServletException.class));
+ }
+
+ public void testLocaleChangeInterceptor2() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/locale.do");
+ request.addPreferredLocale(Locale.GERMAN);
+ request.addUserRole("role2");
+ request.addParameter("locale", "en");
+ request.addParameter("locale2", "en_CA");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertTrue("Not forwarded", response.getForwardedUrl() == null);
+ }
+
+ public void testThemeChangeInterceptor1() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/locale.do");
+ request.addPreferredLocale(Locale.CANADA);
+ request.addUserRole("role1");
+ request.addParameter("theme", "mytheme");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertEquals(200, response.getStatus());
+ assertEquals("forwarded to failed", "failed0.jsp", response.getForwardedUrl());
+ assertTrue("Exception exposed", request.getAttribute("exception").getClass().equals(ServletException.class));
+ }
+
+ public void testThemeChangeInterceptor2() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/locale.do");
+ request.addPreferredLocale(Locale.CANADA);
+ request.addUserRole("role1");
+ request.addParameter("theme", "mytheme");
+ request.addParameter("theme2", "theme");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ try {
+ complexDispatcherServlet.service(request, response);
+ assertTrue("Not forwarded", response.getForwardedUrl() == null);
+ }
+ catch (ServletException ex) {
+ fail("Should not have thrown ServletException: " + ex.getMessage());
+ }
+ }
+
+ public void testNotAuthorized() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/locale.do");
+ request.addPreferredLocale(Locale.CANADA);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ try {
+ complexDispatcherServlet.service(request, response);
+ assertTrue("Correct response", response.getStatus() == HttpServletResponse.SC_FORBIDDEN);
+ }
+ catch (ServletException ex) {
+ fail("Should not have thrown ServletException: " + ex.getMessage());
+ }
+ }
+
+ public void testHeadMethodWithExplicitHandling() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "HEAD", "/head.do");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertEquals(5, response.getContentLength());
+
+ request = new MockHttpServletRequest(getServletContext(), "GET", "/head.do");
+ response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertEquals("", response.getContentAsString());
+ }
+
+ public void testHeadMethodWithNoBodyResponse() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "HEAD", "/body.do");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertEquals(4, response.getContentLength());
+
+ request = new MockHttpServletRequest(getServletContext(), "GET", "/body.do");
+ response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertEquals("body", response.getContentAsString());
+ }
+
+ public void testNotDetectAllHandlerMappings() throws ServletException, IOException {
+ DispatcherServlet complexDispatcherServlet = new DispatcherServlet();
+ complexDispatcherServlet.setContextClass(ComplexWebApplicationContext.class);
+ complexDispatcherServlet.setNamespace("test");
+ complexDispatcherServlet.setDetectAllHandlerMappings(false);
+ complexDispatcherServlet.init(new MockServletConfig(getServletContext(), "complex"));
+
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/unknown.do");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertTrue(response.getStatus() == HttpServletResponse.SC_NOT_FOUND);
+ }
+
+ public void testHandlerNotMappedWithAutodetect() throws ServletException, IOException {
+ DispatcherServlet complexDispatcherServlet = new DispatcherServlet();
+ // no parent
+ complexDispatcherServlet.setContextClass(ComplexWebApplicationContext.class);
+ complexDispatcherServlet.setNamespace("test");
+ complexDispatcherServlet.init(new MockServletConfig(getServletContext(), "complex"));
+
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET",
+ URL_KNOWN_ONLY_PARENT);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertEquals(HttpServletResponse.SC_NOT_FOUND, response.getStatus());
+ }
+
+ public void testDetectHandlerMappingFromParent() throws ServletException, IOException {
+ // create a parent context that includes a mapping
+ StaticWebApplicationContext parent = new StaticWebApplicationContext();
+ parent.setServletContext(servletConfig.getServletContext());
+ parent.registerSingleton("parentHandler", ControllerFromParent.class, new MutablePropertyValues());
+
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue(new PropertyValue("mappings", URL_KNOWN_ONLY_PARENT + "=parentHandler"));
+
+ parent.registerSingleton("parentMapping", SimpleUrlHandlerMapping.class, pvs);
+ parent.refresh();
+
+ DispatcherServlet complexDispatcherServlet = new DispatcherServlet();
+ // will have parent
+ complexDispatcherServlet.setContextClass(ComplexWebApplicationContext.class);
+ complexDispatcherServlet.setNamespace("test");
+
+ ServletConfig config = new MockServletConfig(getServletContext(), "complex");
+ config.getServletContext().setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, parent);
+ complexDispatcherServlet.init(config);
+
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET",
+ URL_KNOWN_ONLY_PARENT);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+
+ assertFalse("Matched through parent controller/handler pair: not response=" + response.getStatus(),
+ response.getStatus() == HttpServletResponse.SC_NOT_FOUND);
+ }
+
+ public void testDetectAllHandlerAdapters() throws ServletException, IOException {
+ DispatcherServlet complexDispatcherServlet = new DispatcherServlet();
+ complexDispatcherServlet.setContextClass(ComplexWebApplicationContext.class);
+ complexDispatcherServlet.setNamespace("test");
+ complexDispatcherServlet.init(new MockServletConfig(getServletContext(), "complex"));
+
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/servlet.do");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertEquals("body", response.getContentAsString());
+
+ request = new MockHttpServletRequest(getServletContext(), "GET", "/form.do");
+ response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertTrue("forwarded to form", "myform.jsp".equals(response.getForwardedUrl()));
+ }
+
+ public void testNotDetectAllHandlerAdapters() throws ServletException, IOException {
+ DispatcherServlet complexDispatcherServlet = new DispatcherServlet();
+ complexDispatcherServlet.setContextClass(ComplexWebApplicationContext.class);
+ complexDispatcherServlet.setNamespace("test");
+ complexDispatcherServlet.setDetectAllHandlerAdapters(false);
+ complexDispatcherServlet.init(new MockServletConfig(getServletContext(), "complex"));
+
+ // only ServletHandlerAdapter with bean name "handlerAdapter" detected
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/servlet.do");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertEquals("body", response.getContentAsString());
+
+ // SimpleControllerHandlerAdapter not detected
+ request = new MockHttpServletRequest(getServletContext(), "GET", "/form.do");
+ response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertEquals("forwarded to failed", "failed0.jsp", response.getForwardedUrl());
+ assertTrue("Exception exposed", request.getAttribute("exception").getClass().equals(ServletException.class));
+ }
+
+ public void testNotDetectAllHandlerExceptionResolvers() throws ServletException, IOException {
+ DispatcherServlet complexDispatcherServlet = new DispatcherServlet();
+ complexDispatcherServlet.setContextClass(ComplexWebApplicationContext.class);
+ complexDispatcherServlet.setNamespace("test");
+ complexDispatcherServlet.setDetectAllHandlerExceptionResolvers(false);
+ complexDispatcherServlet.init(new MockServletConfig(getServletContext(), "complex"));
+
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/unknown.do");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ try {
+ complexDispatcherServlet.service(request, response);
+ fail("Should have thrown ServletException");
+ }
+ catch (ServletException ex) {
+ // expected
+ assertTrue(ex.getMessage().indexOf("No adapter for handler") != -1);
+ }
+ }
+
+ public void testNotDetectAllViewResolvers() throws ServletException, IOException {
+ DispatcherServlet complexDispatcherServlet = new DispatcherServlet();
+ complexDispatcherServlet.setContextClass(ComplexWebApplicationContext.class);
+ complexDispatcherServlet.setNamespace("test");
+ complexDispatcherServlet.setDetectAllViewResolvers(false);
+ complexDispatcherServlet.init(new MockServletConfig(getServletContext(), "complex"));
+
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/unknown.do");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ try {
+ complexDispatcherServlet.service(request, response);
+ fail("Should have thrown ServletException");
+ }
+ catch (ServletException ex) {
+ // expected
+ assertTrue(ex.getMessage().indexOf("failed0") != -1);
+ }
+ }
+
+ public void testCleanupAfterIncludeWithRemove() throws ServletException, IOException {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/main.do");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ request.setAttribute("test1", "value1");
+ request.setAttribute("test2", "value2");
+ WebApplicationContext wac = new StaticWebApplicationContext();
+ request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
+
+ request.setAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE, "/form.do");
+ simpleDispatcherServlet.service(request, response);
+ assertTrue("forwarded to form", "form".equals(response.getIncludedUrl()));
+
+ assertEquals("value1", request.getAttribute("test1"));
+ assertEquals("value2", request.getAttribute("test2"));
+ assertEquals(wac, request.getAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE));
+ assertNull(request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE));
+ assertNull(request.getAttribute("command"));
+ }
+
+ public void testCleanupAfterIncludeWithRestore() throws ServletException, IOException {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/main.do");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ request.setAttribute("test1", "value1");
+ request.setAttribute("test2", "value2");
+ WebApplicationContext wac = new StaticWebApplicationContext();
+ request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
+ TestBean command = new TestBean();
+ request.setAttribute("command", command);
+
+ request.setAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE, "/form.do");
+ simpleDispatcherServlet.service(request, response);
+ assertTrue("forwarded to form", "form".equals(response.getIncludedUrl()));
+
+ assertEquals("value1", request.getAttribute("test1"));
+ assertEquals("value2", request.getAttribute("test2"));
+ assertSame(wac, request.getAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE));
+ assertSame(command, request.getAttribute("command"));
+ }
+
+ public void testNoCleanupAfterInclude() throws ServletException, IOException {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/main.do");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ request.setAttribute("test1", "value1");
+ request.setAttribute("test2", "value2");
+ WebApplicationContext wac = new StaticWebApplicationContext();
+ request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
+ TestBean command = new TestBean();
+ request.setAttribute("command", command);
+
+ request.setAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE, "/form.do");
+ simpleDispatcherServlet.setCleanupAfterInclude(false);
+ simpleDispatcherServlet.service(request, response);
+ assertTrue("forwarded to form", "form".equals(response.getIncludedUrl()));
+
+ assertEquals("value1", request.getAttribute("test1"));
+ assertEquals("value2", request.getAttribute("test2"));
+ assertSame(wac, request.getAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE));
+ assertNotSame(command, request.getAttribute("command"));
+ }
+
+ public void testServletHandlerAdapter() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/servlet.do");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ complexDispatcherServlet.service(request, response);
+ assertEquals("body", response.getContentAsString());
+
+ Servlet myServlet = (Servlet) complexDispatcherServlet.getWebApplicationContext().getBean("myServlet");
+ assertEquals("complex", myServlet.getServletConfig().getServletName());
+ assertEquals(getServletContext(), myServlet.getServletConfig().getServletContext());
+ complexDispatcherServlet.destroy();
+ assertNull(myServlet.getServletConfig());
+ }
+
+ public void testThrowawayController() throws Exception {
+ SimpleWebApplicationContext.TestThrowawayController.counter = 0;
+
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/throwaway.do");
+ request.addParameter("myInt", "5");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ simpleDispatcherServlet.service(request, response);
+ assertTrue("Correct response", "view5".equals(response.getForwardedUrl()));
+ assertEquals(1, SimpleWebApplicationContext.TestThrowawayController.counter);
+
+ request = new MockHttpServletRequest(getServletContext(), "GET", "/throwaway.do");
+ request.addParameter("myInt", "5");
+ response = new MockHttpServletResponse();
+
+ simpleDispatcherServlet.service(request, response);
+ assertTrue("Correct response", "view5".equals(response.getForwardedUrl()));
+ assertEquals(2, SimpleWebApplicationContext.TestThrowawayController.counter);
+ }
+
+ public void testThrowawayControllerWithBindingFailure() throws Exception {
+ SimpleWebApplicationContext.TestThrowawayController.counter = 0;
+ MockHttpServletRequest request = new MockHttpServletRequest(getServletContext(), "GET", "/throwaway.do");
+ request.addParameter("myInt", "5x");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ try {
+ simpleDispatcherServlet.service(request, response);
+ fail("Should have thrown ServletException");
+ }
+ catch (ServletException ex) {
+ // expected
+ assertTrue(ex.getRootCause() instanceof BindException);
+ assertEquals(1, SimpleWebApplicationContext.TestThrowawayController.counter);
+ }
+ }
+
+ public void testWebApplicationContextLookup() {
+ MockServletContext servletContext = new MockServletContext();
+ MockHttpServletRequest request = new MockHttpServletRequest(servletContext, "GET", "/invalid.do");
+
+ try {
+ RequestContextUtils.getWebApplicationContext(request);
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+
+ try {
+ RequestContextUtils.getWebApplicationContext(request, servletContext);
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+
+ servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,
+ new StaticWebApplicationContext());
+ try {
+ RequestContextUtils.getWebApplicationContext(request, servletContext);
+ }
+ catch (IllegalStateException ex) {
+ fail("Should not have thrown IllegalStateException: " + ex.getMessage());
+ }
+ }
+
+ public void testWithNoView() throws Exception {
+ MockServletContext servletContext = new MockServletContext();
+ MockHttpServletRequest request = new MockHttpServletRequest(servletContext, "GET", "/noview.do");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ complexDispatcherServlet.service(request, response);
+ assertEquals("noview.jsp", response.getForwardedUrl());
+ }
+
+ public void testWithNoViewNested() throws Exception {
+ MockServletContext servletContext = new MockServletContext();
+ MockHttpServletRequest request = new MockHttpServletRequest(servletContext, "GET", "/noview/simple.do");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ complexDispatcherServlet.service(request, response);
+ assertEquals("noview/simple.jsp", response.getForwardedUrl());
+ }
+
+ public void testWithNoViewAndSamePath() throws Exception {
+ InternalResourceViewResolver vr = (InternalResourceViewResolver)
+ complexDispatcherServlet.getWebApplicationContext().getBean("viewResolver2");
+ vr.setSuffix("");
+
+ MockServletContext servletContext = new MockServletContext();
+ MockHttpServletRequest request = new MockHttpServletRequest(servletContext, "GET", "/noview");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ try {
+ complexDispatcherServlet.service(request, response);
+ fail("Should have thrown ServletException");
+ }
+ catch (ServletException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ public void testDispatcherServletRefresh() throws ServletException {
+ MockServletContext servletContext = new MockServletContext("org/springframework/web/context");
+ DispatcherServlet servlet = new DispatcherServlet();
+
+ servlet.init(new MockServletConfig(servletContext, "empty"));
+ ServletContextAwareBean contextBean = (ServletContextAwareBean)
+ servlet.getWebApplicationContext().getBean("servletContextAwareBean");
+ ServletConfigAwareBean configBean = (ServletConfigAwareBean)
+ servlet.getWebApplicationContext().getBean("servletConfigAwareBean");
+ assertSame(servletContext, contextBean.getServletContext());
+ assertSame(servlet.getServletConfig(), configBean.getServletConfig());
+ MultipartResolver multipartResolver = servlet.getMultipartResolver();
+ assertNotNull(multipartResolver);
+
+ servlet.refresh();
+
+ ServletContextAwareBean contextBean2 = (ServletContextAwareBean)
+ servlet.getWebApplicationContext().getBean("servletContextAwareBean");
+ ServletConfigAwareBean configBean2 = (ServletConfigAwareBean)
+ servlet.getWebApplicationContext().getBean("servletConfigAwareBean");
+ assertSame(servletContext, contextBean2.getServletContext());
+ assertSame(servlet.getServletConfig(), configBean2.getServletConfig());
+ assertTrue(contextBean != contextBean2);
+ assertTrue(configBean != configBean2);
+ MultipartResolver multipartResolver2 = servlet.getMultipartResolver();
+ assertTrue(multipartResolver != multipartResolver2);
+
+ servlet.destroy();
+ }
+
+ public void testDispatcherServletContextRefresh() throws ServletException {
+ MockServletContext servletContext = new MockServletContext("org/springframework/web/context");
+ DispatcherServlet servlet = new DispatcherServlet();
+
+ servlet.init(new MockServletConfig(servletContext, "empty"));
+ ServletContextAwareBean contextBean = (ServletContextAwareBean)
+ servlet.getWebApplicationContext().getBean("servletContextAwareBean");
+ ServletConfigAwareBean configBean = (ServletConfigAwareBean)
+ servlet.getWebApplicationContext().getBean("servletConfigAwareBean");
+ assertSame(servletContext, contextBean.getServletContext());
+ assertSame(servlet.getServletConfig(), configBean.getServletConfig());
+ MultipartResolver multipartResolver = servlet.getMultipartResolver();
+ assertNotNull(multipartResolver);
+
+ ((ConfigurableApplicationContext) servlet.getWebApplicationContext()).refresh();
+
+ ServletContextAwareBean contextBean2 = (ServletContextAwareBean)
+ servlet.getWebApplicationContext().getBean("servletContextAwareBean");
+ ServletConfigAwareBean configBean2 = (ServletConfigAwareBean)
+ servlet.getWebApplicationContext().getBean("servletConfigAwareBean");
+ assertSame(servletContext, contextBean2.getServletContext());
+ assertSame(servlet.getServletConfig(), configBean2.getServletConfig());
+ assertTrue(contextBean != contextBean2);
+ assertTrue(configBean != configBean2);
+ MultipartResolver multipartResolver2 = servlet.getMultipartResolver();
+ assertTrue(multipartResolver != multipartResolver2);
+
+ servlet.destroy();
+ }
+
+
+ public static class ControllerFromParent implements Controller {
+
+ public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
+ return new ModelAndView(ControllerFromParent.class.getName());
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/SimpleWebApplicationContext.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/SimpleWebApplicationContext.java
new file mode 100644
index 00000000000..8e36eb9e12e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/SimpleWebApplicationContext.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.web.servlet;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.context.support.StaticMessageSource;
+import org.springframework.ui.context.Theme;
+import org.springframework.ui.context.ThemeSource;
+import org.springframework.ui.context.support.SimpleTheme;
+import org.springframework.ui.context.support.UiApplicationContextUtils;
+import org.springframework.web.context.support.StaticWebApplicationContext;
+import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
+import org.springframework.web.servlet.mvc.Controller;
+import org.springframework.web.servlet.mvc.LastModified;
+import org.springframework.web.servlet.mvc.SimpleFormController;
+import org.springframework.web.servlet.mvc.throwaway.ThrowawayController;
+import org.springframework.web.servlet.support.RequestContextUtils;
+import org.springframework.web.servlet.theme.AbstractThemeResolver;
+import org.springframework.web.servlet.view.InternalResourceViewResolver;
+import org.springframework.web.servlet.view.XmlViewResolver;
+import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
+
+/**
+ * @author Juergen Hoeller
+ * @since 21.05.2003
+ */
+public class SimpleWebApplicationContext extends StaticWebApplicationContext {
+
+ public void refresh() throws BeansException {
+ MutablePropertyValues pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("commandClass", "org.springframework.beans.TestBean");
+ pvs.addPropertyValue("formView", "form");
+ registerSingleton("/form.do", SimpleFormController.class, pvs);
+
+ registerSingleton("/locale.do", LocaleChecker.class);
+
+ registerPrototype("/throwaway.do", TestThrowawayController.class);
+
+ addMessage("test", Locale.ENGLISH, "test message");
+ addMessage("test", Locale.CANADA, "Canadian & test message");
+ addMessage("testArgs", Locale.ENGLISH, "test {0} message {1}");
+ addMessage("testArgsFormat", Locale.ENGLISH, "test {0} message {1,number,#.##} X");
+
+ registerSingleton(UiApplicationContextUtils.THEME_SOURCE_BEAN_NAME, DummyThemeSource.class);
+
+ registerSingleton("handlerMapping", BeanNameUrlHandlerMapping.class);
+ registerSingleton("viewResolver", InternalResourceViewResolver.class);
+
+ pvs = new MutablePropertyValues();
+ pvs.addPropertyValue("location", "org/springframework/web/context/WEB-INF/sessionContext.xml");
+ registerSingleton("viewResolver2", XmlViewResolver.class, pvs);
+
+ super.refresh();
+ }
+
+
+ public static class LocaleChecker implements Controller, LastModified {
+
+ public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ if (!(RequestContextUtils.getWebApplicationContext(request) instanceof SimpleWebApplicationContext)) {
+ throw new ServletException("Incorrect WebApplicationContext");
+ }
+ if (!(RequestContextUtils.getLocaleResolver(request) instanceof AcceptHeaderLocaleResolver)) {
+ throw new ServletException("Incorrect LocaleResolver");
+ }
+ if (!Locale.CANADA.equals(RequestContextUtils.getLocale(request))) {
+ throw new ServletException("Incorrect Locale");
+ }
+ return null;
+ }
+
+ public long getLastModified(HttpServletRequest request) {
+ return 98;
+ }
+ }
+
+
+ public static class DummyThemeSource implements ThemeSource {
+
+ private StaticMessageSource messageSource;
+
+ public DummyThemeSource() {
+ this.messageSource = new StaticMessageSource();
+ this.messageSource.addMessage("themetest", Locale.ENGLISH, "theme test message");
+ this.messageSource.addMessage("themetestArgs", Locale.ENGLISH, "theme test message {0}");
+ }
+
+ public Theme getTheme(String themeName) {
+ if (AbstractThemeResolver.ORIGINAL_DEFAULT_THEME_NAME.equals(themeName)) {
+ return new SimpleTheme(AbstractThemeResolver.ORIGINAL_DEFAULT_THEME_NAME, this.messageSource);
+ }
+ else {
+ return null;
+ }
+ }
+ }
+
+
+ public static class TestThrowawayController implements ThrowawayController {
+
+ public static int counter = 0;
+
+ private int myInt;
+
+ public TestThrowawayController() {
+ counter++;
+ }
+
+ public void setMyInt(int myInt) {
+ this.myInt = myInt;
+ }
+
+ public ModelAndView execute() throws Exception {
+ return new ModelAndView("view" + this.myInt);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/complexviews.properties b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/complexviews.properties
new file mode 100644
index 00000000000..6917be21627
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/complexviews.properties
@@ -0,0 +1,3 @@
+form.(class)=org.springframework.web.servlet.view.InternalResourceView
+form.requestContextAttribute=rc
+form.url=myform.jsp
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/BeanNameUrlHandlerMappingTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/BeanNameUrlHandlerMappingTests.java
new file mode 100644
index 00000000000..e6301e7d0df
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/BeanNameUrlHandlerMappingTests.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.servlet.handler;
+
+import javax.servlet.ServletException;
+
+import junit.framework.TestCase;
+
+import org.springframework.context.support.StaticApplicationContext;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.web.context.ConfigurableWebApplicationContext;
+import org.springframework.web.context.support.XmlWebApplicationContext;
+import org.springframework.web.servlet.HandlerExecutionChain;
+import org.springframework.web.servlet.HandlerMapping;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public class BeanNameUrlHandlerMappingTests extends TestCase {
+
+ public static final String CONF = "/org/springframework/web/servlet/handler/map1.xml";
+
+ private ConfigurableWebApplicationContext wac;
+
+ public void setUp() throws Exception {
+ MockServletContext sc = new MockServletContext("");
+ wac = new XmlWebApplicationContext();
+ wac.setServletContext(sc);
+ wac.setConfigLocations(new String[] {CONF});
+ wac.refresh();
+ }
+
+ public void testRequestsWithoutHandlers() throws Exception {
+ HandlerMapping hm = (HandlerMapping) wac.getBean("handlerMapping");
+
+ MockHttpServletRequest req = new MockHttpServletRequest("GET", "/mypath/nonsense.html");
+ req.setContextPath("/myapp");
+ Object h = hm.getHandler(req);
+ assertTrue("Handler is null", h == null);
+
+ req = new MockHttpServletRequest("GET", "/foo/bar/baz.html");
+ h = hm.getHandler(req);
+ assertTrue("Handler is null", h == null);
+ }
+
+ public void testRequestsWithSubPaths() throws Exception {
+ HandlerMapping hm = (HandlerMapping) wac.getBean("handlerMapping");
+ doTestRequestsWithSubPaths(hm);
+ }
+
+ public void testRequestsWithSubPathsInParentContext() throws Exception {
+ BeanNameUrlHandlerMapping hm = new BeanNameUrlHandlerMapping();
+ hm.setDetectHandlersInAncestorContexts(true);
+ hm.setApplicationContext(new StaticApplicationContext(wac));
+ doTestRequestsWithSubPaths(hm);
+ }
+
+ private void doTestRequestsWithSubPaths(HandlerMapping hm) throws Exception {
+ Object bean = wac.getBean("godCtrl");
+
+ MockHttpServletRequest req = new MockHttpServletRequest("GET", "/mypath/welcome.html");
+ HandlerExecutionChain hec = hm.getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/myapp/mypath/welcome.html");
+ req.setContextPath("/myapp");
+ hec = hm.getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/myapp/mypath/welcome.html");
+ req.setContextPath("/myapp");
+ req.setServletPath("/mypath/welcome.html");
+ hec = hm.getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/myapp/myservlet/mypath/welcome.html");
+ req.setContextPath("/myapp");
+ req.setServletPath("/myservlet");
+ hec = hm.getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/myapp/myapp/mypath/welcome.html");
+ req.setContextPath("/myapp");
+ req.setServletPath("/myapp");
+ hec = hm.getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/mypath/show.html");
+ hec = hm.getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/mypath/bookseats.html");
+ hec = hm.getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+ }
+
+ public void testRequestsWithFullPaths() throws Exception {
+ BeanNameUrlHandlerMapping hm = new BeanNameUrlHandlerMapping();
+ hm.setAlwaysUseFullPath(true);
+ hm.setApplicationContext(wac);
+ Object bean = wac.getBean("godCtrl");
+
+ MockHttpServletRequest req = new MockHttpServletRequest("GET", "/mypath/welcome.html");
+ HandlerExecutionChain hec = hm.getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/myapp/mypath/welcome.html");
+ req.setContextPath("/myapp");
+ hec = hm.getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/mypath/welcome.html");
+ req.setContextPath("");
+ req.setServletPath("/mypath");
+ hec = hm.getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/Myapp/mypath/welcome.html");
+ req.setContextPath("/myapp");
+ req.setServletPath("/mypath");
+ hec = hm.getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/");
+ hec = hm.getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+ }
+
+ public void testAsteriskMatches() throws Exception {
+ HandlerMapping hm = (HandlerMapping) wac.getBean("handlerMapping");
+ Object bean = wac.getBean("godCtrl");
+
+ MockHttpServletRequest req = new MockHttpServletRequest("GET", "/mypath/test.html");
+ HandlerExecutionChain hec = hm.getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/mypath/testarossa");
+ hec = hm.getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/mypath/tes");
+ hec = hm.getHandler(req);
+ assertTrue("Handler is correct bean", hec == null);
+ }
+
+ public void testOverlappingMappings() throws Exception {
+ BeanNameUrlHandlerMapping hm = (BeanNameUrlHandlerMapping) wac.getBean("handlerMapping");
+ Object anotherHandler = new Object();
+ hm.registerHandler("/mypath/testaross*", anotherHandler);
+ Object bean = wac.getBean("godCtrl");
+
+ MockHttpServletRequest req = new MockHttpServletRequest("GET", "/mypath/test.html");
+ HandlerExecutionChain hec = hm.getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/mypath/testarossa");
+ hec = hm.getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == anotherHandler);
+
+ req = new MockHttpServletRequest("GET", "/mypath/tes");
+ hec = hm.getHandler(req);
+ assertTrue("Handler is correct bean", hec == null);
+ }
+
+ public void testDoubleMappings() throws ServletException {
+ BeanNameUrlHandlerMapping hm = (BeanNameUrlHandlerMapping) wac.getBean("handlerMapping");
+ try {
+ hm.registerHandler("/mypath/welcome.html", new Object());
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/PathMatchingUrlHandlerMappingTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/PathMatchingUrlHandlerMappingTests.java
new file mode 100644
index 00000000000..c0add0066d3
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/PathMatchingUrlHandlerMappingTests.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.servlet.handler;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.web.context.ConfigurableWebApplicationContext;
+import org.springframework.web.context.support.XmlWebApplicationContext;
+import org.springframework.web.servlet.HandlerExecutionChain;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.HandlerMapping;
+
+/**
+ * @author Alef Arendsen
+ * @author Juergen Hoeller
+ */
+public class PathMatchingUrlHandlerMappingTests extends TestCase {
+
+ public static final String CONF = "/org/springframework/web/servlet/handler/map3.xml";
+
+ private HandlerMapping hm;
+
+ private ConfigurableWebApplicationContext wac;
+
+ public void setUp() throws Exception {
+ MockServletContext sc = new MockServletContext("");
+ wac = new XmlWebApplicationContext();
+ wac.setServletContext(sc);
+ wac.setConfigLocations(new String[] {CONF});
+ wac.refresh();
+ hm = (HandlerMapping) wac.getBean("urlMapping");
+ }
+
+ public void testRequestsWithHandlers() throws Exception {
+ Object bean = wac.getBean("mainController");
+
+ MockHttpServletRequest req = new MockHttpServletRequest("GET", "/welcome.html");
+ HandlerExecutionChain hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/show.html");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/bookseats.html");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+ }
+
+ public void testActualPathMatching() throws Exception {
+ // there a couple of mappings defined with which we can test the
+ // path matching, let's do that...
+
+ Object bean = wac.getBean("mainController");
+ Object defaultBean = wac.getBean("starController");
+
+ // testing some normal behavior
+ MockHttpServletRequest req = new MockHttpServletRequest("GET", "/pathmatchingTest.html");
+ HandlerExecutionChain hec = getHandler(req);
+ assertTrue("Handler is null", hec != null);
+ assertTrue("Handler is correct bean", hec.getHandler() == bean);
+ assertEquals("pathmatchingTest.html", req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE));
+
+ // no match, no forward slash included
+ req = new MockHttpServletRequest("GET", "welcome.html");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == defaultBean);
+ assertEquals("welcome.html", req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE));
+
+ // testing some ????? behavior
+ req = new MockHttpServletRequest("GET", "/pathmatchingAA.html");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+ assertEquals("pathmatchingAA.html", req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE));
+
+ // testing some ????? behavior
+ req = new MockHttpServletRequest("GET", "/pathmatchingA.html");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == defaultBean);
+ assertEquals("/pathmatchingA.html", req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE));
+
+ // testing some ????? behavior
+ req = new MockHttpServletRequest("GET", "/administrator/pathmatching.html");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ // testing simple /**/behavior
+ req = new MockHttpServletRequest("GET", "/administrator/test/pathmatching.html");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ // this should not match because of the administratorT
+ req = new MockHttpServletRequest("GET", "/administratort/pathmatching.html");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == defaultBean);
+
+ // this should match because of *.jsp
+ req = new MockHttpServletRequest("GET", "/bla.jsp");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ // this as well, because there's a **/in there as well
+ req = new MockHttpServletRequest("GET", "/testing/bla.jsp");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ // should match because because exact pattern is there
+ req = new MockHttpServletRequest("GET", "/administrator/another/bla.xml");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ // should not match, because there's not .gif extension in there
+ req = new MockHttpServletRequest("GET", "/administrator/another/bla.gif");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == defaultBean);
+
+ // should match because there testlast* in there
+ req = new MockHttpServletRequest("GET", "/administrator/test/testlastbit");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ // but this not, because it's testlast and not testla
+ req = new MockHttpServletRequest("GET", "/administrator/test/testla");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == defaultBean);
+
+ req = new MockHttpServletRequest("GET", "/administrator/testing/longer/bla");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/administrator/testing/longer/test.jsp");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/administrator/testing/longer2/notmatching/notmatching");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == defaultBean);
+
+ req = new MockHttpServletRequest("GET", "/shortpattern/testing/toolong");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == defaultBean);
+
+ req = new MockHttpServletRequest("GET", "/XXpathXXmatching.html");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/pathXXmatching.html");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/XpathXXmatching.html");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == defaultBean);
+
+ req = new MockHttpServletRequest("GET", "/XXpathmatching.html");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == defaultBean);
+
+ req = new MockHttpServletRequest("GET", "/show12.html");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/show123.html");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/show1.html");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/reallyGood-test-is-this.jpeg");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/reallyGood-tst-is-this.jpeg");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == defaultBean);
+
+ req = new MockHttpServletRequest("GET", "/testing/test.jpeg");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/testing/test.jpg");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == defaultBean);
+
+ req = new MockHttpServletRequest("GET", "/anotherTest");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/stillAnotherTest");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == defaultBean);
+
+ // there outofpattern*yeah in the pattern, so this should fail
+ req = new MockHttpServletRequest("GET", "/outofpattern*ye");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == defaultBean);
+
+ req = new MockHttpServletRequest("GET", "/test't est/path'm atching.html");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == defaultBean);
+
+ req = new MockHttpServletRequest("GET", "/test%26t%20est/path%26m%20atching.html");
+ hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == defaultBean);
+ }
+
+ public void testDefaultMapping() throws Exception {
+ Object bean = wac.getBean("starController");
+ MockHttpServletRequest req = new MockHttpServletRequest("GET", "/goggog.html");
+ HandlerExecutionChain hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+ }
+
+ public void testMappingExposedInRequest() throws Exception {
+ Object bean = wac.getBean("mainController");
+ MockHttpServletRequest req = new MockHttpServletRequest("GET", "/show.html");
+ HandlerExecutionChain hec = getHandler(req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+ assertEquals("Mapping not exposed", "show.html", req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE));
+ }
+
+ private HandlerExecutionChain getHandler(MockHttpServletRequest req) throws Exception {
+ HandlerExecutionChain hec = hm.getHandler(req);
+ HandlerInterceptor[] interceptors = hec.getInterceptors();
+ if (interceptors != null) {
+ for (int i = 0; i < interceptors.length; i++) {
+ interceptors[i].preHandle(req, null, hec.getHandler());
+ }
+ }
+ return hec;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/SimpleMappingExceptionResolverTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/SimpleMappingExceptionResolverTests.java
new file mode 100644
index 00000000000..94c132a13c8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/SimpleMappingExceptionResolverTests.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.servlet.handler;
+
+import java.util.Collections;
+import java.util.Properties;
+
+import javax.servlet.http.HttpServletResponse;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.util.WebUtils;
+
+/**
+ * @author Seth Ladd
+ * @author Juergen Hoeller
+ */
+public class SimpleMappingExceptionResolverTests extends TestCase {
+
+ private SimpleMappingExceptionResolver exceptionResolver;
+ private MockHttpServletRequest request;
+ private MockHttpServletResponse response;
+ private Object handler1;
+ private Object handler2;
+ private Exception genericException;
+
+ protected void setUp() throws Exception {
+ exceptionResolver = new SimpleMappingExceptionResolver();
+ handler1 = new String();
+ handler2 = new Object();
+ request = new MockHttpServletRequest();
+ response = new MockHttpServletResponse();
+ request.setMethod("GET");
+ genericException = new Exception();
+ }
+
+ public void testSetOrder() {
+ exceptionResolver.setOrder(2);
+ assertEquals(2, exceptionResolver.getOrder());
+ }
+
+ public void testDefaultErrorView() {
+ exceptionResolver.setDefaultErrorView("default-view");
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertEquals("default-view", mav.getViewName());
+ assertEquals(genericException, mav.getModel().get(SimpleMappingExceptionResolver.DEFAULT_EXCEPTION_ATTRIBUTE));
+ }
+
+ public void testDefaultErrorViewDifferentHandler() {
+ exceptionResolver.setDefaultErrorView("default-view");
+ exceptionResolver.setMappedHandlers(Collections.singleton(handler1));
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler2, genericException);
+ assertNull(mav);
+ }
+
+ public void testDefaultErrorViewDifferentHandlerClass() {
+ exceptionResolver.setDefaultErrorView("default-view");
+ exceptionResolver.setMappedHandlerClasses(new Class[] {String.class});
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler2, genericException);
+ assertNull(mav);
+ }
+
+ public void testNullExceptionAttribute() {
+ exceptionResolver.setDefaultErrorView("default-view");
+ exceptionResolver.setExceptionAttribute(null);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertEquals("default-view", mav.getViewName());
+ assertNull(mav.getModel().get(SimpleMappingExceptionResolver.DEFAULT_EXCEPTION_ATTRIBUTE));
+ }
+
+ public void testNullExceptionMappings() {
+ exceptionResolver.setExceptionMappings(null);
+ exceptionResolver.setDefaultErrorView("default-view");
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertEquals("default-view", mav.getViewName());
+ }
+
+ public void testNoDefaultStatusCode() {
+ exceptionResolver.setDefaultErrorView("default-view");
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertEquals(HttpServletResponse.SC_OK, response.getStatus());
+ }
+
+ public void testSetDefaultStatusCode() {
+ exceptionResolver.setDefaultErrorView("default-view");
+ exceptionResolver.setDefaultStatusCode(HttpServletResponse.SC_BAD_REQUEST);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertEquals(HttpServletResponse.SC_BAD_REQUEST, response.getStatus());
+ }
+
+ public void testNoDefaultStatusCodeInInclude() {
+ exceptionResolver.setDefaultErrorView("default-view");
+ exceptionResolver.setDefaultStatusCode(HttpServletResponse.SC_BAD_REQUEST);
+ request.setAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE, "some path");
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertEquals(HttpServletResponse.SC_OK, response.getStatus());
+ }
+
+ public void testSimpleExceptionMapping() {
+ Properties props = new Properties();
+ props.setProperty("Exception", "error");
+ exceptionResolver.setWarnLogCategory("HANDLER_EXCEPTION");
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertEquals("error", mav.getViewName());
+ }
+
+ public void testExactExceptionMappingWithHandlerSpecified() {
+ Properties props = new Properties();
+ props.setProperty("java.lang.Exception", "error");
+ exceptionResolver.setMappedHandlers(Collections.singleton(handler1));
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertEquals("error", mav.getViewName());
+ }
+
+ public void testExactExceptionMappingWithHandlerClassSpecified() {
+ Properties props = new Properties();
+ props.setProperty("java.lang.Exception", "error");
+ exceptionResolver.setMappedHandlerClasses(new Class[] {String.class});
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertEquals("error", mav.getViewName());
+ }
+
+ public void testExactExceptionMappingWithHandlerInterfaceSpecified() {
+ Properties props = new Properties();
+ props.setProperty("java.lang.Exception", "error");
+ exceptionResolver.setMappedHandlerClasses(new Class[] {Comparable.class});
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertEquals("error", mav.getViewName());
+ }
+
+ public void testSimpleExceptionMappingWithHandlerSpecifiedButWrongHandler() {
+ Properties props = new Properties();
+ props.setProperty("Exception", "error");
+ exceptionResolver.setMappedHandlers(Collections.singleton(handler1));
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler2, genericException);
+ assertNull(mav);
+ }
+
+ public void testSimpleExceptionMappingWithHandlerClassSpecifiedButWrongHandler() {
+ Properties props = new Properties();
+ props.setProperty("Exception", "error");
+ exceptionResolver.setMappedHandlerClasses(new Class[] {String.class});
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler2, genericException);
+ assertNull(mav);
+ }
+
+ public void testMissingExceptionInMapping() {
+ Properties props = new Properties();
+ props.setProperty("SomeFooThrowable", "error");
+ exceptionResolver.setWarnLogCategory("HANDLER_EXCEPTION");
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertNull(mav);
+ }
+
+ public void testTwoMappings() {
+ Properties props = new Properties();
+ props.setProperty("java.lang.Exception", "error");
+ props.setProperty("AnotherException", "another-error");
+ exceptionResolver.setMappedHandlers(Collections.singleton(handler1));
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertEquals("error", mav.getViewName());
+ }
+
+ public void testTwoMappingsOneShortOneLong() {
+ Properties props = new Properties();
+ props.setProperty("Exception", "error");
+ props.setProperty("AnotherException", "another-error");
+ exceptionResolver.setMappedHandlers(Collections.singleton(handler1));
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, genericException);
+ assertEquals("error", mav.getViewName());
+ }
+
+ public void testTwoMappingsOneShortOneLongThrowOddException() {
+ Exception oddException = new SomeOddException();
+ Properties props = new Properties();
+ props.setProperty("Exception", "error");
+ props.setProperty("SomeOddException", "another-error");
+ exceptionResolver.setMappedHandlers(Collections.singleton(handler1));
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, oddException);
+ assertEquals("error", mav.getViewName());
+ }
+
+ public void testTwoMappingsThrowOddExceptionUseLongExceptionMapping() {
+ Exception oddException = new SomeOddException();
+ Properties props = new Properties();
+ props.setProperty("java.lang.Exception", "error");
+ props.setProperty("SomeOddException", "another-error");
+ exceptionResolver.setMappedHandlers(Collections.singleton(handler1));
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, oddException);
+ assertEquals("another-error", mav.getViewName());
+ }
+
+ public void testThreeMappings() {
+ Exception oddException = new AnotherOddException();
+ Properties props = new Properties();
+ props.setProperty("java.lang.Exception", "error");
+ props.setProperty("SomeOddException", "another-error");
+ props.setProperty("AnotherOddException", "another-some-error");
+ exceptionResolver.setMappedHandlers(Collections.singleton(handler1));
+ exceptionResolver.setExceptionMappings(props);
+ ModelAndView mav = exceptionResolver.resolveException(request, response, handler1, oddException);
+ assertEquals("another-some-error", mav.getViewName());
+ }
+
+
+ private static class SomeOddException extends Exception {
+
+ }
+
+
+ private static class AnotherOddException extends Exception {
+
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMappingTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMappingTests.java
new file mode 100644
index 00000000000..750da2c1884
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMappingTests.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.servlet.handler;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.FatalBeanException;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.web.context.support.XmlWebApplicationContext;
+import org.springframework.web.servlet.HandlerExecutionChain;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.HandlerMapping;
+import org.springframework.web.util.WebUtils;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public class SimpleUrlHandlerMappingTests extends TestCase {
+
+ public void testHandlerBeanNotFound() throws Exception {
+ MockServletContext sc = new MockServletContext("");
+ XmlWebApplicationContext root = new XmlWebApplicationContext();
+ root.setServletContext(sc);
+ root.setConfigLocations(new String[] {"/org/springframework/web/servlet/handler/map1.xml"});
+ root.refresh();
+ XmlWebApplicationContext wac = new XmlWebApplicationContext();
+ wac.setParent(root);
+ wac.setServletContext(sc);
+ wac.setNamespace("map2err");
+ wac.setConfigLocations(new String[] {"/org/springframework/web/servlet/handler/map2err.xml"});
+ try {
+ wac.refresh();
+ fail("Should have thrown NoSuchBeanDefinitionException");
+ }
+ catch (FatalBeanException ex) {
+ NoSuchBeanDefinitionException nestedEx = (NoSuchBeanDefinitionException) ex.getCause();
+ assertEquals("mainControlle", nestedEx.getBeanName());
+ }
+ }
+
+ public void testUrlMappingWithUrlMap() throws Exception {
+ checkMappings("urlMapping");
+ }
+
+ public void testUrlMappingWithProps() throws Exception {
+ checkMappings("urlMappingWithProps");
+ }
+
+ private void checkMappings(String beanName) throws Exception {
+ MockServletContext sc = new MockServletContext("");
+ XmlWebApplicationContext wac = new XmlWebApplicationContext();
+ wac.setServletContext(sc);
+ wac.setConfigLocations(new String[] {"/org/springframework/web/servlet/handler/map2.xml"});
+ wac.refresh();
+ Object bean = wac.getBean("mainController");
+ Object otherBean = wac.getBean("otherController");
+ Object defaultBean = wac.getBean("starController");
+ HandlerMapping hm = (HandlerMapping) wac.getBean(beanName);
+
+ MockHttpServletRequest req = new MockHttpServletRequest("GET", "/welcome.html");
+ HandlerExecutionChain hec = getHandler(hm, req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+ assertEquals("/welcome.html", req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE));
+
+ req = new MockHttpServletRequest("GET", "/welcome.x");
+ hec = getHandler(hm, req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == otherBean);
+ assertEquals("welcome.x", req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE));
+
+ req = new MockHttpServletRequest("GET", "/");
+ req.setServletPath("/welcome.html");
+ hec = getHandler(hm, req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/welcome.html");
+ req.setContextPath("/app");
+ hec = getHandler(hm, req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/show.html");
+ hec = getHandler(hm, req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/bookseats.html");
+ hec = getHandler(hm, req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/original-welcome.html");
+ req.setAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE, "/welcome.html");
+ hec = getHandler(hm, req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/original-show.html");
+ req.setAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE, "/show.html");
+ hec = getHandler(hm, req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/original-bookseats.html");
+ req.setAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE, "/bookseats.html");
+ hec = getHandler(hm, req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+
+ req = new MockHttpServletRequest("GET", "/");
+ hec = getHandler(hm, req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == bean);
+ assertEquals("/", req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE));
+
+ req = new MockHttpServletRequest("GET", "/somePath");
+ hec = getHandler(hm, req);
+ assertTrue("Handler is correct bean", hec != null && hec.getHandler() == defaultBean);
+ assertEquals("/somePath", req.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE));
+ }
+
+ private HandlerExecutionChain getHandler(HandlerMapping hm, MockHttpServletRequest req) throws Exception {
+ HandlerExecutionChain hec = hm.getHandler(req);
+ HandlerInterceptor[] interceptors = hec.getInterceptors();
+ if (interceptors != null) {
+ for (int i = 0; i < interceptors.length; i++) {
+ interceptors[i].preHandle(req, null, hec.getHandler());
+ }
+ }
+ return hec;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/map1.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/map1.xml
new file mode 100644
index 00000000000..f4b473bb158
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/map1.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/map2.properties b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/map2.properties
new file mode 100644
index 00000000000..581757cbe34
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/map2.properties
@@ -0,0 +1,7 @@
+/welcome*=otherController
+/welcome.html= mainController \n
+/show.html=mainController
+/bookseats.html=mainController
+/reservation.html=mainController
+/payment.html=mainController
+/confirmation.html=mainController
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/map2.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/map2.xml
new file mode 100644
index 00000000000..9e895318381
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/map2.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /org/springframework/web/servlet/handler/map2.properties
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/map2err.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/map2err.xml
new file mode 100644
index 00000000000..08f51cffe85
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/map2err.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /org/springframework/web/servlet/handler/map2.properties
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/map3.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/map3.xml
new file mode 100644
index 00000000000..bc7a9e49a19
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/map3.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+ true
+
+
+ welcome.html=mainController
+ /**/pathmatchingTest.html=mainController
+ /**/pathmatching??.html=mainController
+ /**/path??matching.html=mainController
+ /**/??path??matching.html=mainController
+ /**/*.jsp=mainController
+ /administrator/**/pathmatching.html=mainController
+ /administrator/**/testlast*=mainController
+ /administrator/another/bla.xml=mainController
+ /administrator/testing/longer/**/**/**/**/**=mainController
+ /administrator/testing/longer2/**/**/bla/**=mainController
+ /*test*.jpeg=mainController
+ /*/test.jpeg=mainController
+ /outofpattern*yeah=mainController
+ /anotherTest*=mainController
+ /stillAnotherTestYeah=mainController
+ /shortpattern/testing=mainController
+ /show123.html=mainController
+ /sho*=mainController
+ /bookseats.html=mainController
+ /reservation.html=mainController
+ /payment.html=mainController
+ /confirmation.html=mainController
+ /test%26t%20est/path%26m%20atching.html=mainController
+ *=starController
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/metadata/BeanPropertyController.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/metadata/BeanPropertyController.java
new file mode 100644
index 00000000000..d8b248c948e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/metadata/BeanPropertyController.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.web.servlet.handler.metadata;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.beans.ITestBean;
+import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.servlet.mvc.Controller;
+
+/**
+ * @author Juergen Hoeller
+ *
+ * @@PathMap("/constructor.cgi")
+ */
+public class BeanPropertyController implements Controller {
+
+ public ITestBean testBean;
+
+ public void setTestBean(ITestBean testBean) {
+ this.testBean = testBean;
+ }
+
+ public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
+ return new ModelAndView("test");
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/metadata/ConstructorController.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/metadata/ConstructorController.java
new file mode 100644
index 00000000000..a69fd377c73
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/metadata/ConstructorController.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.web.servlet.handler.metadata;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.beans.ITestBean;
+import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.servlet.mvc.Controller;
+
+/**
+ * @author Rod Johnson
+ *
+ * @@PathMap("/constructor.cgi")
+ */
+public class ConstructorController implements Controller {
+
+ public ITestBean testBean;
+
+ public ConstructorController(ITestBean testBean) {
+ this.testBean = testBean;
+ }
+
+ public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
+ return new ModelAndView("test");
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/metadata/PathMapHandlerMappingTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/metadata/PathMapHandlerMappingTests.java
new file mode 100644
index 00000000000..d1df6745dda
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/handler/metadata/PathMapHandlerMappingTests.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.web.servlet.handler.metadata;
+
+import java.util.HashMap;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.factory.UnsatisfiedDependencyException;
+import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.web.context.support.StaticWebApplicationContext;
+import org.springframework.web.servlet.HandlerExecutionChain;
+
+/**
+ * @author Rod Johnson
+ */
+public class PathMapHandlerMappingTests extends TestCase {
+
+ public void testSatisfiedConstructorDependency() throws Exception {
+ String path = "/Constructor.htm";
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.registerSingleton("test", TestBean.class, new MutablePropertyValues());
+
+ HashUrlMapHandlerMapping hm = new HashUrlMapHandlerMapping();
+ hm.register(ConstructorController.class, new PathMap(path));
+ hm.setApplicationContext(wac);
+
+ ConstructorController cc = (ConstructorController) wac.getBean(ConstructorController.class.getName());
+ assertSame(wac.getBean("test"), cc.testBean);
+ HandlerExecutionChain chain = hm.getHandler(new MockHttpServletRequest("GET", path));
+ assertNotNull(chain);
+ assertEquals("Path is mapped correctly based on attribute", cc, chain.getHandler());
+ chain = hm.getHandler(new MockHttpServletRequest("GET", "completeRubbish.html"));
+ assertNull("Don't know anything about this path", chain);
+ }
+
+ public void testUnsatisfiedConstructorDependency() throws Exception {
+ String path = "/Constructor.htm";
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ // No registration of a TestBean
+ //wac.registerSingleton("test", TestBean.class, new MutablePropertyValues());
+
+ HashUrlMapHandlerMapping hm = new HashUrlMapHandlerMapping();
+ hm.register(ConstructorController.class, new PathMap(path));
+ try {
+ hm.setApplicationContext(wac);
+ fail("DependencyCheck should have failed");
+ }
+ catch (UnsatisfiedDependencyException ex) {
+ // Ok
+ }
+ }
+
+ public void testSatisfiedBeanPropertyDependency() throws Exception {
+ String path = "/BeanProperty.htm";
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.registerSingleton("test", TestBean.class, new MutablePropertyValues());
+
+ HashUrlMapHandlerMapping hm = new HashUrlMapHandlerMapping();
+ hm.register(BeanPropertyController.class, new PathMap(path));
+ hm.setApplicationContext(wac);
+
+ BeanPropertyController bpc = (BeanPropertyController) wac.getBean(BeanPropertyController.class.getName());
+ assertSame(wac.getBean("test"), bpc.testBean);
+ HandlerExecutionChain chain = hm.getHandler(new MockHttpServletRequest("GET", path));
+ assertNotNull(chain);
+ assertEquals("Path is mapped correctly based on attribute", bpc, chain.getHandler());
+ chain = hm.getHandler(new MockHttpServletRequest("GET", "completeRubbish.html"));
+ assertNull("Don't know anything about this path", chain);
+ }
+
+ public void testSatisfiedBeanPropertyDependencyWithAutowireByType() throws Exception {
+ String path = "/BeanProperty.htm";
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.registerSingleton("test", TestBean.class, new MutablePropertyValues());
+
+ HashUrlMapHandlerMapping hm = new HashUrlMapHandlerMapping();
+ hm.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE);
+ hm.register(BeanPropertyController.class, new PathMap(path));
+ hm.setApplicationContext(wac);
+
+ BeanPropertyController bpc = (BeanPropertyController) wac.getBean(BeanPropertyController.class.getName());
+ assertSame(wac.getBean("test"), bpc.testBean);
+ HandlerExecutionChain chain = hm.getHandler(new MockHttpServletRequest("GET", path));
+ assertNotNull(chain);
+ assertEquals("Path is mapped correctly based on attribute", bpc, chain.getHandler());
+ chain = hm.getHandler(new MockHttpServletRequest("GET", "completeRubbish.html"));
+ assertNull("Don't know anything about this path", chain);
+ }
+
+ public void testUnsatisfiedBeanPropertyDependencyWithAutowireByType() throws Exception {
+ String path = "/BeanProperty.htm";
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+
+ HashUrlMapHandlerMapping hm = new HashUrlMapHandlerMapping();
+ hm.setAutowireModeName("AUTOWIRE_BY_TYPE");
+ hm.register(BeanPropertyController.class, new PathMap(path));
+ try {
+ hm.setApplicationContext(wac);
+ fail("DependencyCheck should have failed");
+ }
+ catch (UnsatisfiedDependencyException ex) {
+ // Ok
+ }
+ }
+
+ public void testSatisfiedBeanPropertyDependencyWithAutowireByName() throws Exception {
+ String path = "/BeanProperty.htm";
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.registerSingleton("testBean", TestBean.class, new MutablePropertyValues());
+
+ HashUrlMapHandlerMapping hm = new HashUrlMapHandlerMapping();
+ hm.setAutowireModeName("AUTOWIRE_BY_NAME");
+ hm.register(BeanPropertyController.class, new PathMap(path));
+ hm.setApplicationContext(wac);
+
+ BeanPropertyController bpc = (BeanPropertyController) wac.getBean(BeanPropertyController.class.getName());
+ assertSame(wac.getBean("testBean"), bpc.testBean);
+ HandlerExecutionChain chain = hm.getHandler(new MockHttpServletRequest("GET", path));
+ assertNotNull(chain);
+ assertEquals("Path is mapped correctly based on attribute", bpc, chain.getHandler());
+ chain = hm.getHandler(new MockHttpServletRequest("GET", "completeRubbish.html"));
+ assertNull("Don't know anything about this path", chain);
+ }
+
+ public void testUnsatisfiedBeanPropertyDependencyWithAutowireByName() throws Exception {
+ String path = "/BeanProperty.htm";
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.registerSingleton("test", TestBean.class, new MutablePropertyValues());
+
+ HashUrlMapHandlerMapping hm = new HashUrlMapHandlerMapping();
+ hm.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME);
+ hm.register(BeanPropertyController.class, new PathMap(path));
+ try {
+ hm.setApplicationContext(wac);
+ fail("DependencyCheck should have failed");
+ }
+ catch (UnsatisfiedDependencyException ex) {
+ // Ok
+ }
+ }
+
+ public void testUnsatisfiedBeanPropertyDependencyWithNoDependencyCheck() throws Exception {
+ String path = "/BeanProperty.htm";
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+
+ HashUrlMapHandlerMapping hm = new HashUrlMapHandlerMapping();
+ hm.setAutowireModeName("AUTOWIRE_BY_NAME");
+ hm.setDependencyCheck(false);
+ hm.register(BeanPropertyController.class, new PathMap(path));
+ hm.setApplicationContext(wac);
+
+ BeanPropertyController bpc = (BeanPropertyController) wac.getBean(BeanPropertyController.class.getName());
+ assertNull("Not autowired but no dependency check", bpc.testBean);
+ HandlerExecutionChain chain = hm.getHandler(new MockHttpServletRequest("GET", path));
+ assertNotNull(chain);
+ assertEquals("Path is mapped correctly based on attribute", bpc, chain.getHandler());
+ chain = hm.getHandler(new MockHttpServletRequest("GET", "completeRubbish.html"));
+ assertNull("Don't know anything about this path", chain);
+ }
+
+ public void testMultiplePaths() throws Exception {
+ String path1 = "/Constructor.htm";
+ String path2 = "path2.cgi";
+ StaticWebApplicationContext wac = new StaticWebApplicationContext();
+ wac.registerSingleton("test", TestBean.class, new MutablePropertyValues());
+
+ HashUrlMapHandlerMapping hm = new HashUrlMapHandlerMapping();
+ hm.register(ConstructorController.class, new PathMap[] { new PathMap(path1), new PathMap(path2) });
+ hm.setApplicationContext(wac);
+ ConstructorController cc = (ConstructorController) wac.getBean(ConstructorController.class.getName());
+ assertSame(wac.getBean("test"), cc.testBean);
+ HandlerExecutionChain chain = hm.getHandler(new MockHttpServletRequest("GET", path1));
+ assertNotNull(chain);
+ assertEquals("Path is mapped correctly based on attribute 1", cc, chain.getHandler());
+ chain = hm.getHandler(new MockHttpServletRequest(null, "GET", "/" + path2));
+ assertEquals("Path is mapped correctly based on attribute 2", cc, chain.getHandler());
+ chain = hm.getHandler(new MockHttpServletRequest(null, "GET", "completeRubbish.html"));
+ assertNull("Don't know anything about this path", chain);
+ }
+
+
+ private static class HashUrlMapHandlerMapping extends AbstractPathMapHandlerMapping {
+
+ private HashMap classToPathMaps = new HashMap();
+
+ public void register(Class clazz, PathMap pm) {
+ classToPathMaps.put(clazz, new PathMap[] { pm });
+ }
+
+ public void register(Class clazz, PathMap[] pms) {
+ classToPathMaps.put(clazz, pms);
+ }
+
+ protected Class[] getClassesWithPathMapAttributes() {
+ return (Class[]) classToPathMaps.keySet().toArray(new Class[classToPathMaps.size()]);
+ }
+
+ protected PathMap[] getPathMapAttributes(Class handlerClass) {
+ return (PathMap[]) classToPathMaps.get(handlerClass);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/i18n/CookieLocaleResolverTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/i18n/CookieLocaleResolverTests.java
new file mode 100644
index 00000000000..b26d68c4942
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/i18n/CookieLocaleResolverTests.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.servlet.i18n;
+
+import java.util.Locale;
+
+import javax.servlet.http.Cookie;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+
+/**
+ * @author Alef Arendsen
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ */
+public class CookieLocaleResolverTests extends TestCase {
+
+ public void testResolveLocale() {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ Cookie cookie = new Cookie("LanguageKoekje", "nl");
+ request.setCookies(new Cookie[]{cookie});
+
+ CookieLocaleResolver resolver = new CookieLocaleResolver();
+ // yup, koekje is the Dutch name for Cookie ;-)
+ resolver.setCookieName("LanguageKoekje");
+ Locale loc = resolver.resolveLocale(request);
+ assertEquals(loc.getLanguage(), "nl");
+ }
+
+ public void testSetAndResolveLocale() {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ CookieLocaleResolver resolver = new CookieLocaleResolver();
+ resolver.setLocale(request, response, new Locale("nl", ""));
+
+ Cookie cookie = response.getCookie(CookieLocaleResolver.DEFAULT_COOKIE_NAME);
+ assertNotNull(cookie);
+ assertEquals(CookieLocaleResolver.DEFAULT_COOKIE_NAME, cookie.getName());
+ assertEquals(null, cookie.getDomain());
+ assertEquals(CookieLocaleResolver.DEFAULT_COOKIE_PATH, cookie.getPath());
+ assertEquals(CookieLocaleResolver.DEFAULT_COOKIE_MAX_AGE, cookie.getMaxAge());
+ assertFalse(cookie.getSecure());
+
+ request = new MockHttpServletRequest();
+ request.setCookies(new Cookie[]{cookie});
+
+ resolver = new CookieLocaleResolver();
+ Locale loc = resolver.resolveLocale(request);
+ assertEquals(loc.getLanguage(), "nl");
+ }
+
+ public void testCustomCookie() {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ CookieLocaleResolver resolver = new CookieLocaleResolver();
+ resolver.setCookieName("LanguageKoek");
+ resolver.setCookieDomain(".springframework.org");
+ resolver.setCookiePath("/mypath");
+ resolver.setCookieMaxAge(10000);
+ resolver.setCookieSecure(true);
+ resolver.setLocale(request, response, new Locale("nl", ""));
+
+ Cookie cookie = response.getCookie("LanguageKoek");
+ assertNotNull(cookie);
+ assertEquals("LanguageKoek", cookie.getName());
+ assertEquals(".springframework.org", cookie.getDomain());
+ assertEquals("/mypath", cookie.getPath());
+ assertEquals(10000, cookie.getMaxAge());
+ assertTrue(cookie.getSecure());
+
+ request = new MockHttpServletRequest();
+ request.setCookies(new Cookie[]{cookie});
+
+ resolver = new CookieLocaleResolver();
+ resolver.setCookieName("LanguageKoek");
+ Locale loc = resolver.resolveLocale(request);
+ assertEquals(loc.getLanguage(), "nl");
+ }
+
+ public void testResolveLocaleWithoutCookie() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addPreferredLocale(Locale.TAIWAN);
+
+ CookieLocaleResolver resolver = new CookieLocaleResolver();
+
+ Locale locale = resolver.resolveLocale(request);
+ assertEquals(request.getLocale(), locale);
+ }
+
+ public void testResolveLocaleWithoutCookieAndDefaultLocale() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addPreferredLocale(Locale.TAIWAN);
+
+ CookieLocaleResolver resolver = new CookieLocaleResolver();
+ resolver.setDefaultLocale(Locale.GERMAN);
+
+ Locale locale = resolver.resolveLocale(request);
+ assertEquals(Locale.GERMAN, locale);
+ }
+
+ public void testResolveLocaleWithCookieWithoutLocale() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addPreferredLocale(Locale.TAIWAN);
+ Cookie cookie = new Cookie(CookieLocaleResolver.LOCALE_REQUEST_ATTRIBUTE_NAME, "");
+ request.setCookies(new Cookie[]{cookie});
+
+ CookieLocaleResolver resolver = new CookieLocaleResolver();
+
+ Locale locale = resolver.resolveLocale(request);
+ assertEquals(request.getLocale(), locale);
+ }
+
+ public void testSetLocaleToNullLocale() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addPreferredLocale(Locale.TAIWAN);
+ Cookie cookie = new Cookie(CookieLocaleResolver.LOCALE_REQUEST_ATTRIBUTE_NAME, Locale.UK.toString());
+ request.setCookies(new Cookie[]{cookie});
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ CookieLocaleResolver resolver = new CookieLocaleResolver();
+ resolver.setLocale(request, response, null);
+ Locale locale = (Locale) request.getAttribute(CookieLocaleResolver.LOCALE_REQUEST_ATTRIBUTE_NAME);
+ assertEquals(Locale.TAIWAN, locale);
+
+ Cookie[] cookies = response.getCookies();
+ assertEquals(1, cookies.length);
+ Cookie localeCookie = cookies[0];
+ assertEquals(CookieLocaleResolver.LOCALE_REQUEST_ATTRIBUTE_NAME, localeCookie.getName());
+ assertEquals("", localeCookie.getValue());
+ }
+
+ public void testSetLocaleToNullLocaleWithDefault() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addPreferredLocale(Locale.TAIWAN);
+ Cookie cookie = new Cookie(CookieLocaleResolver.LOCALE_REQUEST_ATTRIBUTE_NAME, Locale.UK.toString());
+ request.setCookies(new Cookie[]{cookie});
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ CookieLocaleResolver resolver = new CookieLocaleResolver();
+ resolver.setDefaultLocale(Locale.CANADA_FRENCH);
+ resolver.setLocale(request, response, null);
+ Locale locale = (Locale) request.getAttribute(CookieLocaleResolver.LOCALE_REQUEST_ATTRIBUTE_NAME);
+ assertEquals(Locale.CANADA_FRENCH, locale);
+
+ Cookie[] cookies = response.getCookies();
+ assertEquals(1, cookies.length);
+ Cookie localeCookie = cookies[0];
+ assertEquals(CookieLocaleResolver.LOCALE_REQUEST_ATTRIBUTE_NAME, localeCookie.getName());
+ assertEquals("", localeCookie.getValue());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/i18n/LocaleResolverTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/i18n/LocaleResolverTests.java
new file mode 100644
index 00000000000..86eb821f9d3
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/i18n/LocaleResolverTests.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.web.servlet.i18n;
+
+import java.util.Locale;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.web.servlet.LocaleResolver;
+
+/**
+ * @author Juergen Hoeller
+ * @since 20.03.2003
+ */
+public class LocaleResolverTests extends TestCase {
+
+ private void internalTest(LocaleResolver localeResolver, boolean shouldSet) {
+ // create mocks
+ MockServletContext context = new MockServletContext();
+ MockHttpServletRequest request = new MockHttpServletRequest(context);
+ request.addPreferredLocale(Locale.UK);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ // check original locale
+ Locale locale = localeResolver.resolveLocale(request);
+ assertEquals(locale, Locale.UK);
+ // set new locale
+ try {
+ localeResolver.setLocale(request, response, Locale.GERMANY);
+ if (!shouldSet)
+ fail("should not be able to set Locale");
+ // check new locale
+ locale = localeResolver.resolveLocale(request);
+ assertEquals(locale, Locale.GERMANY);
+ }
+ catch (UnsupportedOperationException ex) {
+ if (shouldSet)
+ fail("should be able to set Locale");
+ }
+ }
+
+ public void testAcceptHeaderLocaleResolver() {
+ internalTest(new AcceptHeaderLocaleResolver(), false);
+ }
+
+ public void testCookieLocaleResolver() {
+ internalTest(new CookieLocaleResolver(), true);
+ }
+
+ public void testSessionLocaleResolver() {
+ internalTest(new SessionLocaleResolver(), true);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/i18n/SessionLocaleResolverTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/i18n/SessionLocaleResolverTests.java
new file mode 100644
index 00000000000..84f9caa98df
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/i18n/SessionLocaleResolverTests.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.servlet.i18n;
+
+import java.util.Locale;
+
+import javax.servlet.http.HttpSession;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class SessionLocaleResolverTests extends TestCase {
+
+ public void testResolveLocale() {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.getSession().setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, Locale.GERMAN);
+
+ SessionLocaleResolver resolver = new SessionLocaleResolver();
+ assertEquals(Locale.GERMAN, resolver.resolveLocale(request));
+ }
+
+ public void testSetAndResolveLocale() {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ SessionLocaleResolver resolver = new SessionLocaleResolver();
+ resolver.setLocale(request, response, Locale.GERMAN);
+ assertEquals(Locale.GERMAN, resolver.resolveLocale(request));
+
+ HttpSession session = request.getSession();
+ request = new MockHttpServletRequest();
+ request.setSession(session);
+ resolver = new SessionLocaleResolver();
+
+ assertEquals(Locale.GERMAN, resolver.resolveLocale(request));
+ }
+
+ public void testResolveLocaleWithoutSession() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addPreferredLocale(Locale.TAIWAN);
+
+ SessionLocaleResolver resolver = new SessionLocaleResolver();
+
+ assertEquals(request.getLocale(), resolver.resolveLocale(request));
+ }
+
+ public void testResolveLocaleWithoutSessionAndDefaultLocale() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addPreferredLocale(Locale.TAIWAN);
+
+ SessionLocaleResolver resolver = new SessionLocaleResolver();
+ resolver.setDefaultLocale(Locale.GERMAN);
+
+ assertEquals(Locale.GERMAN, resolver.resolveLocale(request));
+ }
+
+ public void testSetLocaleToNullLocale() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addPreferredLocale(Locale.TAIWAN);
+ request.getSession().setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, Locale.GERMAN);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ SessionLocaleResolver resolver = new SessionLocaleResolver();
+ resolver.setLocale(request, response, null);
+ Locale locale = (Locale) request.getSession().getAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME);
+ assertNull(locale);
+
+ HttpSession session = request.getSession();
+ request = new MockHttpServletRequest();
+ request.addPreferredLocale(Locale.TAIWAN);
+ request.setSession(session);
+ resolver = new SessionLocaleResolver();
+ assertEquals(Locale.TAIWAN, resolver.resolveLocale(request));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/CancellableFormControllerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/CancellableFormControllerTests.java
new file mode 100644
index 00000000000..804d13489e5
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/CancellableFormControllerTests.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.servlet.mvc;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.validation.BindException;
+import org.springframework.validation.Errors;
+import org.springframework.validation.Validator;
+import org.springframework.web.servlet.ModelAndView;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class CancellableFormControllerTests extends TestCase {
+
+ public void testFormViewRequest() throws Exception {
+ String formView = "theFormView";
+
+ TestController ctl = new TestController();
+ ctl.setFormView(formView);
+ ctl.setBindOnNewForm(true);
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ String name = "Rob Harrop";
+ int age = 23;
+
+ request.setMethod("GET");
+ request.addParameter("name", name);
+ request.addParameter("age", "" + age);
+
+ ModelAndView mv = ctl.handleRequest(request, response);
+
+ assertEquals("Incorrect view name", formView, mv.getViewName());
+
+ TestBean command = (TestBean) mv.getModel().get(ctl.getCommandName());
+
+ testCommandIsBound(command, name, age);
+ }
+
+ public void testFormSubmissionRequestWithoutCancel() throws Exception {
+ String successView = "successView";
+
+ TestController ctl = new TestController();
+ ctl.setSuccessView(successView);
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ String name = "Rob Harrop";
+ int age = 23;
+
+ request.setMethod("POST");
+ request.addParameter("name", name);
+ request.addParameter("age", "" + age);
+
+ ModelAndView mv = ctl.handleRequest(request, response);
+
+ assertEquals("Incorrect view name", successView, mv.getViewName());
+
+ TestBean command = (TestBean) mv.getModel().get(ctl.getCommandName());
+
+ testCommandIsBound(command, name, age);
+ }
+
+ public void testFormSubmissionWithErrors() throws Exception {
+ String successView = "successView";
+ String formView = "formView";
+
+ TestController ctl = new TestController();
+ ctl.setSuccessView(successView);
+ ctl.setFormView(formView);
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ request.setMethod("POST");
+ request.addParameter("name", "Rob Harrop");
+ request.addParameter("age", "xxx23");
+
+ ModelAndView mv = ctl.handleRequest(request, response);
+ assertEquals("Incorrect view name", formView, mv.getViewName());
+
+ Errors errors = (Errors) mv.getModel().get(BindException.MODEL_KEY_PREFIX + ctl.getCommandName());
+ assertNotNull("No errors", errors);
+ assertEquals(1, errors.getErrorCount());
+ }
+
+ public void testFormSubmissionWithValidationError() throws Exception {
+ String successView = "successView";
+ String formView = "formView";
+
+ TestController ctl = new TestController();
+ ctl.setSuccessView(successView);
+ ctl.setFormView(formView);
+ TestValidator val = new TestValidator();
+ ctl.setValidator(val);
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ request.setMethod("POST");
+ request.addParameter("name", "Rob Harrop");
+ request.addParameter("age", "23");
+
+ ModelAndView mv = ctl.handleRequest(request, response);
+ assertEquals("Incorrect view name", formView, mv.getViewName());
+
+ Errors errors = (Errors) mv.getModel().get(BindException.MODEL_KEY_PREFIX + ctl.getCommandName());
+ assertNotNull("No errors", errors);
+ assertEquals(1, errors.getErrorCount());
+ assertTrue(val.invoked);
+ }
+
+ public void testCancelSubmission() throws Exception {
+ String cancelView = "cancelView";
+ String cancelParameterKey = "cancelRequest";
+
+ TestController ctl = new TestController();
+ ctl.setCancelParamKey(cancelParameterKey);
+ ctl.setCancelView(cancelView);
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ request.setMethod("POST");
+ request.addParameter("cancelRequest", "true");
+
+ ModelAndView mv = ctl.handleRequest(request, response);
+ assertEquals("Incorrect view name", cancelView, mv.getViewName());
+ }
+
+ public void testCancelSubmissionWithValidationError() throws Exception {
+ String cancelView = "cancelView";
+ String cancelParameterKey = "cancelRequest";
+
+ TestController ctl = new TestController();
+ ctl.setCancelParamKey(cancelParameterKey);
+ ctl.setCancelView(cancelView);
+ TestValidator val = new TestValidator();
+ ctl.setValidator(val);
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ request.setMethod("POST");
+ request.addParameter("name", "Rob Harrop");
+ request.addParameter("age", "23");
+ request.addParameter("cancelRequest", "true");
+
+ ModelAndView mv = ctl.handleRequest(request, response);
+ assertEquals("Incorrect view name", cancelView, mv.getViewName());
+
+ assertFalse(val.invoked);
+ }
+
+ public void testCancelSubmissionWithCustomModelParams() throws Exception {
+ String cancelView = "cancelView";
+ String cancelParameterKey = "cancelRequest";
+ final String reason = "Because I wanted to";
+
+ TestController ctl = new TestController() {
+ protected ModelAndView onCancel(HttpServletRequest request, HttpServletResponse response, Object command) {
+ return new ModelAndView(getCancelView(), "reason", reason);
+ }
+ };
+
+ ctl.setCancelParamKey(cancelParameterKey);
+ ctl.setCancelView(cancelView);
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ request.setMethod("POST");
+ request.addParameter("cancelRequest", "true");
+
+ ModelAndView mv = ctl.handleRequest(request, response);
+ assertEquals("Incorrect view name", cancelView, mv.getViewName());
+ assertEquals("Model parameter reason not correct", reason, mv.getModel().get("reason"));
+ }
+
+ private void testCommandIsBound(TestBean command, String name, int age) {
+ assertNotNull("Command bean should not be null", command);
+ assertEquals("Name not bound", name, command.getName());
+ assertEquals("Age not bound", age, command.getAge());
+ }
+
+
+ private static class TestController extends CancellableFormController {
+
+ public TestController() {
+ setCommandClass(TestBean.class);
+ }
+ }
+
+
+ private static class TestValidator implements Validator {
+
+ private boolean invoked = false;
+
+ public boolean supports(Class clazz) {
+ return TestBean.class.isAssignableFrom(clazz);
+ }
+ public void validate(Object target, Errors errors) {
+ this.invoked = true;
+ TestBean tb = (TestBean) target;
+ if (tb.getAge() < 25) {
+ errors.rejectValue("age", "TOO_YOUNG");
+ }
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/CommandControllerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/CommandControllerTests.java
new file mode 100644
index 00000000000..1b757c9314d
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/CommandControllerTests.java
@@ -0,0 +1,510 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.web.servlet.mvc;
+
+import java.text.DateFormat;
+import java.text.NumberFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+import org.springframework.beans.propertyeditors.CustomDateEditor;
+import org.springframework.beans.propertyeditors.CustomNumberEditor;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockHttpSession;
+import org.springframework.validation.BindException;
+import org.springframework.validation.Errors;
+import org.springframework.validation.FieldError;
+import org.springframework.web.bind.ServletRequestDataBinder;
+import org.springframework.web.servlet.ModelAndView;
+
+/**
+ * @author Rod Johnson
+ */
+public class CommandControllerTests extends TestCase {
+
+ public void testNoArgsNoErrors() throws Exception {
+ TestController mc = new TestController();
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/welcome.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ assertTrue("returned correct view name", mv.getViewName().equals(request.getServletPath()));
+ TestBean person = (TestBean) mv.getModel().get("command");
+ Errors errors = (Errors) mv.getModel().get("errors");
+ assertTrue("command and errors non null", person != null && errors != null);
+ assertTrue("no errors", !errors.hasErrors());
+ assertTrue("Correct caching", response.getHeader("Cache-Control") == null);
+ assertTrue("Correct expires header", response.getHeader("Expires") == null);
+ }
+
+ public void test2ArgsNoErrors() throws Exception {
+ TestController mc = new TestController();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/ok.html");
+ String name = "Rod";
+ int age = 32;
+ request.addParameter("name", name);
+ request.addParameter("age", "" + age);
+ HttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ assertTrue("returned correct view name", mv.getViewName().equals(request.getServletPath()));
+ TestBean person = (TestBean) mv.getModel().get("command");
+ Errors errors = (Errors) mv.getModel().get("errors");
+ assertTrue("command and errors non null", person != null && errors != null);
+ assertTrue("no errors", !errors.hasErrors());
+ assertTrue("command name bound ok", person.getName().equals(name));
+ assertTrue("command age bound ok", person.getAge() == age);
+ }
+
+ public void test2Args1Mismatch() throws Exception {
+ TestController mc = new TestController();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/ok.html");
+ String name = "Rod";
+ String age = "32x";
+ request.addParameter("name", name);
+ request.addParameter("age", age);
+ HttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ assertTrue("returned correct view name", mv.getViewName().equals(request.getServletPath()));
+ TestBean person = (TestBean) mv.getModel().get("command");
+ Errors errors = (Errors) mv.getModel().get("errors");
+ assertTrue("command and errors non null", person != null && errors != null);
+ assertTrue("has 1 errors", errors.getErrorCount() == 1);
+ assertTrue("command name bound ok", person.getName().equals(name));
+ assertTrue("command age default", person.getAge() == new TestBean().getAge());
+ assertTrue("has error on field age", errors.hasFieldErrors("age"));
+ FieldError fe = errors.getFieldError("age");
+ assertTrue("Saved invalid value", fe.getRejectedValue().equals(age));
+ assertTrue("Correct field", fe.getField().equals("age"));
+ }
+
+ public void testSupportedMethods() throws Exception {
+ TestController mc = new TestController();
+ mc.setSupportedMethods(new String[] {"POST"});
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/ok.html");
+ HttpServletResponse response = new MockHttpServletResponse();
+ try {
+ mc.handleRequest(request, response);
+ fail("Should have thrown ServletException");
+ }
+ catch (ServletException ex) {
+ // expected
+ }
+ }
+
+ public void testRequireSessionWithoutSession() throws Exception {
+ TestController mc = new TestController();
+ mc.setRequireSession(true);
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/ok.html");
+ HttpServletResponse response = new MockHttpServletResponse();
+ try {
+ mc.handleRequest(request, response);
+ fail("Should have thrown ServletException");
+ }
+ catch (ServletException ex) {
+ // expected
+ }
+ }
+
+ public void testRequireSessionWithSession() throws Exception {
+ TestController mc = new TestController();
+ mc.setRequireSession(true);
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/ok.html");
+ request.setSession(new MockHttpSession(null));
+ HttpServletResponse response = new MockHttpServletResponse();
+ mc.handleRequest(request, response);
+ }
+
+ public void testNoCaching() throws Exception {
+ TestController mc = new TestController();
+ mc.setCacheSeconds(0);
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/ok.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ mc.handleRequest(request, response);
+ assertTrue("Correct expires header", response.getHeader("Expires").equals(new Long(1)));
+ List cacheControl = response.getHeaders("Cache-Control");
+ assertTrue("Correct cache control", cacheControl.contains("no-cache"));
+ assertTrue("Correct cache control", cacheControl.contains("no-store"));
+ }
+
+ public void testNoCachingWithoutExpires() throws Exception {
+ TestController mc = new TestController();
+ mc.setCacheSeconds(0);
+ mc.setUseExpiresHeader(false);
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/ok.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ mc.handleRequest(request, response);
+ assertTrue("No expires header", response.getHeader("Expires") == null);
+ List cacheControl = response.getHeaders("Cache-Control");
+ assertTrue("Correct cache control", cacheControl.contains("no-cache"));
+ assertTrue("Correct cache control", cacheControl.contains("no-store"));
+ }
+
+ public void testNoCachingWithoutCacheControl() throws Exception {
+ TestController mc = new TestController();
+ mc.setCacheSeconds(0);
+ mc.setUseCacheControlHeader(false);
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/ok.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ mc.handleRequest(request, response);
+ assertTrue("Correct expires header", response.getHeader("Expires").equals(new Long(1)));
+ assertTrue("No cache control", response.getHeader("Cache-Control") == null);
+ }
+
+ public void testCaching() throws Exception {
+ TestController mc = new TestController();
+ mc.setCacheSeconds(10);
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/ok.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ mc.handleRequest(request, response);
+ assertTrue("Correct expires header", response.getHeader("Expires") != null);
+ assertTrue("Correct cache control", response.getHeader("Cache-Control").equals("max-age=10"));
+ }
+
+ public void testCachingWithoutExpires() throws Exception {
+ TestController mc = new TestController();
+ mc.setCacheSeconds(10);
+ mc.setUseExpiresHeader(false);
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/ok.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ mc.handleRequest(request, response);
+ assertTrue("No expires header", response.getHeader("Expires") == null);
+ assertTrue("Correct cache control", response.getHeader("Cache-Control").equals("max-age=10"));
+ }
+
+ public void testCachingWithoutCacheControl() throws Exception {
+ TestController mc = new TestController();
+ mc.setCacheSeconds(10);
+ mc.setUseCacheControlHeader(false);
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/ok.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ mc.handleRequest(request, response);
+ assertTrue("Correct expires header", response.getHeader("Expires") != null);
+ assertTrue("No cache control", response.getHeader("Cache-Control") == null);
+ }
+
+ public void testCachingWithLastModified() throws Exception {
+ class LastModifiedTestController extends TestController implements LastModified {
+ public long getLastModified(HttpServletRequest request) {
+ return 0;
+ }
+ }
+ LastModifiedTestController mc = new LastModifiedTestController();
+ mc.setCacheSeconds(10);
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/ok.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ mc.handleRequest(request, response);
+ assertTrue("Correct expires header", response.getHeader("Expires") != null);
+ assertTrue("Correct cache control", response.getHeader("Cache-Control").equals("max-age=10, must-revalidate"));
+ }
+
+ public void testCachingWithCustomCacheForSecondsCall() throws Exception {
+ TestController mc = new TestController() {
+ protected ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) {
+ cacheForSeconds(response, 5);
+ return super.handle(request, response, command, errors);
+ }
+ };
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/ok.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ mc.handleRequest(request, response);
+ assertTrue("Correct expires header", response.getHeader("Expires") != null);
+ assertTrue("Correct cache control", response.getHeader("Cache-Control").equals("max-age=5"));
+ }
+
+ public void testCachingWithCustomApplyCacheSecondsCall1() throws Exception {
+ TestController mc = new TestController() {
+ protected ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) {
+ applyCacheSeconds(response, 5);
+ return super.handle(request, response, command, errors);
+ }
+ };
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/ok.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ mc.handleRequest(request, response);
+ assertTrue("Correct expires header", response.getHeader("Expires") != null);
+ assertTrue("Correct cache control", response.getHeader("Cache-Control").equals("max-age=5"));
+ }
+
+ public void testCachingWithCustomApplyCacheSecondsCall2() throws Exception {
+ TestController mc = new TestController() {
+ protected ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) {
+ applyCacheSeconds(response, 0);
+ return super.handle(request, response, command, errors);
+ }
+ };
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/ok.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ mc.handleRequest(request, response);
+ assertTrue("Correct expires header", response.getHeader("Expires").equals(new Long(1)));
+ List cacheControl = response.getHeaders("Cache-Control");
+ assertTrue("Correct cache control", cacheControl.contains("no-cache"));
+ assertTrue("Correct cache control", cacheControl.contains("no-store"));
+ }
+
+ public void testCachingWithCustomApplyCacheSecondsCall3() throws Exception {
+ TestController mc = new TestController() {
+ protected ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) {
+ applyCacheSeconds(response, -1);
+ return super.handle(request, response, command, errors);
+ }
+ };
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/ok.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ mc.handleRequest(request, response);
+ assertTrue("No expires header", response.getHeader("Expires") == null);
+ assertTrue("No cache control", response.getHeader("Cache-Control") == null);
+ }
+
+ public void testCustomDateEditorWithAllowEmpty() throws Exception {
+ final DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.GERMAN);
+ TestController mc = new TestController() {
+ protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) {
+ binder.registerCustomEditor(Date.class, new CustomDateEditor(df, true));
+ }
+ };
+
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/welcome.html");
+ request.addParameter("date", "1.5.2003");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ TestBean tb = (TestBean) mv.getModel().get("command");
+ Errors errors = (Errors) mv.getModel().get("errors");
+ assertTrue("No field error", !errors.hasFieldErrors("date"));
+ assertTrue("Correct date property", df.parse("1.5.2003").equals(tb.getDate()));
+ assertTrue("Correct date value", "01.05.2003".equals(errors.getFieldValue("date")));
+
+ request = new MockHttpServletRequest("GET", "/welcome.html");
+ request.addParameter("date", "");
+ response = new MockHttpServletResponse();
+ mv = mc.handleRequest(request, response);
+ tb = (TestBean) mv.getModel().get("command");
+ errors = (Errors) mv.getModel().get("errors");
+ assertTrue("No field error", !errors.hasFieldErrors("date"));
+ assertTrue("Correct date property", tb.getDate() == null);
+ assertTrue("Correct date value", "".equals(errors.getFieldValue("date")));
+ }
+
+ public void testCustomDateEditorWithoutAllowEmpty() throws Exception {
+ final DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.GERMAN);
+ TestController mc = new TestController() {
+ protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) {
+ binder.registerCustomEditor(Date.class, new CustomDateEditor(df, false));
+ }
+ };
+
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/welcome.html");
+ request.addParameter("date", "1.5.2003");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ TestBean tb = (TestBean) mv.getModel().get("command");
+ Errors errors = (Errors) mv.getModel().get("errors");
+ assertTrue("No field error", !errors.hasFieldErrors("date"));
+ assertTrue("Correct date property", df.parse("1.5.2003").equals(tb.getDate()));
+ assertTrue("Correct date value", "01.05.2003".equals(errors.getFieldValue("date")));
+
+ request = new MockHttpServletRequest("GET", "/welcome.html");
+ request.addParameter("date", "");
+ response = new MockHttpServletResponse();
+ mv = mc.handleRequest(request, response);
+ tb = (TestBean) mv.getModel().get("command");
+ errors = (Errors) mv.getModel().get("errors");
+ assertTrue("Has field error", errors.hasFieldErrors("date"));
+ assertTrue("Correct date property", tb.getDate() != null);
+ assertTrue("Correct date value", errors.getFieldValue("date") != null);
+ }
+
+ public void testCustomNumberEditorWithAllowEmpty() throws Exception {
+ final NumberFormat nf = NumberFormat.getNumberInstance(Locale.GERMAN);
+
+ TestController mc = new TestController() {
+ protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) {
+ binder.registerCustomEditor(Float.class, new CustomNumberEditor(Float.class, nf, true));
+ }
+ };
+
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/welcome.html");
+ request.addParameter("myFloat", "5,1");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ TestBean tb = (TestBean) mv.getModel().get("command");
+ Errors errors = (Errors) mv.getModel().get("errors");
+ assertTrue("No field error", !errors.hasFieldErrors("myFloat"));
+ assertTrue("Correct float property", (new Float(5.1)).equals(tb.getMyFloat()));
+ assertTrue("Correct float value", "5,1".equals(errors.getFieldValue("myFloat")));
+
+ request = new MockHttpServletRequest("GET", "/welcome.html");
+ request.addParameter("myFloat", "");
+ response = new MockHttpServletResponse();
+ mv = mc.handleRequest(request, response);
+ tb = (TestBean) mv.getModel().get("command");
+ errors = (Errors) mv.getModel().get("errors");
+ assertTrue("No field error", !errors.hasFieldErrors("myFloat"));
+ assertTrue("Correct float property", tb.getMyFloat() == null);
+ assertTrue("Correct float value", "".equals(errors.getFieldValue("myFloat")));
+ }
+
+ public void testCustomNumberEditorWithoutAllowEmpty() throws Exception {
+ final NumberFormat nf = NumberFormat.getNumberInstance(Locale.GERMAN);
+
+ TestController mc = new TestController() {
+ protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) {
+ binder.registerCustomEditor(Float.class, new CustomNumberEditor(Float.class, nf, false));
+ }
+ };
+
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/welcome.html");
+ request.addParameter("myFloat", "5,1");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ TestBean tb = (TestBean) mv.getModel().get("command");
+ Errors errors = (Errors) mv.getModel().get("errors");
+ assertTrue("No field error", !errors.hasFieldErrors("myFloat"));
+ assertTrue("Correct float property", (new Float(5.1)).equals(tb.getMyFloat()));
+ assertTrue("Correct float value", "5,1".equals(errors.getFieldValue("myFloat")));
+
+ request = new MockHttpServletRequest("GET", "/welcome.html");
+ request.addParameter("myFloat", "");
+ response = new MockHttpServletResponse();
+ mv = mc.handleRequest(request, response);
+ tb = (TestBean) mv.getModel().get("command");
+ errors = (Errors) mv.getModel().get("errors");
+ assertTrue("Has field error", errors.hasFieldErrors("myFloat"));
+ assertTrue("Correct float property", tb.getMyFloat() != null);
+ assertTrue("Correct float value", errors.getFieldValue("myFloat") != null);
+ }
+
+ public void testResetEmptyStringField() throws Exception {
+ TestController mc = new TestController();
+
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/welcome.html");
+ request.addParameter("_name", "visible");
+ request.addParameter("name", "test");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ TestBean tb = (TestBean) mv.getModel().get("command");
+ Errors errors = (Errors) mv.getModel().get("errors");
+ assertTrue("Correct name property", "test".equals(tb.getName()));
+ assertTrue("Correct name value", "test".equals(errors.getFieldValue("name")));
+
+ request = new MockHttpServletRequest("GET", "/welcome.html");
+ request.addParameter("_name", "visible");
+ request.addParameter("_someNonExistingField", "visible");
+ mv = mc.handleRequest(request, response);
+ tb = (TestBean) mv.getModel().get("command");
+ errors = (Errors) mv.getModel().get("errors");
+ assertTrue("Correct name property", tb.getName() == null);
+ assertTrue("Correct name value", errors.getFieldValue("name") == null);
+ }
+
+ public void testResetEmptyBooleanField() throws Exception {
+ TestController mc = new TestController();
+
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/welcome.html");
+ request.addParameter("_postProcessed", "visible");
+ request.addParameter("postProcessed", "true");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ TestBean tb = (TestBean) mv.getModel().get("command");
+ Errors errors = (Errors) mv.getModel().get("errors");
+ assertTrue("Correct postProcessed property", tb.isPostProcessed());
+ assertTrue("Correct postProcessed value", Boolean.TRUE.equals(errors.getFieldValue("postProcessed")));
+
+ request = new MockHttpServletRequest("GET", "/welcome.html");
+ request.addParameter("_postProcessed", "visible");
+ mv = mc.handleRequest(request, response);
+ tb = (TestBean) mv.getModel().get("command");
+ errors = (Errors) mv.getModel().get("errors");
+ assertTrue("Correct postProcessed property", !tb.isPostProcessed());
+ assertTrue("Correct postProcessed value", Boolean.FALSE.equals(errors.getFieldValue("postProcessed")));
+ }
+
+ public void testResetEmptyStringArrayField() throws Exception {
+ TestController mc = new TestController();
+
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/welcome.html");
+ request.addParameter("_stringArray", "visible");
+ request.addParameter("stringArray", "value1");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ TestBean tb = (TestBean) mv.getModel().get("command");
+ assertTrue("Correct stringArray property",
+ tb.getStringArray() != null && "value1".equals(tb.getStringArray()[0]));
+
+ request = new MockHttpServletRequest("GET", "/welcome.html");
+ request.addParameter("_stringArray", "visible");
+ mv = mc.handleRequest(request, response);
+ tb = (TestBean) mv.getModel().get("command");
+ assertTrue("Correct stringArray property", tb.getStringArray() != null && tb.getStringArray().length == 0);
+ }
+
+ public void testResetEmptyFieldsTurnedOff() throws Exception {
+ TestController mc = new TestController() {
+ protected Object getCommand(HttpServletRequest request) throws Exception {
+ return new TestBean("original", 99);
+ }
+ protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) {
+ binder.setFieldMarkerPrefix(null);
+ }
+ };
+
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/welcome.html");
+ request.addParameter("_name", "visible");
+ request.addParameter("name", "test");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ TestBean tb = (TestBean) mv.getModel().get("command");
+ Errors errors = (Errors) mv.getModel().get("errors");
+ assertTrue("Correct name property", "test".equals(tb.getName()));
+ assertTrue("Correct name value", "test".equals(errors.getFieldValue("name")));
+
+ request = new MockHttpServletRequest("GET", "/welcome.html");
+ request.addParameter("_name", "true");
+ mv = mc.handleRequest(request, response);
+ tb = (TestBean) mv.getModel().get("command");
+ errors = (Errors) mv.getModel().get("errors");
+ assertTrue("Correct name property", "original".equals(tb.getName()));
+ assertTrue("Correct name value", "original".equals(errors.getFieldValue("name")));
+ }
+
+
+ private static class TestController extends AbstractCommandController {
+
+ private TestController() {
+ super(TestBean.class, "person");
+ }
+
+ protected ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) {
+ Map m = new HashMap();
+ assertTrue("Command not null", command != null);
+ assertTrue("errors not null", errors != null);
+ m.put("errors", errors);
+ m.put("command", command);
+ return new ModelAndView(request.getServletPath(), m);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/ControllerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/ControllerTests.java
new file mode 100644
index 00000000000..d54fc6ab3e1
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/ControllerTests.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.servlet.mvc;
+
+import java.util.Properties;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.Servlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import junit.framework.TestCase;
+import org.easymock.MockControl;
+
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.web.context.support.StaticWebApplicationContext;
+import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.util.WebUtils;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public class ControllerTests extends TestCase {
+
+ public void testParameterizableViewController() throws Exception {
+ String viewName = "viewName";
+ ParameterizableViewController pvc = new ParameterizableViewController();
+ pvc.setViewName(viewName);
+ pvc.initApplicationContext();
+ // We don't care about the params.
+ ModelAndView mv = pvc.handleRequest(new MockHttpServletRequest("GET", "foo.html"), null);
+ assertTrue("model has no data", mv.getModel().size() == 0);
+ assertTrue("model has correct viewname", mv.getViewName().equals(viewName));
+ assertTrue("getViewName matches", pvc.getViewName().equals(viewName));
+ }
+
+ public void testParameterizableViewControllerWithPropertyNotSet() {
+ ParameterizableViewController pvc = new ParameterizableViewController();
+ try {
+ pvc.initApplicationContext();
+ fail("should require viewName property to be set");
+ }
+ catch (IllegalArgumentException ex){
+ // expected
+ assertTrue("meaningful exception message", ex.getMessage().indexOf("viewName") != -1);
+ }
+ }
+
+ public void testServletForwardingController() throws Exception {
+ ServletForwardingController sfc = new ServletForwardingController();
+ sfc.setServletName("action");
+ doTestServletForwardingController(sfc, false);
+ }
+
+ public void testServletForwardingControllerWithInclude() throws Exception {
+ ServletForwardingController sfc = new ServletForwardingController();
+ sfc.setServletName("action");
+ doTestServletForwardingController(sfc, true);
+ }
+
+ public void testServletForwardingControllerWithBeanName() throws Exception {
+ ServletForwardingController sfc = new ServletForwardingController();
+ sfc.setBeanName("action");
+ doTestServletForwardingController(sfc, false);
+ }
+
+ private void doTestServletForwardingController(ServletForwardingController sfc, boolean include)
+ throws Exception {
+
+ MockControl requestControl = MockControl.createControl(HttpServletRequest.class);
+ HttpServletRequest request = (HttpServletRequest) requestControl.getMock();
+ MockControl responseControl = MockControl.createControl(HttpServletResponse.class);
+ HttpServletResponse response = (HttpServletResponse) responseControl.getMock();
+ MockControl contextControl = MockControl.createControl(ServletContext.class);
+ ServletContext context = (ServletContext) contextControl.getMock();
+ MockControl dispatcherControl = MockControl.createControl(RequestDispatcher.class);
+ RequestDispatcher dispatcher = (RequestDispatcher) dispatcherControl.getMock();
+
+ request.getMethod();
+ requestControl.setReturnValue("GET", 1);
+ context.getNamedDispatcher("action");
+ contextControl.setReturnValue(dispatcher, 1);
+ if (include) {
+ request.getAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE);
+ requestControl.setReturnValue("somePath", 1);
+ dispatcher.include(request, response);
+ dispatcherControl.setVoidCallable(1);
+ }
+ else {
+ request.getAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE);
+ requestControl.setReturnValue(null, 1);
+ dispatcher.forward(request, response);
+ dispatcherControl.setVoidCallable(1);
+ }
+ requestControl.replay();
+ contextControl.replay();
+ dispatcherControl.replay();
+
+ StaticWebApplicationContext sac = new StaticWebApplicationContext();
+ sac.setServletContext(context);
+ sfc.setApplicationContext(sac);
+ assertNull(sfc.handleRequest(request, response));
+
+ requestControl.verify();
+ contextControl.verify();
+ dispatcherControl.verify();
+ }
+
+ public void testServletWrappingController() throws Exception {
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/somePath");
+ HttpServletResponse response = new MockHttpServletResponse();
+
+ ServletWrappingController swc = new ServletWrappingController();
+ swc.setServletClass(TestServlet.class);
+ swc.setServletName("action");
+ Properties props = new Properties();
+ props.setProperty("config", "myValue");
+ swc.setInitParameters(props);
+
+ swc.afterPropertiesSet();
+ assertNotNull(TestServlet.config);
+ assertEquals("action", TestServlet.config.getServletName());
+ assertEquals("myValue", TestServlet.config.getInitParameter("config"));
+ assertNull(TestServlet.request);
+ assertFalse(TestServlet.destroyed);
+
+ assertNull(swc.handleRequest(request, response));
+ assertEquals(request, TestServlet.request);
+ assertEquals(response, TestServlet.response);
+ assertFalse(TestServlet.destroyed);
+
+ swc.destroy();
+ assertTrue(TestServlet.destroyed);
+ }
+
+ public void testServletWrappingControllerWithBeanName() throws Exception {
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/somePath");
+ HttpServletResponse response = new MockHttpServletResponse();
+
+ ServletWrappingController swc = new ServletWrappingController();
+ swc.setServletClass(TestServlet.class);
+ swc.setBeanName("action");
+
+ swc.afterPropertiesSet();
+ assertNotNull(TestServlet.config);
+ assertEquals("action", TestServlet.config.getServletName());
+ assertNull(TestServlet.request);
+ assertFalse(TestServlet.destroyed);
+
+ assertNull(swc.handleRequest(request, response));
+ assertEquals(request, TestServlet.request);
+ assertEquals(response, TestServlet.response);
+ assertFalse(TestServlet.destroyed);
+
+ swc.destroy();
+ assertTrue(TestServlet.destroyed);
+ }
+
+
+ public static class TestServlet implements Servlet {
+
+ private static ServletConfig config;
+ private static ServletRequest request;
+ private static ServletResponse response;
+ private static boolean destroyed;
+
+ public TestServlet() {
+ config = null;
+ request = null;
+ response = null;
+ destroyed = false;
+ }
+
+ public void init(ServletConfig servletConfig) {
+ config = servletConfig;
+ }
+
+ public ServletConfig getServletConfig() {
+ return config;
+ }
+
+ public void service(ServletRequest servletRequest, ServletResponse servletResponse) {
+ request = servletRequest;
+ response = servletResponse;
+ }
+
+ public String getServletInfo() {
+ return "TestServlet";
+ }
+
+ public void destroy() {
+ destroyed = true;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/FormControllerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/FormControllerTests.java
new file mode 100644
index 00000000000..dd735910802
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/FormControllerTests.java
@@ -0,0 +1,646 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.servlet.mvc;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.IndexedTestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.context.support.StaticApplicationContext;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.validation.BindException;
+import org.springframework.validation.Errors;
+import org.springframework.validation.FieldError;
+import org.springframework.validation.ObjectError;
+import org.springframework.validation.Validator;
+import org.springframework.web.context.support.StaticWebApplicationContext;
+import org.springframework.web.servlet.ModelAndView;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ */
+public class FormControllerTests extends TestCase {
+
+ public void testReferenceDataOnForm() throws Exception {
+ String formView = "f";
+ String successView = "s";
+
+ RefController mc = new RefController();
+ mc.setFormView(formView);
+ mc.setCommandName("tb");
+ mc.setSuccessView(successView);
+ mc.refDataCount = 0;
+
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/welcome.html");
+ HttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ assertTrue("returned correct view name", mv.getViewName().equals(formView));
+
+ assertTrue("refDataCount == 1", mc.refDataCount == 1);
+
+ TestBean person = (TestBean) mv.getModel().get(mc.getCommandName());
+ int[] numbers = (int[]) mv.getModel().get(mc.NUMBERS_ATT);
+ assertTrue("model is non null", person != null);
+ assertTrue("numbers is non null", numbers != null);
+ }
+
+ public void testReferenceDataOnResubmit() throws Exception {
+ String formView = "f";
+ String successView = "s";
+
+ RefController mc = new RefController();
+ mc.setFormView(formView);
+ mc.setCommandName("tb");
+ mc.setSuccessView(successView);
+ mc.refDataCount = 0;
+
+ MockHttpServletRequest request = new MockHttpServletRequest("POST", "/welcome.html");
+ request.addParameter("age", "23x");
+ HttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ assertTrue("returned correct view name", mv.getViewName().equals(formView));
+ assertTrue("has errors", mv.getModel().get(BindException.MODEL_KEY_PREFIX + mc.getCommandName()) != null);
+
+ assertTrue("refDataCount == 1", mc.refDataCount == 1);
+
+ TestBean person = (TestBean) mv.getModel().get(mc.getCommandName());
+ int[] numbers = (int[]) mv.getModel().get(mc.NUMBERS_ATT);
+ assertTrue("model is non null", person != null);
+ assertTrue("numbers is non null", numbers != null);
+ }
+
+ public void testForm() throws Exception {
+ String formView = "f";
+ String successView = "s";
+
+ TestController mc = new TestController();
+ mc.setFormView(formView);
+ mc.setSuccessView(successView);
+
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/welcome.html");
+ request.addParameter("name", "rod");
+ HttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ assertTrue("returned correct view name", mv.getViewName().equals(formView));
+
+ TestBean person = (TestBean) mv.getModel().get(TestController.BEAN_NAME);
+ assertTrue("model is non null", person != null);
+ assertTrue("bean age default ok", person.getAge() == TestController.DEFAULT_AGE);
+ assertTrue("name not set", person.getName() == null);
+ }
+
+ public void testBindOnNewForm() throws Exception {
+ String formView = "f";
+ String successView = "s";
+ final Integer someNumber = new Integer(12);
+
+ TestController mc = new TestController() {
+ protected void onBindOnNewForm(HttpServletRequest request, Object command) throws Exception {
+ TestBean testBean = (TestBean)command;
+ testBean.setSomeNumber(new Integer(12));
+ }
+ };
+ mc.setFormView(formView);
+ mc.setSuccessView(successView);
+ mc.setBindOnNewForm(true);
+
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/welcome.html");
+ request.addParameter("name", "rod");
+ HttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ assertEquals("returned correct view name", formView, mv.getViewName());
+
+ TestBean person = (TestBean) mv.getModel().get(TestController.BEAN_NAME);
+ assertNotNull("model is non null", person);
+ assertEquals("bean age default ok", person.getAge(), TestController.DEFAULT_AGE);
+ assertEquals("name set", "rod", person.getName());
+ assertEquals("Property [someNumber] not set in onBindOnNewForm callback", someNumber, person.getSomeNumber());
+ }
+
+ public void testSubmitWithoutErrors() throws Exception {
+ String formView = "f";
+ String successView = "s";
+
+ TestController mc = new TestController();
+ mc.setFormView(formView);
+ mc.setSuccessView(successView);
+
+ String name = "Rod";
+ int age = 32;
+
+ MockHttpServletRequest request = new MockHttpServletRequest("POST", "/welcome.html");
+ request.addParameter("name", name);
+ request.addParameter("age", "" + age);
+ HttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+
+ assertEquals("returned correct view name", successView, mv.getViewName());
+ TestBean person = (TestBean) mv.getModel().get(TestController.BEAN_NAME);
+ Errors errors = (Errors) mv.getModel().get(BindException.MODEL_KEY_PREFIX + TestController.BEAN_NAME);
+ assertTrue("model is non null", person != null);
+ assertTrue("errors is non null", errors != null);
+ assertTrue("bean name bound ok", person.getName().equals(name));
+ assertTrue("bean age bound ok", person.getAge() == age);
+ }
+
+ public void testSubmitWithoutValidation() throws Exception {
+ String formView = "f";
+ String successView = "s";
+
+ TestController mc = new TestController();
+ mc.setFormView(formView);
+ mc.setSuccessView(successView);
+
+ String name = "Rod";
+ int age = 32;
+
+ MockHttpServletRequest request = new MockHttpServletRequest("POST", "/welcome.html");
+ request.addParameter("name", name);
+ request.addParameter("age", "" + age);
+ request.addParameter("formChange", "true");
+ HttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+
+ assertEquals("returned correct view name", formView, mv.getViewName());
+ TestBean person = (TestBean) mv.getModel().get(TestController.BEAN_NAME);
+ Errors errors = (Errors) mv.getModel().get(BindException.MODEL_KEY_PREFIX + TestController.BEAN_NAME);
+ assertTrue("model is non null", person != null);
+ assertTrue("errors is non null", errors != null);
+ assertTrue("bean name bound ok", person.getName().equals(name));
+ assertTrue("bean age bound ok", person.getAge() == age);
+ }
+
+ public void testSubmitWithCustomOnSubmit() throws Exception {
+ String formView = "f";
+
+ TestControllerWithCustomOnSubmit mc = new TestControllerWithCustomOnSubmit();
+ mc.setFormView(formView);
+
+ String name = "Rod";
+ int age = 32;
+
+ MockHttpServletRequest request = new MockHttpServletRequest("POST", "/welcome.html");
+ request.addParameter("name", name);
+ request.addParameter("age", "" + age);
+ HttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ assertEquals("returned correct view name", "mySuccess", mv.getViewName());
+ assertTrue("no model", mv.getModel().isEmpty());
+ }
+
+ public void testSubmitPassedByValidator() throws Exception {
+ String formView = "f";
+ String successView = "s";
+
+ TestController mc = new TestController();
+ mc.setFormView(formView);
+ mc.setSuccessView(successView);
+ mc.setValidator(new TestValidator());
+
+ String name = "Roderick Johnson";
+ int age = 32;
+
+ MockHttpServletRequest request = new MockHttpServletRequest("POST", "/welcome.html");
+ request.addParameter("name", name);
+ request.addParameter("age", "" + age);
+ HttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ assertTrue("returned correct view name: expected '" + successView + "', not '" + mv.getViewName() + "'",
+ mv.getViewName().equals(successView));
+
+ TestBean person = (TestBean) mv.getModel().get(TestController.BEAN_NAME);
+ assertTrue("model is non null", person != null);
+ assertTrue("bean name bound ok", person.getName().equals(name));
+ assertTrue("bean age bound ok", person.getAge() == age);
+ }
+
+ public void testSubmit1Mismatch() throws Exception {
+ String formView = "fred";
+ String successView = "tony";
+
+ TestController mc = new TestController();
+ mc.setFormView(formView);
+ mc.setSuccessView(successView);
+
+ String name = "Rod";
+ String age = "xxx";
+
+ MockHttpServletRequest request = new MockHttpServletRequest("POST", "/foo.html");
+ request.addParameter("name", name);
+ request.addParameter("age", "" + age);
+ HttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ assertTrue("returned correct view name: expected '" + formView + "', not '" + mv.getViewName() + "'",
+ mv.getViewName().equals(formView));
+
+ TestBean person = (TestBean) mv.getModel().get(mc.getCommandName());
+ assertTrue("model is non null", person != null);
+ assertTrue("bean name bound ok", person.getName().equals(name));
+ assertTrue("bean age is default", person.getAge() == TestController.DEFAULT_AGE);
+ Errors errors = (Errors) mv.getModel().get(BindException.MODEL_KEY_PREFIX + mc.getCommandName());
+ assertTrue("errors returned in model", errors != null);
+ assertTrue("One error", errors.getErrorCount() == 1);
+ FieldError fe = errors.getFieldError("age");
+ assertTrue("Saved invalid value", fe.getRejectedValue().equals(age));
+ assertTrue("Correct field", fe.getField().equals("age"));
+ }
+
+ public void testSubmit1Mismatch1Invalidated() throws Exception {
+ String formView = "fred";
+ String successView = "tony";
+
+ TestController mc = new TestController();
+ mc.setFormView(formView);
+ mc.setSuccessView(successView);
+ mc.setValidators(new Validator[] {new TestValidator(), new TestValidator2()});
+
+ String name = "Rod";
+ // will be rejected
+ String age = "xxx";
+
+ MockHttpServletRequest request = new MockHttpServletRequest("POST", "/foo.html");
+ request.addParameter("name", name);
+ request.addParameter("age", "" + age);
+ HttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ assertTrue("returned correct view name: expected '" + formView + "', not '" + mv.getViewName() + "'",
+ mv.getViewName().equals(formView));
+
+ TestBean person = (TestBean) mv.getModel().get(TestController.BEAN_NAME);
+ assertTrue("model is non null", person != null);
+
+ // yes, but it was rejected after binding by the validator
+ assertTrue("bean name bound ok", person.getName().equals(name));
+ assertTrue("bean age is default", person.getAge() == TestController.DEFAULT_AGE);
+ Errors errors = (Errors) mv.getModel().get(BindException.MODEL_KEY_PREFIX + mc.getCommandName());
+ assertTrue("errors returned in model", errors != null);
+ assertTrue("3 errors", errors.getErrorCount() == 3);
+ FieldError fe = errors.getFieldError("age");
+ assertTrue("Saved invalid value", fe.getRejectedValue().equals(age));
+ assertTrue("Correct field", fe.getField().equals("age"));
+
+ // raised by first validator
+ fe = errors.getFieldError("name");
+ assertTrue("Saved invalid value", fe.getRejectedValue().equals(name));
+ assertTrue("Correct field", fe.getField().equals("name"));
+ assertTrue("Correct validation code: expected '" +TestValidator.TOOSHORT + "', not '" +
+ fe.getCode() + "'", fe.getCode().equals(TestValidator.TOOSHORT));
+
+ // raised by second validator
+ ObjectError oe = errors.getGlobalError();
+ assertEquals("test", oe.getCode());
+ assertEquals("testmessage", oe.getDefaultMessage());
+ }
+
+ public void testSessionController() throws Exception {
+ String formView = "f";
+ String successView = "s";
+
+ TestController mc = new TestController();
+ mc.setFormView(formView);
+ mc.setSuccessView(successView);
+ mc.setSessionForm(true);
+
+ // first request: GET form
+ HttpServletRequest request1 = new MockHttpServletRequest("GET", "/welcome.html");
+ HttpServletResponse response1 = new MockHttpServletResponse();
+ ModelAndView mv1 = mc.handleRequest(request1, response1);
+ assertTrue("returned correct view name", mv1.getViewName().equals(formView));
+ TestBean person = (TestBean) mv1.getModel().get(TestController.BEAN_NAME);
+ assertTrue("model is non null", person != null);
+ assertTrue("Bean age default ok", person.getAge() == TestController.DEFAULT_AGE);
+
+ // second request, using same session: POST submit
+ MockHttpServletRequest request2 = new MockHttpServletRequest("POST", "/welcome.html");
+ request2.setSession(request1.getSession(false));
+ HttpServletResponse response2 = new MockHttpServletResponse();
+ ModelAndView mv2 = mc.handleRequest(request2, response2);
+ assertTrue("returned correct view name", mv2.getViewName().equals(successView));
+ TestBean person2 = (TestBean) mv2.getModel().get(TestController.BEAN_NAME);
+ assertTrue("model is same object", person == person2);
+ }
+
+ public void testDefaultInvalidSubmit() throws Exception {
+ String formView = "f";
+ String successView = "s";
+
+ TestController mc = new TestController();
+ mc.setFormView(formView);
+ mc.setSuccessView(successView);
+ mc.setSessionForm(true);
+
+ // invalid request: POST submit
+ MockHttpServletRequest request = new MockHttpServletRequest("POST", "/welcome.html");
+ HttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ assertTrue("returned correct view name", mv.getViewName().equals(successView));
+ TestBean person = (TestBean) mv.getModel().get(TestController.BEAN_NAME);
+ assertTrue("model is non null", person != null);
+ }
+
+ public void testSpecialInvalidSubmit() throws Exception {
+ String formView = "f";
+ String successView = "s";
+
+ TestController mc = new TestController() {
+ protected ModelAndView handleInvalidSubmit(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ throw new ServletException("invalid submit");
+ }
+ };
+ mc.setFormView(formView);
+ mc.setSuccessView(successView);
+ mc.setSessionForm(true);
+
+ // invalid request: POST submit
+ MockHttpServletRequest request = new MockHttpServletRequest("POST", "/welcome.html");
+ HttpServletResponse response = new MockHttpServletResponse();
+ try {
+ mc.handleRequest(request, response);
+ fail("Should have thrown ServletException");
+ }
+ catch (ServletException ex) {
+ // expected
+ }
+ }
+
+ public void testSubmitWithIndexedProperties() throws Exception {
+ String formView = "fred";
+ String successView = "tony";
+
+ SimpleFormController mc = new SimpleFormController();
+ mc.setCommandClass(IndexedTestBean.class);
+ mc.setFormView(formView);
+ mc.setSuccessView(successView);
+
+ MockHttpServletRequest request = new MockHttpServletRequest("POST", "/foo.html");
+ request.addParameter("array[0].name", "name3");
+ request.addParameter("array[1].age", "name2");
+ request.addParameter("list[0].name", "name1");
+ request.addParameter("list[1].age", "name0");
+ request.addParameter("list[2]", "listobj");
+ request.addParameter("map[key1]", "mapobj1");
+ request.addParameter("map[key3]", "mapobj2");
+ HttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ assertTrue("returned correct view name: expected '" + formView + "', not '" + mv.getViewName() + "'",
+ mv.getViewName().equals(formView));
+
+ IndexedTestBean bean = (IndexedTestBean) mv.getModel().get(mc.getCommandName());
+ assertTrue("model is non null", bean != null);
+ assertEquals("name3", bean.getArray()[0].getName());
+ assertEquals("name1", ((TestBean) bean.getList().get(0)).getName());
+ Errors errors = (Errors) mv.getModel().get(BindException.MODEL_KEY_PREFIX + mc.getCommandName());
+ assertTrue("errors returned in model", errors != null);
+ assertTrue("2 errors", errors.getErrorCount() == 2);
+ FieldError fe1 = errors.getFieldError("array[1].age");
+ assertTrue("Saved invalid value", fe1.getRejectedValue().equals("name2"));
+ assertTrue("Correct field", fe1.getField().equals("array[1].age"));
+ FieldError fe2 = errors.getFieldError("list[1].age");
+ assertTrue("Saved invalid value", fe2.getRejectedValue().equals("name0"));
+ assertTrue("Correct field", fe2.getField().equals("list[1].age"));
+
+ assertEquals("listobj", bean.getList().get(2));
+ assertEquals("mapobj1", bean.getMap().get("key1"));
+ assertEquals("mapobj2", bean.getMap().get("key3"));
+ }
+
+ public void testFormChangeRequest() throws Exception {
+ String formView = "fred";
+ String successView = "tony";
+ final Float myFloat = new Float("123.45");
+
+ TestController mc = new TestController() {
+ protected boolean isFormChangeRequest(HttpServletRequest request) {
+ return (request.getParameter("formChange") != null);
+ }
+
+ protected void onFormChange(HttpServletRequest request, HttpServletResponse response, Object command) {
+ assertNotNull("Command should not be null", command);
+ assertEquals("Incorrect command class", TestBean.class, command.getClass());
+ ((TestBean)command).setMyFloat(myFloat);
+ }
+ };
+ mc.setFormView(formView);
+ mc.setSuccessView(successView);
+
+ MockHttpServletRequest request = new MockHttpServletRequest("POST", "/foo.html");
+ request.addParameter("name", "Rod");
+ request.addParameter("age", "99");
+ request.addParameter("formChange", "true");
+ HttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ assertTrue("returned correct view name: expected '" + formView + "', not '" + mv.getViewName() + "'",
+ mv.getViewName().equals(formView));
+
+ TestBean person = (TestBean) mv.getModel().get(mc.getCommandName());
+ assertTrue("model is non null", person != null);
+ assertTrue("bean name bound ok", person.getName().equals("Rod"));
+ assertTrue("bean age is 99", person.getAge() == 99);
+ assertEquals("Command property myFloat not updated in onFormChange", myFloat, person.getMyFloat());
+ Errors errors = (Errors) mv.getModel().get(BindException.MODEL_KEY_PREFIX + mc.getCommandName());
+ assertTrue("errors returned in model", errors != null);
+ assertTrue("No errors", errors.getErrorCount() == 0);
+ }
+
+ public void testFormBindingOfNestedBooleans() throws Exception {
+ BooleanBindingFormController controller = new BooleanBindingFormController();
+ controller.setCommandClass(ListForm.class);
+ MockHttpServletRequest req = new MockHttpServletRequest("POST", "/myurl");
+ MockHttpServletResponse res = new MockHttpServletResponse();
+ req.addParameter("oks[0].ok", "true");
+ ModelAndView mav = controller.handleRequest(req, res);
+ ListForm form = (ListForm) mav.getModelMap().get("command");
+ Boolean ok = ((Ok) form.getOks().get(0)).getOk();
+ assertNotNull(ok);
+ }
+
+ public void testFormControllerInWebApplicationContext() {
+ StaticWebApplicationContext ctx = new StaticWebApplicationContext();
+ ctx.setServletContext(new MockServletContext());
+ RefController mc = new RefController();
+ mc.setApplicationContext(ctx);
+ try {
+ mc.invokeWebSpecificStuff();
+ }
+ catch (IllegalStateException ex) {
+ fail("Shouldn't have thrown exception: " + ex.getMessage());
+ }
+ }
+
+ public void testFormControllerInNonWebApplicationContext() {
+ StaticApplicationContext ctx = new StaticApplicationContext();
+ RefController mc = new RefController();
+ mc.setApplicationContext(ctx);
+ try {
+ mc.invokeWebSpecificStuff();
+ fail("Should have thrown IllegalStateException");
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ }
+
+
+ private static class TestValidator implements Validator {
+
+ public static String TOOSHORT = "tooshort";
+
+ public boolean supports(Class clazz) { return true; }
+
+ public void validate(Object obj, Errors errors) {
+ TestBean tb = (TestBean) obj;
+ if (tb.getName() == null || "".equals(tb.getName()))
+ errors.rejectValue("name", "needname", null, "need name");
+ else if (tb.getName().length() < 5)
+ errors.rejectValue("name", TOOSHORT, null, "need full name");
+ }
+ }
+
+
+ private static class TestValidator2 implements Validator {
+
+ public static String TOOSHORT = "tooshort";
+
+ public boolean supports(Class clazz) { return true; }
+
+ public void validate(Object obj, Errors errors) {
+ errors.reject("test", "testmessage");
+ }
+ }
+
+
+ private static class TestController extends SimpleFormController {
+
+ public static String BEAN_NAME = "person";
+
+ public static int DEFAULT_AGE = 52;
+
+ public TestController() {
+ setCommandClass(TestBean.class);
+ setCommandName(BEAN_NAME);
+ }
+
+ protected Object formBackingObject(HttpServletRequest request) throws ServletException {
+ TestBean person = new TestBean();
+ person.setAge(DEFAULT_AGE);
+ return person;
+ }
+
+ protected boolean isFormChangeRequest(HttpServletRequest request) {
+ return (request.getParameter("formChange") != null);
+ }
+ }
+
+
+ private static class TestControllerWithCustomOnSubmit extends TestController {
+
+ protected ModelAndView onSubmit(Object command) throws Exception {
+ return new ModelAndView("mySuccess");
+ }
+ }
+
+
+ private static class RefController extends SimpleFormController {
+
+ final String NUMBERS_ATT = "NUMBERS";
+
+ static final int[] NUMBERS = { 1, 2, 3, 4 };
+
+ int refDataCount;
+
+ public RefController() {
+ setCommandClass(TestBean.class);
+ }
+
+ protected Map referenceData(HttpServletRequest request) {
+ ++refDataCount;
+ Map m = new HashMap();
+ m.put(NUMBERS_ATT, NUMBERS);
+ return m;
+ }
+
+ public void invokeWebSpecificStuff() {
+ getTempDir();
+ }
+ }
+
+
+ public static class BooleanBindingFormController extends AbstractFormController {
+
+ protected ModelAndView processFormSubmission
+ (HttpServletRequest req, HttpServletResponse resp, Object command, BindException errors) throws Exception {
+ ModelAndView mav = new ModelAndView();
+ mav.addObject("command", command);
+ return mav;
+ }
+
+ protected ModelAndView showForm(
+ HttpServletRequest req, HttpServletResponse resp, BindException err) throws Exception {
+ return null;
+ }
+ }
+
+
+ public static class Ok {
+
+ private Boolean ok;
+
+ public Boolean getOk () {
+ return ok;
+ }
+
+ public void setOk(Boolean ok) {
+ this.ok = ok;
+ }
+ }
+
+
+ public static class ListForm {
+
+ private List oks = new ArrayList();
+
+ public ListForm () {
+ for (int index = 0; index < 5; index++) {
+ Ok ok = new Ok();
+ oks.add(ok);
+ }
+ }
+
+ public List getOks() {
+ return oks;
+ }
+
+ public void setOks(List oks) {
+ this.oks = oks;
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/UrlFilenameViewControllerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/UrlFilenameViewControllerTests.java
new file mode 100644
index 00000000000..ed45d97f820
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/UrlFilenameViewControllerTests.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.servlet.mvc;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.util.AntPathMatcher;
+import org.springframework.util.PathMatcher;
+import org.springframework.web.servlet.HandlerMapping;
+import org.springframework.web.servlet.ModelAndView;
+
+/**
+ * @author Juergen Hoeller
+ * @author Rick Evans
+ * @since 14.09.2005
+ */
+public class UrlFilenameViewControllerTests extends TestCase {
+
+ private PathMatcher pathMatcher = new AntPathMatcher();
+
+
+ public void testWithPlainFilename() throws Exception {
+ UrlFilenameViewController ctrl = new UrlFilenameViewController();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/index");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = ctrl.handleRequest(request, response);
+ assertEquals("index", mv.getViewName());
+ assertTrue(mv.getModel().isEmpty());
+ }
+
+ public void testWithFilenamePlusExtension() throws Exception {
+ UrlFilenameViewController ctrl = new UrlFilenameViewController();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/index.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = ctrl.handleRequest(request, response);
+ assertEquals("index", mv.getViewName());
+ assertTrue(mv.getModel().isEmpty());
+ }
+
+ public void testWithPrefixAndSuffix() throws Exception {
+ UrlFilenameViewController ctrl = new UrlFilenameViewController();
+ ctrl.setPrefix("mypre_");
+ ctrl.setSuffix("_mysuf");
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/index.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = ctrl.handleRequest(request, response);
+ assertEquals("mypre_index_mysuf", mv.getViewName());
+ assertTrue(mv.getModel().isEmpty());
+ }
+
+ public void testWithPrefix() throws Exception {
+ UrlFilenameViewController ctrl = new UrlFilenameViewController();
+ ctrl.setPrefix("mypre_");
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/index.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = ctrl.handleRequest(request, response);
+ assertEquals("mypre_index", mv.getViewName());
+ assertTrue(mv.getModel().isEmpty());
+ }
+
+ public void testWithSuffix() throws Exception {
+ UrlFilenameViewController ctrl = new UrlFilenameViewController();
+ ctrl.setSuffix("_mysuf");
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/index.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = ctrl.handleRequest(request, response);
+ assertEquals("index_mysuf", mv.getViewName());
+ assertTrue(mv.getModel().isEmpty());
+ }
+
+ public void testMultiLevel() throws Exception {
+ UrlFilenameViewController ctrl = new UrlFilenameViewController();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/docs/cvs/commit.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = ctrl.handleRequest(request, response);
+ assertEquals("docs/cvs/commit", mv.getViewName());
+ assertTrue(mv.getModel().isEmpty());
+ }
+
+ public void testMultiLevelWithMapping() throws Exception {
+ UrlFilenameViewController ctrl = new UrlFilenameViewController();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/docs/cvs/commit.html");
+ exposePathInMapping(request, "/docs/**");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = ctrl.handleRequest(request, response);
+ assertEquals("cvs/commit", mv.getViewName());
+ assertTrue(mv.getModel().isEmpty());
+ }
+
+ public void testMultiLevelMappingWithFallback() throws Exception {
+ UrlFilenameViewController ctrl = new UrlFilenameViewController();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/docs/cvs/commit.html");
+ exposePathInMapping(request, "/docs/cvs/commit.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = ctrl.handleRequest(request, response);
+ assertEquals("docs/cvs/commit", mv.getViewName());
+ assertTrue(mv.getModel().isEmpty());
+ }
+
+ public void testWithContextMapping() throws Exception {
+ UrlFilenameViewController ctrl = new UrlFilenameViewController();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myapp/docs/cvs/commit.html");
+ request.setContextPath("/myapp");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = ctrl.handleRequest(request, response);
+ assertEquals("docs/cvs/commit", mv.getViewName());
+ assertTrue(mv.getModel().isEmpty());
+ }
+
+ public void testSettingPrefixToNullCausesEmptyStringToBeUsed() throws Exception {
+ UrlFilenameViewController ctrl = new UrlFilenameViewController();
+ ctrl.setPrefix(null);
+ assertNotNull("When setPrefix(..) is called with a null argument, the empty string value must be used instead.", ctrl.getPrefix());
+ assertEquals("When setPrefix(..) is called with a null argument, the empty string value must be used instead.", "", ctrl.getPrefix());
+ }
+
+ public void testSettingSuffixToNullCausesEmptyStringToBeUsed() throws Exception {
+ UrlFilenameViewController ctrl = new UrlFilenameViewController();
+ ctrl.setSuffix(null);
+ assertNotNull("When setSuffix(..) is called with a null argument, the empty string value must be used instead.", ctrl.getSuffix());
+ assertEquals("When setSuffix(..) is called with a null argument, the empty string value must be used instead.", "", ctrl.getSuffix());
+ }
+
+ /**
+ * This is the expected behavior, and it now has a test to prove it.
+ * http://opensource.atlassian.com/projects/spring/browse/SPR-2789
+ */
+ public void testNestedPathisUsedAsViewName_InBreakingChangeFromSpring12Line() throws Exception {
+ UrlFilenameViewController ctrl = new UrlFilenameViewController();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/products/view.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = ctrl.handleRequest(request, response);
+ assertEquals("products/view", mv.getViewName());
+ assertTrue(mv.getModel().isEmpty());
+ }
+
+ private void exposePathInMapping(MockHttpServletRequest request, String mapping) {
+ String pathInMapping = this.pathMatcher.extractPathWithinPattern(mapping, request.getRequestURI());
+ request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, pathInMapping);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/WebContentInterceptorTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/WebContentInterceptorTests.java
new file mode 100644
index 00000000000..e23a379f2be
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/WebContentInterceptorTests.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.servlet.mvc;
+
+import java.util.List;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.AssertThrows;
+import org.springframework.web.servlet.support.WebContentGenerator;
+
+/**
+ * @author Rick Evans
+ */
+public class WebContentInterceptorTests extends TestCase {
+
+ private MockHttpServletRequest request;
+
+ private MockHttpServletResponse response;
+
+
+ protected void setUp() throws Exception {
+ request = new MockHttpServletRequest();
+ request.setMethod(WebContentGenerator.METHOD_GET);
+ response = new MockHttpServletResponse();
+ }
+
+
+ public void testPreHandleSetsCacheSecondsOnMatchingRequest() throws Exception {
+ WebContentInterceptor interceptor = new WebContentInterceptor();
+ interceptor.setCacheSeconds(10);
+
+ interceptor.preHandle(request, response, null);
+
+ List expiresHeaders = response.getHeaders("Expires");
+ assertNotNull("'Expires' header not set (must be) : null", expiresHeaders);
+ assertTrue("'Expires' header not set (must be) : empty", expiresHeaders.size() > 0);
+ List cacheControlHeaders = response.getHeaders("Cache-Control");
+ assertNotNull("'Cache-Control' header not set (must be) : null", cacheControlHeaders);
+ assertTrue("'Cache-Control' header not set (must be) : empty", cacheControlHeaders.size() > 0);
+ }
+
+ public void testPreHandleSetsCacheSecondsOnMatchingRequestWithCustomCacheMapping() throws Exception {
+ Properties mappings = new Properties();
+ mappings.setProperty("**/*handle.vm", "-1");
+
+ WebContentInterceptor interceptor = new WebContentInterceptor();
+ interceptor.setCacheSeconds(10);
+ interceptor.setCacheMappings(mappings);
+
+ request.setRequestURI("http://localhost:7070/example/adminhandle.vm");
+ interceptor.preHandle(request, response, null);
+
+ List expiresHeaders = response.getHeaders("Expires");
+ assertTrue("'Expires' header set (must not be) : empty", expiresHeaders.size() == 0);
+ List cacheControlHeaders = response.getHeaders("Cache-Control");
+ assertTrue("'Cache-Control' header set (must not be) : empty", cacheControlHeaders.size() == 0);
+
+ request.setRequestURI("http://localhost:7070/example/bingo.html");
+ interceptor.preHandle(request, response, null);
+
+ expiresHeaders = response.getHeaders("Expires");
+ assertNotNull("'Expires' header not set (must be) : null", expiresHeaders);
+ assertTrue("'Expires' header not set (must be) : empty", expiresHeaders.size() > 0);
+ cacheControlHeaders = response.getHeaders("Cache-Control");
+ assertNotNull("'Cache-Control' header not set (must be) : null", cacheControlHeaders);
+ assertTrue("'Cache-Control' header not set (must be) : empty", cacheControlHeaders.size() > 0);
+ }
+
+ public void testPreHandleSetsCacheSecondsOnMatchingRequestWithNoCaching() throws Exception {
+ WebContentInterceptor interceptor = new WebContentInterceptor();
+ interceptor.setCacheSeconds(0);
+
+ interceptor.preHandle(request, response, null);
+
+ List expiresHeaders = response.getHeaders("Expires");
+ assertNotNull("'Expires' header not set (must be) : null", expiresHeaders);
+ assertTrue("'Expires' header not set (must be) : empty", expiresHeaders.size() > 0);
+ List cacheControlHeaders = response.getHeaders("Cache-Control");
+ assertNotNull("'Cache-Control' header not set (must be) : null", cacheControlHeaders);
+ assertTrue("'Cache-Control' header not set (must be) : empty", cacheControlHeaders.size() > 0);
+ }
+
+ public void testPreHandleSetsCacheSecondsOnMatchingRequestWithCachingDisabled() throws Exception {
+ WebContentInterceptor interceptor = new WebContentInterceptor();
+ interceptor.setCacheSeconds(-1);
+
+ interceptor.preHandle(request, response, null);
+
+ List expiresHeaders = response.getHeaders("Expires");
+ assertTrue("'Expires' header set (must not be) : empty", expiresHeaders.size() == 0);
+ List cacheControlHeaders = response.getHeaders("Cache-Control");
+ assertTrue("'Cache-Control' header set (must not be) : empty", cacheControlHeaders.size() == 0);
+ }
+
+ public void testSetPathMatcherToNull() throws Exception {
+ new AssertThrows(IllegalArgumentException.class) {
+ public void test() throws Exception {
+ WebContentInterceptor interceptor = new WebContentInterceptor();
+ interceptor.setPathMatcher(null);
+ }
+ }.runTest();
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/WizardFormControllerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/WizardFormControllerTests.java
new file mode 100644
index 00000000000..b8e35f02671
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/WizardFormControllerTests.java
@@ -0,0 +1,428 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.servlet.mvc;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.TestBean;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.util.ObjectUtils;
+import org.springframework.validation.BindException;
+import org.springframework.validation.Errors;
+import org.springframework.web.servlet.ModelAndView;
+
+/**
+ * @author Juergen Hoeller
+ * @since 29.04.2003
+ */
+public class WizardFormControllerTests extends TestCase {
+
+ public void testNoDirtyPageChange() throws Exception {
+ AbstractWizardFormController wizard = new TestWizardController();
+ wizard.setAllowDirtyBack(false);
+ wizard.setAllowDirtyForward(false);
+ wizard.setPageAttribute("currentPage");
+
+ assertTrue(wizard.getFormSessionAttributeName() != wizard.getPageSessionAttributeName());
+ HttpSession session = performRequest(wizard, null, null, 0, null, 0, "currentPage");
+
+ Properties params = new Properties();
+ params.setProperty(AbstractWizardFormController.PARAM_TARGET + "1", "value");
+ performRequest(wizard, session, null, 0, null, 0, "currentPage");
+ // not allowed to go to 1
+
+ params.clear();
+ params.setProperty("name", "myname");
+ params.setProperty(AbstractWizardFormController.PARAM_PAGE, "0");
+ params.setProperty(AbstractWizardFormController.PARAM_TARGET + "1", "value");
+ performRequest(wizard, session, params, 1, "myname", 0, "currentPage");
+ // name set -> now allowed to go to 1
+
+ params.clear();
+ params.setProperty("name", "myname");
+ performRequest(wizard, session, params, 1, "myname", 0, "currentPage");
+ // name set -> now allowed to go to 1
+
+ params.clear();
+ params.setProperty("name", "myname");
+ params.setProperty(AbstractWizardFormController.PARAM_TARGET + "1.x", "value");
+ performRequest(wizard, session, params, 1, "myname", 0, "currentPage");
+ // name set -> now allowed to go to 1
+
+ params.clear();
+ params.setProperty("name", "myname");
+ params.setProperty(AbstractWizardFormController.PARAM_TARGET + "1.y", "value");
+ performRequest(wizard, session, params, 1, "myname", 0, "currentPage");
+ // name set -> now allowed to go to 1
+
+ params.clear();
+ params.setProperty("date", "not a date");
+ params.setProperty(AbstractWizardFormController.PARAM_TARGET + "1.y", "value");
+ performRequest(wizard, session, params, 1, "myname", 0, "currentPage");
+ // name set -> now allowed to go to 1
+
+ params.clear();
+ params.setProperty(AbstractWizardFormController.PARAM_TARGET + "0", "value");
+ performRequest(wizard, session, params, 1, "myname", 0, "currentPage");
+ // not allowed to go to 0
+
+ params.clear();
+ params.setProperty("age", "32");
+ params.setProperty(AbstractWizardFormController.PARAM_PAGE, "1");
+ params.setProperty(AbstractWizardFormController.PARAM_TARGET + "0", "value");
+ performRequest(wizard, session, params, 0, "myname", 32, "currentPage");
+ // age set -> now allowed to go to 0
+
+ params.clear();
+ params.setProperty(AbstractWizardFormController.PARAM_FINISH, "value");
+ performRequest(wizard, session, params, -1, "myname", 32, null);
+ }
+
+ public void testCustomSessionAttributes() throws Exception {
+ AbstractWizardFormController wizard = new TestWizardController() {
+ protected String getFormSessionAttributeName() {
+ return "myFormAttr";
+ }
+ protected String getPageSessionAttributeName() {
+ return "myPageAttr";
+ }
+ };
+ wizard.setAllowDirtyBack(false);
+ wizard.setAllowDirtyForward(false);
+ wizard.setPageAttribute("currentPage");
+
+ HttpSession session = performRequest(wizard, null, null, 0, null, 0, "currentPage");
+ assertTrue(session.getAttribute("myFormAttr") instanceof TestBean);
+ assertEquals(new Integer(0), session.getAttribute("myPageAttr"));
+
+ Properties params = new Properties();
+ params.setProperty(AbstractWizardFormController.PARAM_TARGET + "1", "value");
+ performRequest(wizard, session, null, 0, null, 0, "currentPage");
+ // not allowed to go to 1
+
+ params.clear();
+ params.setProperty("name", "myname");
+ params.setProperty(AbstractWizardFormController.PARAM_PAGE, "0");
+ params.setProperty(AbstractWizardFormController.PARAM_TARGET + "1", "value");
+ performRequest(wizard, session, params, 1, "myname", 0, "currentPage");
+ // name set -> now allowed to go to 1
+
+ params.clear();
+ params.setProperty("age", "32");
+ params.setProperty(AbstractWizardFormController.PARAM_FINISH, "value");
+ performRequest(wizard, session, params, -1, "myname", 32, "currentPage");
+ }
+
+ public void testCustomRequestDependentSessionAttributes() throws Exception {
+ AbstractWizardFormController wizard = new TestWizardController() {
+ protected String getFormSessionAttributeName(HttpServletRequest request) {
+ return "myFormAttr" + request.getParameter("formAttr");
+ }
+ protected String getPageSessionAttributeName(HttpServletRequest request) {
+ return "myPageAttr" + request.getParameter("pageAttr");
+ }
+ };
+ wizard.setAllowDirtyBack(false);
+ wizard.setAllowDirtyForward(false);
+ wizard.setPageAttribute("currentPage");
+
+ HttpSession session = performRequest(wizard, null, null, 0, null, 0, "currentPage");
+ assertTrue(session.getAttribute("myFormAttr1") instanceof TestBean);
+ assertEquals(new Integer(0), session.getAttribute("myPageAttr2"));
+
+ Properties params = new Properties();
+ params.setProperty(AbstractWizardFormController.PARAM_TARGET + "1", "value");
+ performRequest(wizard, session, null, 0, null, 0, "currentPage");
+ // not allowed to go to 1
+
+ params.clear();
+ params.setProperty("name", "myname");
+ params.setProperty(AbstractWizardFormController.PARAM_PAGE, "0");
+ params.setProperty(AbstractWizardFormController.PARAM_TARGET + "1", "value");
+ performRequest(wizard, session, params, 1, "myname", 0, "currentPage");
+ // name set -> now allowed to go to 1
+
+ params.clear();
+ params.setProperty("age", "32");
+ params.setProperty(AbstractWizardFormController.PARAM_FINISH, "value");
+ performRequest(wizard, session, params, -1, "myname", 32, "currentPage");
+ }
+
+ public void testDirtyBack() throws Exception {
+ AbstractWizardFormController wizard = new TestWizardController();
+ wizard.setAllowDirtyBack(true);
+ wizard.setAllowDirtyForward(false);
+ HttpSession session = performRequest(wizard, null, null, 0, null, 0, null);
+
+ Properties params = new Properties();
+ params.setProperty(AbstractWizardFormController.PARAM_TARGET + "1", "value");
+ performRequest(wizard, session, params, 0, null, 0, null);
+ // not allowed to go to 1
+
+ params.clear();
+ params.setProperty("name", "myname");
+ params.setProperty(AbstractWizardFormController.PARAM_TARGET + "1", "value");
+ performRequest(wizard, session, params, 1, "myname", 0, null);
+ // name set -> now allowed to go to 1
+
+ params.clear();
+ params.setProperty(AbstractWizardFormController.PARAM_TARGET + "0", "value");
+ performRequest(wizard, session, params, 0, "myname", 0, null);
+ // dirty back -> allowed to go to 0
+
+ params.clear();
+ params.setProperty(AbstractWizardFormController.PARAM_FINISH, "value");
+ performRequest(wizard, session, params, 1, "myname", 0, null);
+ // finish while dirty -> show dirty page (1)
+
+ params.clear();
+ params.setProperty("age", "32");
+ params.setProperty(AbstractWizardFormController.PARAM_FINISH, "value");
+ performRequest(wizard, session, params, -1, "myname", 32, null);
+ // age set -> now allowed to finish
+ }
+
+ public void testDirtyForward() throws Exception {
+ AbstractWizardFormController wizard = new TestWizardController();
+ wizard.setAllowDirtyBack(false);
+ wizard.setAllowDirtyForward(true);
+ HttpSession session = performRequest(wizard, null, null, 0, null, 0, null);
+
+ Properties params = new Properties();
+ params.setProperty(AbstractWizardFormController.PARAM_TARGET + "1", "value");
+ performRequest(wizard, session, params, 1, null, 0, null);
+ // dirty forward -> allowed to go to 1
+
+ params.clear();
+ params.setProperty(AbstractWizardFormController.PARAM_TARGET + "0", "value");
+ performRequest(wizard, session, params, 1, null, 0, null);
+ // not allowed to go to 0
+
+ params.clear();
+ params.setProperty("age", "32");
+ params.setProperty(AbstractWizardFormController.PARAM_TARGET + "0", "value");
+ performRequest(wizard, session, params, 0, null, 32, null);
+ // age set -> now allowed to go to 0
+
+ params.clear();
+ params.setProperty(AbstractWizardFormController.PARAM_FINISH, "value");
+ performRequest(wizard, session, params, 0, null, 32, null);
+ // finish while dirty -> show dirty page (0)
+
+ params.clear();
+ params.setProperty("name", "myname");
+ params.setProperty(AbstractWizardFormController.PARAM_FINISH + ".x", "value");
+ performRequest(wizard, session, params, -1, "myname", 32, null);
+ // name set -> now allowed to finish
+ }
+
+ public void testSubmitWithoutValidation() throws Exception {
+ AbstractWizardFormController wizard = new TestWizardController();
+ wizard.setAllowDirtyBack(false);
+ wizard.setAllowDirtyForward(false);
+ HttpSession session = performRequest(wizard, null, null, 0, null, 0, null);
+
+ Properties params = new Properties();
+ params.setProperty("formChange", "true");
+ params.setProperty(AbstractWizardFormController.PARAM_TARGET + "1", "value");
+ performRequest(wizard, session, params, 1, null, 0, null);
+ // no validation -> allowed to go to 1
+
+ params.clear();
+ params.setProperty(AbstractWizardFormController.PARAM_TARGET + "0", "value");
+ performRequest(wizard, session, params, 1, null, 0, null);
+ // not allowed to go to 0
+
+ params.clear();
+ params.setProperty("age", "32");
+ params.setProperty(AbstractWizardFormController.PARAM_TARGET + "0", "value");
+ performRequest(wizard, session, params, 0, null, 32, null);
+ // age set -> now allowed to go to 0
+
+ params.clear();
+ params.setProperty(AbstractWizardFormController.PARAM_FINISH, "value");
+ performRequest(wizard, session, params, 0, null, 32, null);
+ // finish while dirty -> show dirty page (0)
+
+ params.clear();
+ params.setProperty("name", "myname");
+ params.setProperty(AbstractWizardFormController.PARAM_FINISH + ".x", "value");
+ performRequest(wizard, session, params, -1, "myname", 32, null);
+ // name set -> now allowed to finish
+ }
+
+ public void testCancel() throws Exception {
+ AbstractWizardFormController wizard = new TestWizardController();
+ HttpSession session = performRequest(wizard, null, null, 0, null, 0, null);
+ Properties params = new Properties();
+ params.setProperty(AbstractWizardFormController.PARAM_CANCEL, "value");
+ performRequest(wizard, session, params, -2, null, 0, null);
+
+ assertTrue(session.getAttribute(wizard.getFormSessionAttributeName()) == null);
+ assertTrue(session.getAttribute(wizard.getPageSessionAttributeName()) == null);
+
+ session = performRequest(wizard, null, null, 0, null, 0, null);
+ params = new Properties();
+ params.setProperty(AbstractWizardFormController.PARAM_CANCEL + ".y", "value");
+ performRequest(wizard, session, params, -2, null, 0, null);
+ }
+
+ public void testInvalidSubmit() throws Exception {
+ AbstractWizardFormController wizard = new TestWizardController();
+ wizard.setAllowDirtyBack(false);
+ wizard.setAllowDirtyForward(false);
+ wizard.setPageAttribute("currentPage");
+ HttpSession session = performRequest(wizard, null, null, 0, null, 0, "currentPage");
+
+ Properties params = new Properties();
+ params.setProperty("name", "myname");
+ params.setProperty(AbstractWizardFormController.PARAM_TARGET + "1", "value");
+ performRequest(wizard, session, params, 1, "myname", 0, "currentPage");
+
+ params.clear();
+ params.setProperty("age", "32");
+ params.setProperty(AbstractWizardFormController.PARAM_TARGET + "0", "value");
+ performRequest(wizard, session, params, 0, "myname", 32, "currentPage");
+
+ params.clear();
+ params.setProperty(AbstractWizardFormController.PARAM_FINISH, "value");
+ performRequest(wizard, session, params, -1, "myname", 32, null);
+
+ params.clear();
+ params.setProperty(AbstractWizardFormController.PARAM_FINISH, "value");
+ performRequest(wizard, session, params, 0, null, 0, "currentPage");
+ // returned to initial page of new wizard form
+ }
+
+ private HttpSession performRequest(
+ AbstractWizardFormController wizard, HttpSession session, Properties params,
+ int target, String name, int age, String pageAttr) throws Exception {
+
+ MockHttpServletRequest request = new MockHttpServletRequest((params != null ? "POST" : "GET"), "/wizard");
+ request.addParameter("formAttr", "1");
+ request.addParameter("pageAttr", "2");
+ if (params != null) {
+ for (Iterator it = params.keySet().iterator(); it.hasNext();) {
+ String param = (String) it.next();
+ request.addParameter(param, params.getProperty(param));
+ }
+ }
+ request.setSession(session);
+ request.setAttribute("target", new Integer(target));
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = wizard.handleRequest(request, response);
+ if (target >= 0) {
+ assertTrue("Page " + target + " returned", ("page" + target).equals(mv.getViewName()));
+ if (pageAttr != null) {
+ assertTrue("Page attribute set", (new Integer(target)).equals(mv.getModel().get(pageAttr)));
+ assertTrue("Correct model size", mv.getModel().size() == 3);
+ }
+ else {
+ assertTrue("Correct model size", mv.getModel().size() == 2);
+ }
+ assertTrue(
+ request.getSession().getAttribute(wizard.getFormSessionAttributeName(request)) instanceof TestBean);
+ assertEquals(new Integer(target),
+ request.getSession().getAttribute(wizard.getPageSessionAttributeName(request)));
+ }
+ else if (target == -1) {
+ assertTrue("Success target returned", "success".equals(mv.getViewName()));
+ assertTrue("Correct model size", mv.getModel().size() == 1);
+ assertTrue(request.getSession().getAttribute(wizard.getFormSessionAttributeName(request)) == null);
+ assertTrue(request.getSession().getAttribute(wizard.getPageSessionAttributeName(request)) == null);
+ }
+ else if (target == -2) {
+ assertTrue("Cancel view returned", "cancel".equals(mv.getViewName()));
+ assertTrue("Correct model size", mv.getModel().size() == 1);
+ assertTrue(request.getSession().getAttribute(wizard.getFormSessionAttributeName(request)) == null);
+ assertTrue(request.getSession().getAttribute(wizard.getPageSessionAttributeName(request)) == null);
+ }
+ TestBean tb = (TestBean) mv.getModel().get("tb");
+ assertTrue("Has model", tb != null);
+ assertTrue("Name is " + name, ObjectUtils.nullSafeEquals(name, tb.getName()));
+ assertTrue("Age is " + age, tb.getAge() == age);
+ Errors errors = (Errors) mv.getModel().get(BindException.MODEL_KEY_PREFIX + "tb");
+ if (params != null && params.containsKey("formChange")) {
+ assertNotNull(errors);
+ assertFalse(errors.hasErrors());
+ }
+ return request.getSession(false);
+ }
+
+
+ private static class TestWizardController extends AbstractWizardFormController {
+
+ public TestWizardController() {
+ setCommandClass(TestBean.class);
+ setCommandName("tb");
+ setPages(new String[] {"page0", "page1"});
+ }
+
+ protected Map referenceData(HttpServletRequest request, int page) throws Exception {
+ assertEquals(new Integer(page), request.getAttribute("target"));
+ return super.referenceData(request, page);
+ }
+
+ protected boolean suppressValidation(HttpServletRequest request, Object command) {
+ return (request.getParameter("formChange") != null);
+ }
+
+ protected void validatePage(Object command, Errors errors, int page) {
+ TestBean tb = (TestBean) command;
+ switch (page) {
+ case 0:
+ if (tb.getName() == null) {
+ errors.rejectValue("name", "NAME_REQUIRED", null, "Name is required");
+ }
+ break;
+ case 1:
+ if (tb.getAge() == 0) {
+ errors.rejectValue("age", "AGE_REQUIRED", null, "Age is required");
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid page number");
+ }
+ }
+
+ protected ModelAndView processFinish(
+ HttpServletRequest request, HttpServletResponse response, Object command, BindException errors)
+ throws ServletException, IOException {
+ assertTrue(getCurrentPage(request) == 0 || getCurrentPage(request) == 1);
+ return new ModelAndView("success", getCommandName(), command);
+ }
+
+ protected ModelAndView processCancel(
+ HttpServletRequest request, HttpServletResponse response, Object command, BindException errors)
+ throws ServletException, IOException {
+ assertTrue(getCurrentPage(request) == 0 || getCurrentPage(request) == 1);
+ return new ModelAndView("cancel", getCommandName(), command);
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/AdminController.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/AdminController.java
new file mode 100644
index 00000000000..650e201d0fc
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/AdminController.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.servlet.mvc.mapping;
+
+import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
+
+/**
+ * @author Rob Harrop
+ */
+public class AdminController extends MultiActionController {
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/BuyForm.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/BuyForm.java
new file mode 100644
index 00000000000..3f42bdd83af
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/BuyForm.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.servlet.mvc.mapping;
+
+import org.springframework.web.servlet.mvc.SimpleFormController;
+
+/**
+ * @author Rob Harrop
+ */
+public class BuyForm extends SimpleFormController {
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/Controller.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/Controller.java
new file mode 100644
index 00000000000..307b6ab80d8
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/Controller.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.servlet.mvc.mapping;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.web.servlet.ModelAndView;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class Controller implements org.springframework.web.servlet.mvc.Controller {
+
+ public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
+ return new ModelAndView("indexView");
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/ControllerBeanNameHandlerMappingTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/ControllerBeanNameHandlerMappingTests.java
new file mode 100644
index 00000000000..5351f35b581
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/ControllerBeanNameHandlerMappingTests.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.web.servlet.mvc.mapping;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.web.context.support.XmlWebApplicationContext;
+import org.springframework.web.servlet.HandlerExecutionChain;
+import org.springframework.web.servlet.HandlerMapping;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class ControllerBeanNameHandlerMappingTests extends TestCase {
+
+ public static final String LOCATION = "/org/springframework/web/servlet/mvc/mapping/name-mapping.xml";
+
+ private XmlWebApplicationContext wac;
+
+ private HandlerMapping hm;
+
+ public void setUp() throws Exception {
+ MockServletContext sc = new MockServletContext("");
+ this.wac = new XmlWebApplicationContext();
+ this.wac.setServletContext(sc);
+ this.wac.setConfigLocations(new String[] {LOCATION});
+ this.wac.refresh();
+ this.hm = (HandlerMapping) this.wac.getBean("mapping");
+ }
+
+ public void testIndexUri() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/index");
+ HandlerExecutionChain chain = this.hm.getHandler(request);
+ assertEquals(this.wac.getBean("index"), chain.getHandler());
+ }
+
+ public void testMapSimpleUri() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/welcome");
+ HandlerExecutionChain chain = this.hm.getHandler(request);
+ assertEquals(this.wac.getBean("welcome"), chain.getHandler());
+ }
+
+ public void testWithContextPath() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myapp/welcome");
+ request.setContextPath("/myapp");
+ HandlerExecutionChain chain = this.hm.getHandler(request);
+ assertEquals(this.wac.getBean("welcome"), chain.getHandler());
+ }
+
+ public void testWithMultiActionControllerMapping() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/admin");
+ HandlerExecutionChain chain = this.hm.getHandler(request);
+ assertEquals(this.wac.getBean("admin"), chain.getHandler());
+ }
+
+ public void testWithoutControllerSuffix() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/buy");
+ HandlerExecutionChain chain = this.hm.getHandler(request);
+ assertEquals(this.wac.getBean("buy"), chain.getHandler());
+ }
+
+}
\ No newline at end of file
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/ControllerClassNameHandlerMappingTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/ControllerClassNameHandlerMappingTests.java
new file mode 100644
index 00000000000..e822f40f043
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/ControllerClassNameHandlerMappingTests.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.web.servlet.mvc.mapping;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.web.context.support.XmlWebApplicationContext;
+import org.springframework.web.servlet.HandlerExecutionChain;
+import org.springframework.web.servlet.HandlerMapping;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class ControllerClassNameHandlerMappingTests extends TestCase {
+
+ public static final String LOCATION = "/org/springframework/web/servlet/mvc/mapping/class-mapping.xml";
+
+ private XmlWebApplicationContext wac;
+
+ private HandlerMapping hm;
+
+ private HandlerMapping hm2;
+
+ private HandlerMapping hm3;
+
+ private HandlerMapping hm4;
+
+ public void setUp() throws Exception {
+ MockServletContext sc = new MockServletContext("");
+ this.wac = new XmlWebApplicationContext();
+ this.wac.setServletContext(sc);
+ this.wac.setConfigLocations(new String[] {LOCATION});
+ this.wac.refresh();
+ this.hm = (HandlerMapping) this.wac.getBean("mapping");
+ this.hm2 = (HandlerMapping) this.wac.getBean("mapping2");
+ this.hm3 = (HandlerMapping) this.wac.getBean("mapping3");
+ this.hm4 = (HandlerMapping) this.wac.getBean("mapping4");
+ }
+
+ public void testIndexUri() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
+ HandlerExecutionChain chain = this.hm.getHandler(request);
+ assertEquals(this.wac.getBean("index"), chain.getHandler());
+ }
+
+ public void testMapSimpleUri() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/welcome");
+ HandlerExecutionChain chain = this.hm.getHandler(request);
+ assertEquals(this.wac.getBean("welcome"), chain.getHandler());
+ }
+
+ public void testWithContextPath() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myapp/welcome");
+ request.setContextPath("/myapp");
+ HandlerExecutionChain chain = this.hm.getHandler(request);
+ assertEquals(this.wac.getBean("welcome"), chain.getHandler());
+ }
+
+ public void testWithMultiActionControllerMapping() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/admin/user");
+ HandlerExecutionChain chain = this.hm.getHandler(request);
+ assertEquals(this.wac.getBean("admin"), chain.getHandler());
+
+ request = new MockHttpServletRequest("GET", "/admin/product");
+ chain = this.hm.getHandler(request);
+ assertEquals(this.wac.getBean("admin"), chain.getHandler());
+ }
+
+ public void testWithoutControllerSuffix() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/buyform");
+ HandlerExecutionChain chain = this.hm.getHandler(request);
+ assertEquals(this.wac.getBean("buy"), chain.getHandler());
+ }
+
+ public void testWithBasePackage() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myapp/mvc/mapping/welcome");
+ HandlerExecutionChain chain = this.hm2.getHandler(request);
+ assertEquals(this.wac.getBean("welcome"), chain.getHandler());
+ }
+
+ public void testWithBasePackageAndCaseSensitive() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myapp/mvc/mapping/buyForm");
+ HandlerExecutionChain chain = this.hm2.getHandler(request);
+ assertEquals(this.wac.getBean("buy"), chain.getHandler());
+ }
+
+ public void testWithFullBasePackage() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myapp/welcome");
+ HandlerExecutionChain chain = this.hm3.getHandler(request);
+ assertEquals(this.wac.getBean("welcome"), chain.getHandler());
+ }
+
+ public void testWithRootAsBasePackage() throws Exception {
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myapp/org/springframework/web/servlet/mvc/mapping/welcome");
+ HandlerExecutionChain chain = this.hm4.getHandler(request);
+ assertEquals(this.wac.getBean("welcome"), chain.getHandler());
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/WelcomeController.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/WelcomeController.java
new file mode 100644
index 00000000000..5c36b0989d3
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/WelcomeController.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * 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.springframework.web.servlet.mvc.mapping;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.servlet.mvc.Controller;
+
+/**
+ * @author Rob Harrop
+ */
+public class WelcomeController implements Controller {
+
+ public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
+ return new ModelAndView("welcomeView");
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/class-mapping.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/class-mapping.xml
new file mode 100644
index 00000000000..214b8498b31
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/class-mapping.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/name-mapping.xml b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/name-mapping.xml
new file mode 100644
index 00000000000..67ec8eda816
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/mapping/name-mapping.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/multiaction/MultiActionControllerTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/multiaction/MultiActionControllerTests.java
new file mode 100644
index 00000000000..ddf7bd44517
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/mvc/multiaction/MultiActionControllerTests.java
@@ -0,0 +1,720 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.web.servlet.mvc.multiaction;
+
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import junit.framework.TestCase;
+
+import org.springframework.beans.FatalBeanException;
+import org.springframework.beans.TestBean;
+import org.springframework.context.ApplicationContextException;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockHttpSession;
+import org.springframework.web.HttpSessionRequiredException;
+import org.springframework.web.bind.ServletRequestBindingException;
+import org.springframework.web.servlet.ModelAndView;
+
+/**
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @author Colin Sampaleanu
+ * @author Rob Harrop
+ * @author Sam Brannen
+ */
+public class MultiActionControllerTests extends TestCase {
+
+ public void testDefaultInternalPathMethodNameResolver() throws Exception {
+ doDefaultTestInternalPathMethodNameResolver("/foo.html", "foo");
+ doDefaultTestInternalPathMethodNameResolver("/foo/bar.html", "bar");
+ doDefaultTestInternalPathMethodNameResolver("/bugal.xyz", "bugal");
+ doDefaultTestInternalPathMethodNameResolver("/x/y/z/q/foo.html", "foo");
+ doDefaultTestInternalPathMethodNameResolver("qqq.q", "qqq");
+ }
+
+ private void doDefaultTestInternalPathMethodNameResolver(String in, String expected) throws Exception {
+ MultiActionController rc = new MultiActionController();
+ HttpServletRequest request = new MockHttpServletRequest("GET", in);
+ String actual = rc.getMethodNameResolver().getHandlerMethodName(request);
+ assertEquals("Wrong method name resolved", expected, actual);
+ }
+
+ public void testCustomizedInternalPathMethodNameResolver() throws Exception {
+ doTestCustomizedInternalPathMethodNameResolver("/foo.html", "my", null, "myfoo");
+ doTestCustomizedInternalPathMethodNameResolver("/foo/bar.html", null, "Handler", "barHandler");
+ doTestCustomizedInternalPathMethodNameResolver("/Bugal.xyz", "your", "Method", "yourBugalMethod");
+ }
+
+ private void doTestCustomizedInternalPathMethodNameResolver(String in, String prefix, String suffix, String expected)
+ throws Exception {
+
+ MultiActionController rc = new MultiActionController();
+ InternalPathMethodNameResolver resolver = new InternalPathMethodNameResolver();
+ if (prefix != null) {
+ resolver.setPrefix(prefix);
+ }
+ if (suffix != null) {
+ resolver.setSuffix(suffix);
+ }
+ rc.setMethodNameResolver(resolver);
+ HttpServletRequest request = new MockHttpServletRequest("GET", in);
+ String actual = rc.getMethodNameResolver().getHandlerMethodName(request);
+ assertEquals("Wrong method name resolved", expected, actual);
+ }
+
+ public void testParameterMethodNameResolver() throws NoSuchRequestHandlingMethodException {
+ ParameterMethodNameResolver mnr = new ParameterMethodNameResolver();
+
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo.html");
+ request.addParameter("action", "bar");
+ assertEquals("bar", mnr.getHandlerMethodName(request));
+
+ request = new MockHttpServletRequest("GET", "/foo.html");
+ try {
+ mnr.getHandlerMethodName(request);
+ fail("Should have thrown NoSuchRequestHandlingMethodException");
+ }
+ catch (NoSuchRequestHandlingMethodException expected) {
+ }
+
+ request = new MockHttpServletRequest("GET", "/foo.html");
+ request.addParameter("action", "");
+ try {
+ mnr.getHandlerMethodName(request);
+ fail("Should have thrown NoSuchRequestHandlingMethodException");
+ }
+ catch (NoSuchRequestHandlingMethodException expected) {
+ }
+
+ request = new MockHttpServletRequest("GET", "/foo.html");
+ request.addParameter("action", " ");
+ try {
+ mnr.getHandlerMethodName(request);
+ fail("Should have thrown NoSuchRequestHandlingMethodException");
+ }
+ catch (NoSuchRequestHandlingMethodException expected) {
+ }
+ }
+
+ public void testParameterMethodNameResolverWithCustomParamName() throws NoSuchRequestHandlingMethodException {
+ ParameterMethodNameResolver mnr = new ParameterMethodNameResolver();
+ mnr.setParamName("myparam");
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo.html");
+ request.addParameter("myparam", "bar");
+ assertEquals("bar", mnr.getHandlerMethodName(request));
+ }
+
+ public void testParameterMethodNameResolverWithParamNames() throws NoSuchRequestHandlingMethodException {
+ ParameterMethodNameResolver resolver = new ParameterMethodNameResolver();
+ resolver.setDefaultMethodName("default");
+ resolver.setMethodParamNames(new String[] { "hello", "spring", "colin" });
+ Properties logicalMappings = new Properties();
+ logicalMappings.setProperty("hello", "goodbye");
+ logicalMappings.setProperty("nina", "colin");
+ resolver.setLogicalMappings(logicalMappings);
+
+ // verify default handler
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("this will not match anything", "whatever");
+ assertEquals("default", resolver.getHandlerMethodName(request));
+
+ // verify first resolution strategy (action=method)
+ request = new MockHttpServletRequest();
+ request.addParameter("action", "reset");
+ assertEquals("reset", resolver.getHandlerMethodName(request));
+ // this one also tests logical mapping
+ request = new MockHttpServletRequest();
+ request.addParameter("action", "nina");
+ assertEquals("colin", resolver.getHandlerMethodName(request));
+
+ // now validate second resolution strategy (parameter existence)
+ // this also tests logical mapping
+ request = new MockHttpServletRequest();
+ request.addParameter("hello", "whatever");
+ assertEquals("goodbye", resolver.getHandlerMethodName(request));
+
+ request = new MockHttpServletRequest();
+ request.addParameter("spring", "whatever");
+ assertEquals("spring", resolver.getHandlerMethodName(request));
+
+ request = new MockHttpServletRequest();
+ request.addParameter("hello", "whatever");
+ request.addParameter("spring", "whatever");
+ assertEquals("goodbye", resolver.getHandlerMethodName(request));
+
+ request = new MockHttpServletRequest();
+ request.addParameter("colin", "whatever");
+ request.addParameter("spring", "whatever");
+ assertEquals("spring", resolver.getHandlerMethodName(request));
+
+ // validate image button handling
+ request = new MockHttpServletRequest();
+ request.addParameter("spring.x", "whatever");
+ assertEquals("spring", resolver.getHandlerMethodName(request));
+
+ request = new MockHttpServletRequest();
+ request.addParameter("hello.x", "whatever");
+ request.addParameter("spring", "whatever");
+ assertEquals("goodbye", resolver.getHandlerMethodName(request));
+ }
+
+ public void testParameterMethodNameResolverWithDefaultMethodName() throws NoSuchRequestHandlingMethodException {
+ ParameterMethodNameResolver mnr = new ParameterMethodNameResolver();
+ mnr.setDefaultMethodName("foo");
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo.html");
+ request.addParameter("action", "bar");
+ assertEquals("bar", mnr.getHandlerMethodName(request));
+ request = new MockHttpServletRequest("GET", "/foo.html");
+ assertEquals("foo", mnr.getHandlerMethodName(request));
+ }
+
+ public void testInvokesCorrectMethod() throws Exception {
+ TestMaController mc = new TestMaController();
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/welcome.html");
+ HttpServletResponse response = new MockHttpServletResponse();
+ Properties p = new Properties();
+ p.put("/welcome.html", "welcome");
+ PropertiesMethodNameResolver mnr = new PropertiesMethodNameResolver();
+ mnr.setMappings(p);
+ mc.setMethodNameResolver(mnr);
+
+ ModelAndView mv = mc.handleRequest(request, response);
+ assertTrue("Invoked welcome method", mc.wasInvoked("welcome"));
+ assertTrue("view name is welcome", mv.getViewName().equals("welcome"));
+ assertTrue("Only one method invoked", mc.getInvokedMethods() == 1);
+
+ mc = new TestMaController();
+ request = new MockHttpServletRequest("GET", "/subdir/test.html");
+ response = new MockHttpServletResponse();
+ mv = mc.handleRequest(request, response);
+ assertTrue("Invoked test method", mc.wasInvoked("test"));
+ assertTrue("view name is subdir_test", mv.getViewName().equals("test"));
+ assertTrue("Only one method invoked", mc.getInvokedMethods() == 1);
+ }
+
+ public void testPathMatching() throws Exception {
+ TestMaController mc = new TestMaController();
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/welcome.html");
+ HttpServletResponse response = new MockHttpServletResponse();
+ Properties p = new Properties();
+ p.put("/welc*.html", "welcome");
+ PropertiesMethodNameResolver mn = new PropertiesMethodNameResolver();
+ mn.setMappings(p);
+ mc.setMethodNameResolver(mn);
+
+ ModelAndView mv = mc.handleRequest(request, response);
+ assertTrue("Invoked welcome method", mc.wasInvoked("welcome"));
+ assertTrue("view name is welcome", mv.getViewName().equals("welcome"));
+ assertTrue("Only one method invoked", mc.getInvokedMethods() == 1);
+
+ mc = new TestMaController();
+ mc.setMethodNameResolver(mn);
+ request = new MockHttpServletRequest("GET", "/nomatch");
+ response = new MockHttpServletResponse();
+ try {
+ mv = mc.handleRequest(request, response);
+ }
+ catch (Exception expected) {
+ }
+ assertFalse("Not invoking welcome method", mc.wasInvoked("welcome"));
+ assertTrue("No method invoked", mc.getInvokedMethods() == 0);
+ }
+
+ public void testInvokesCorrectMethodOnDelegate() throws Exception {
+ MultiActionController mac = new MultiActionController();
+ TestDelegate d = new TestDelegate();
+ mac.setDelegate(d);
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/test.html");
+ HttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mac.handleRequest(request, response);
+ assertTrue("view name is test", mv.getViewName().equals("test"));
+ assertTrue("Delegate was invoked", d.invoked);
+ }
+
+ public void testInvokesCorrectMethodWithSession() throws Exception {
+ TestMaController mc = new TestMaController();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/inSession.html");
+ request.setSession(new MockHttpSession(null));
+ HttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ assertTrue("Invoked inSession method", mc.wasInvoked("inSession"));
+ assertTrue("view name is welcome", mv.getViewName().equals("inSession"));
+ assertTrue("Only one method invoked", mc.getInvokedMethods() == 1);
+
+ request = new MockHttpServletRequest("GET", "/inSession.html");
+ response = new MockHttpServletResponse();
+ try {
+
+ mc.handleRequest(request, response);
+ fail("Must have rejected request without session");
+ }
+ catch (ServletException expected) {
+ }
+ }
+
+ public void testInvokesCommandMethodNoSession() throws Exception {
+ TestMaController mc = new TestMaController();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/commandNoSession.html");
+ request.addParameter("name", "rod");
+ request.addParameter("age", "32");
+ HttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ assertTrue("Invoked commandNoSession method", mc.wasInvoked("commandNoSession"));
+ assertTrue("view name is commandNoSession", mv.getViewName().equals("commandNoSession"));
+ assertTrue("Only one method invoked", mc.getInvokedMethods() == 1);
+ }
+
+ public void testInvokesCommandMethodWithSession() throws Exception {
+ TestMaController mc = new TestMaController();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/commandInSession.html");
+ request.addParameter("name", "rod");
+ request.addParameter("age", "32");
+
+ request.setSession(new MockHttpSession(null));
+ HttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mv = mc.handleRequest(request, response);
+ assertTrue("Invoked commandInSession method", mc.wasInvoked("commandInSession"));
+ assertTrue("view name is commandInSession", mv.getViewName().equals("commandInSession"));
+ assertTrue("Only one method invoked", mc.getInvokedMethods() == 1);
+
+ request = new MockHttpServletRequest("GET", "/commandInSession.html");
+ response = new MockHttpServletResponse();
+ try {
+
+ mc.handleRequest(request, response);
+ fail("Must have rejected request without session");
+ }
+ catch (ServletException expected) {
+ }
+ }
+
+ public void testSessionRequiredCatchable() throws Exception {
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/testSession.html");
+ HttpServletResponse response = new MockHttpServletResponse();
+ TestMaController contr = new TestSessionRequiredController();
+ try {
+ contr.handleRequest(request, response);
+ fail("Should have thrown exception");
+ }
+ catch (HttpSessionRequiredException ex) {
+ // assertTrue("session required", ex.equals(t));
+ }
+ request = new MockHttpServletRequest("GET", "/testSession.html");
+ response = new MockHttpServletResponse();
+ contr = new TestSessionRequiredExceptionHandler();
+ ModelAndView mv = contr.handleRequest(request, response);
+ assertTrue("Name is ok", mv.getViewName().equals("handle(SRE)"));
+ }
+
+ private void testExceptionNoHandler(TestMaController mc, Throwable t) throws Exception {
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/testException.html");
+ request.setAttribute(TestMaController.THROWABLE_ATT, t);
+ HttpServletResponse response = new MockHttpServletResponse();
+ try {
+ mc.handleRequest(request, response);
+ fail("Should have thrown exception");
+ }
+ catch (Throwable ex) {
+ assertTrue(ex.equals(t));
+ }
+ }
+
+ private void testExceptionNoHandler(Throwable t) throws Exception {
+ testExceptionNoHandler(new TestMaController(), t);
+ }
+
+ public void testExceptionNoHandler() throws Exception {
+ testExceptionNoHandler(new Exception());
+
+ // must go straight through
+ testExceptionNoHandler(new ServletException());
+
+ // subclass of servlet exception
+ testExceptionNoHandler(new ServletRequestBindingException("foo"));
+ testExceptionNoHandler(new RuntimeException());
+ testExceptionNoHandler(new Error());
+ }
+
+ public void testLastModifiedDefault() throws Exception {
+ TestMaController mc = new TestMaController();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/welcome.html");
+ long lastMod = mc.getLastModified(request);
+ assertTrue("default last modified is -1", lastMod == -1L);
+ }
+
+ public void testLastModifiedWithMethod() throws Exception {
+ LastModController mc = new LastModController();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/welcome.html");
+ long lastMod = mc.getLastModified(request);
+ assertTrue("last modified with method is > -1", lastMod == mc.getLastModified(request));
+ }
+
+ private ModelAndView testHandlerCaughtException(TestMaController mc, Throwable t) throws Exception {
+ HttpServletRequest request = new MockHttpServletRequest("GET", "/testException.html");
+ request.setAttribute(TestMaController.THROWABLE_ATT, t);
+ HttpServletResponse response = new MockHttpServletResponse();
+ return mc.handleRequest(request, response);
+ }
+
+ public void testHandlerCaughtException() throws Exception {
+ TestMaController mc = new TestExceptionHandler();
+ ModelAndView mv = testHandlerCaughtException(mc, new Exception());
+ assertNotNull("ModelAndView must not be null", mv);
+ assertTrue("mv name is handle(Exception)", "handle(Exception)".equals(mv.getViewName()));
+ assertTrue("Invoked correct method", mc.wasInvoked("handle(Exception)"));
+
+ // WILL GET RUNTIME EXCEPTIONS TOO
+ testExceptionNoHandler(mc, new Error());
+
+ mc = new TestServletExceptionHandler();
+ mv = testHandlerCaughtException(mc, new ServletException());
+ assertTrue(mv.getViewName().equals("handle(ServletException)"));
+ assertTrue("Invoke correct method", mc.wasInvoked("handle(ServletException)"));
+
+ mv = testHandlerCaughtException(mc, new ServletRequestBindingException("foo"));
+ assertTrue(mv.getViewName().equals("handle(ServletException)"));
+ assertTrue("Invoke correct method", mc.wasInvoked("handle(ServletException)"));
+
+ // Check it doesn't affect unknown exceptions
+ testExceptionNoHandler(mc, new RuntimeException());
+ testExceptionNoHandler(mc, new Error());
+ testExceptionNoHandler(mc, new SQLException());
+ testExceptionNoHandler(mc, new Exception());
+
+ mc = new TestRuntimeExceptionHandler();
+ mv = testHandlerCaughtException(mc, new RuntimeException());
+ assertTrue(mv.getViewName().equals("handle(RTE)"));
+ assertTrue("Invoke correct method", mc.wasInvoked("handle(RTE)"));
+ mv = testHandlerCaughtException(mc, new FatalBeanException(null, null));
+ assertTrue(mv.getViewName().equals("handle(RTE)"));
+ assertTrue("Invoke correct method", mc.wasInvoked("handle(RTE)"));
+
+ testExceptionNoHandler(mc, new SQLException());
+ testExceptionNoHandler(mc, new Exception());
+ }
+
+ public void testHandlerReturnsMap() throws Exception {
+ Map model = new HashMap();
+ model.put("message", "Hello World!");
+
+ MultiActionController mac = new ModelOnlyMultiActionController(model);
+
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/welcome.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mav = mac.handleRequest(request, response);
+
+ assertNotNull("ModelAndView cannot be null", mav);
+ assertFalse("ModelAndView should not have a view", mav.hasView());
+ assertEquals(model, mav.getModel());
+ }
+
+ public void testExceptionHandlerReturnsMap() throws Exception {
+ Map model = new HashMap();
+
+ MultiActionController mac = new ModelOnlyMultiActionController(model);
+
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/index.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mav = mac.handleRequest(request, response);
+
+ assertNotNull("ModelAndView cannot be null", mav);
+ assertFalse("ModelAndView should not have a view", mav.hasView());
+ assertTrue(model.containsKey("exception"));
+ }
+
+ public void testCannotCallExceptionHandlerDirectly() throws Exception {
+ Map model = new HashMap();
+
+ MultiActionController mac = new ModelOnlyMultiActionController(model);
+
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/handleIllegalStateException.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mav = mac.handleRequest(request, response);
+ assertEquals(HttpServletResponse.SC_NOT_FOUND, response.getStatus());
+ }
+
+ public void testHandlerReturnsVoid() throws Exception {
+ MultiActionController mac = new VoidMultiActionController();
+
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/welcome.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mav = mac.handleRequest(request, response);
+
+ assertNull("ModelAndView must be null", mav);
+ }
+
+ public void testExceptionHandlerReturnsVoid() throws Exception {
+ MultiActionController mac = new VoidMultiActionController();
+
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/index.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mav = mac.handleRequest(request, response);
+
+ assertNull("ModelAndView must be null", mav);
+ assertEquals("exception", response.getContentAsString());
+ }
+
+ public void testHandlerReturnsString() throws Exception {
+ MultiActionController mac = new StringMultiActionController();
+
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/welcome.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mav = mac.handleRequest(request, response);
+
+ assertNotNull("ModelAndView cannot be null", mav);
+ assertTrue("ModelAndView must have a view", mav.hasView());
+ assertEquals("Verifying view name", "welcomeString", mav.getViewName());
+ }
+
+ public void testExceptionHandlerReturnsString() throws Exception {
+ MultiActionController mac = new StringMultiActionController();
+
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/index.html");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ModelAndView mav = mac.handleRequest(request, response);
+
+ assertNotNull("ModelAndView cannot be null", mav);
+ assertTrue("ModelAndView must have a view", mav.hasView());
+ assertEquals("Verifying view name", "handleIllegalStateExceptionString", mav.getViewName());
+ }
+
+
+ /** No error handlers */
+ public static class TestMaController extends MultiActionController {
+
+ public static final String THROWABLE_ATT = "throwable";
+
+ /** Method name -> object */
+ protected Map invoked = new HashMap();
+
+ public void clear() {
+ this.invoked.clear();
+ }
+
+ public ModelAndView welcome(HttpServletRequest request, HttpServletResponse response) {
+ this.invoked.put("welcome", Boolean.TRUE);
+ return new ModelAndView("welcome");
+ }
+
+ public ModelAndView commandNoSession(HttpServletRequest request, HttpServletResponse response, TestBean command) {
+ this.invoked.put("commandNoSession", Boolean.TRUE);
+
+ String pname = request.getParameter("name");
+ String page = request.getParameter("age");
+ // ALLOW FOR NULL
+ if (pname == null) {
+ assertTrue("name null", command.getName() == null);
+ }
+ else {
+ assertTrue("name param set", pname.equals(command.getName()));
+ }
+ // if (page == null)
+ // assertTrue("age default", command.getAge() == 0);
+ // else
+ // assertTrue("age set", command.getName().equals(pname));
+ // assertTrue("a",
+ // command.getAge().equals(request.getParameter("name")));
+ return new ModelAndView("commandNoSession");
+ }
+
+ public ModelAndView inSession(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
+ this.invoked.put("inSession", Boolean.TRUE);
+ assertTrue("session non null", session != null);
+ return new ModelAndView("inSession");
+ }
+
+ public ModelAndView commandInSession(HttpServletRequest request, HttpServletResponse response,
+ HttpSession session, TestBean command) {
+ this.invoked.put("commandInSession", Boolean.TRUE);
+ assertTrue("session non null", session != null);
+ return new ModelAndView("commandInSession");
+ }
+
+ public ModelAndView test(HttpServletRequest request, HttpServletResponse response) {
+ this.invoked.put("test", Boolean.TRUE);
+ return new ModelAndView("test");
+ }
+
+ public ModelAndView testException(HttpServletRequest request, HttpServletResponse response) throws Throwable {
+ this.invoked.put("testException", Boolean.TRUE);
+ Throwable t = (Throwable) request.getAttribute(THROWABLE_ATT);
+ if (t != null) {
+ throw t;
+ }
+ else {
+ return new ModelAndView("no throwable");
+ }
+ }
+
+ public boolean wasInvoked(String method) {
+ return this.invoked.get(method) != null;
+ }
+
+ public int getInvokedMethods() {
+ return this.invoked.size();
+ }
+ }
+
+
+ public static class TestDelegate {
+
+ boolean invoked;
+
+ public ModelAndView test(HttpServletRequest request, HttpServletResponse response) {
+ this.invoked = true;
+ return new ModelAndView("test");
+ }
+ }
+
+
+ public static class TestExceptionHandler extends TestMaController {
+
+ public ModelAndView handleAnyException(HttpServletRequest request, HttpServletResponse response, Exception ex) {
+ this.invoked.put("handle(Exception)", Boolean.TRUE);
+ return new ModelAndView("handle(Exception)");
+ }
+ }
+
+
+ public static class TestRuntimeExceptionHandler extends TestMaController {
+
+ public ModelAndView handleRuntimeProblem(HttpServletRequest request, HttpServletResponse response,
+ RuntimeException ex) {
+ this.invoked.put("handle(RTE)", Boolean.TRUE);
+ return new ModelAndView("handle(RTE)");
+ }
+ }
+
+
+ public static class TestSessionRequiredController extends TestMaController {
+
+ public ModelAndView testSession(HttpServletRequest request, HttpServletResponse response, HttpSession sess) {
+ return null;
+ }
+ }
+
+
+ /** Extends previous to handle exception */
+ public static class TestSessionRequiredExceptionHandler extends TestSessionRequiredController {
+
+ public ModelAndView handleServletException(HttpServletRequest request, HttpServletResponse response,
+ HttpSessionRequiredException ex) {
+ this.invoked.put("handle(SRE)", Boolean.TRUE);
+ return new ModelAndView("handle(SRE)");
+ }
+ }
+
+ public static class TestServletExceptionHandler extends TestMaController {
+
+ public ModelAndView handleServletException(HttpServletRequest request, HttpServletResponse response,
+ ServletException ex) {
+ this.invoked.put("handle(ServletException)", Boolean.TRUE);
+ return new ModelAndView("handle(ServletException)");
+ }
+ }
+
+
+ public static class LastModController extends MultiActionController {
+
+ public static final String THROWABLE_ATT = "throwable";
+
+ /** Method name -> object */
+ protected HashMap invoked = new HashMap();
+
+ public void clear() {
+ this.invoked.clear();
+ }
+
+ public ModelAndView welcome(HttpServletRequest request, HttpServletResponse response) {
+ this.invoked.put("welcome", Boolean.TRUE);
+ return new ModelAndView("welcome");
+ }
+
+ /** Always says content is up to date */
+ public long welcomeLastModified(HttpServletRequest request) {
+ return 1111L;
+ }
+ }
+
+
+ public static class ModelOnlyMultiActionController extends MultiActionController {
+
+ private final Map model;
+
+ public ModelOnlyMultiActionController(Map model) throws ApplicationContextException {
+ this.model = model;
+ }
+
+ public Map welcome(HttpServletRequest request, HttpServletResponse response) {
+ return this.model;
+ }
+
+ public Map index(HttpServletRequest request, HttpServletResponse response) {
+ throw new IllegalStateException();
+ }
+
+ public Map handleIllegalStateException(HttpServletRequest request, HttpServletResponse response,
+ IllegalStateException ex) {
+ this.model.put("exception", ex);
+ return this.model;
+ }
+ }
+
+
+ public static class VoidMultiActionController extends MultiActionController {
+
+ public void welcome(HttpServletRequest request, HttpServletResponse response) {
+ }
+
+ public void index(HttpServletRequest request, HttpServletResponse response) {
+ throw new IllegalStateException();
+ }
+
+ public void handleIllegalStateException(HttpServletRequest request, HttpServletResponse response,
+ IllegalStateException ex) throws IOException {
+ response.getWriter().write("exception");
+ }
+ }
+
+
+ public static class StringMultiActionController extends MultiActionController {
+
+ public String welcome(HttpServletRequest request, HttpServletResponse response) {
+ return "welcomeString";
+ }
+
+ public String index(HttpServletRequest request, HttpServletResponse response) {
+ throw new IllegalStateException();
+ }
+
+ public String handleIllegalStateException(HttpServletRequest request, HttpServletResponse response,
+ IllegalStateException ex) throws IOException {
+ return "handleIllegalStateExceptionString";
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/AbstractTagTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/AbstractTagTests.java
new file mode 100644
index 00000000000..59d76364aac
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/AbstractTagTests.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.servlet.tags;
+
+import java.io.StringWriter;
+
+import javax.servlet.jsp.JspWriter;
+
+import junit.framework.TestCase;
+
+import org.springframework.mock.web.MockBodyContent;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockPageContext;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.servlet.DispatcherServlet;
+import org.springframework.web.servlet.LocaleResolver;
+import org.springframework.web.servlet.SimpleWebApplicationContext;
+import org.springframework.web.servlet.ThemeResolver;
+import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
+import org.springframework.web.servlet.theme.FixedThemeResolver;
+
+/**
+ * Abstract base class for testing tags: provides createPageContext.
+ *
+ * @author Alef Arendsen
+ * @author Juergen Hoeller
+ */
+public abstract class AbstractTagTests extends TestCase {
+
+ protected MockPageContext createPageContext() {
+ MockServletContext sc = new MockServletContext();
+ SimpleWebApplicationContext wac = new SimpleWebApplicationContext();
+ wac.setServletContext(sc);
+ wac.setNamespace("test");
+ wac.refresh();
+
+ MockHttpServletRequest request = new MockHttpServletRequest(sc);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ if (inDispatcherServlet()) {
+ request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
+ LocaleResolver lr = new AcceptHeaderLocaleResolver();
+ request.setAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE, lr);
+ ThemeResolver tr = new FixedThemeResolver();
+ request.setAttribute(DispatcherServlet.THEME_RESOLVER_ATTRIBUTE, tr);
+ request.setAttribute(DispatcherServlet.THEME_SOURCE_ATTRIBUTE, wac);
+ }
+ else {
+ sc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
+ }
+
+ return new MockPageContext(sc, request, response);
+ }
+
+ protected boolean inDispatcherServlet() {
+ return true;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/BindTagOutsideDispatcherServletTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/BindTagOutsideDispatcherServletTests.java
new file mode 100644
index 00000000000..e4fce1213fc
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/BindTagOutsideDispatcherServletTests.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2002-2005 the original author or authors.
+ *
+ * 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.springframework.web.servlet.tags;
+
+/**
+ * @author Juergen Hoeller
+ * @since 14.01.2005
+ */
+public class BindTagOutsideDispatcherServletTests extends BindTagTests {
+
+ protected boolean inDispatcherServlet() {
+ return false;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/BindTagTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/BindTagTests.java
new file mode 100644
index 00000000000..747ee0e9a1e
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/BindTagTests.java
@@ -0,0 +1,1040 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.servlet.tags;
+
+import java.beans.PropertyEditorSupport;
+import java.io.StringWriter;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Set;
+
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.PageContext;
+import javax.servlet.jsp.tagext.Tag;
+
+import org.springframework.beans.IndexedTestBean;
+import org.springframework.beans.NestedTestBean;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.propertyeditors.CustomDateEditor;
+import org.springframework.validation.BindException;
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.DataBinder;
+import org.springframework.validation.Errors;
+import org.springframework.web.bind.ServletRequestDataBinder;
+import org.springframework.web.servlet.support.BindStatus;
+import org.springframework.web.servlet.tags.form.FormTag;
+import org.springframework.web.servlet.tags.form.TagWriter;
+
+/**
+ * @author Juergen Hoeller
+ * @author Alef Arendsen
+ * @author Mark Fisher
+ */
+public class BindTagTests extends AbstractTagTests {
+
+ public void testBindTagWithoutErrors() throws JspException {
+ PageContext pc = createPageContext();
+ Errors errors = new ServletRequestDataBinder(new TestBean(), "tb").getBindingResult();
+ pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors);
+ BindTag tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status != null);
+ assertTrue("Correct expression", status.getExpression() == null);
+ assertTrue("Correct value", status.getValue() == null);
+ assertTrue("Correct displayValue", "".equals(status.getDisplayValue()));
+ assertTrue("Correct isError", !status.isError());
+ assertTrue("Correct errorCodes", status.getErrorCodes().length == 0);
+ assertTrue("Correct errorMessages", status.getErrorMessages().length == 0);
+ assertTrue("Correct errorCode", "".equals(status.getErrorCode()));
+ assertTrue("Correct errorMessage", "".equals(status.getErrorMessage()));
+ assertTrue("Correct errorMessagesAsString", "".equals(status.getErrorMessagesAsString(",")));
+ }
+
+ public void testBindTagWithGlobalErrors() throws JspException {
+ PageContext pc = createPageContext();
+ Errors errors = new ServletRequestDataBinder(new TestBean(), "tb").getBindingResult();
+ errors.reject("code1", "message1");
+ pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors);
+
+ BindTag tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status != null);
+ assertTrue("Correct expression", status.getExpression() == null);
+ assertTrue("Correct value", status.getValue() == null);
+ assertTrue("Correct displayValue", "".equals(status.getDisplayValue()));
+ assertTrue("Correct isError", status.isError());
+ assertTrue("Correct errorCodes", status.getErrorCodes().length == 1);
+ assertTrue("Correct errorMessages", status.getErrorMessages().length == 1);
+ assertTrue("Correct errorCode", "code1".equals(status.getErrorCode()));
+ assertTrue("Correct errorMessage", "message1".equals(status.getErrorMessage()));
+ assertTrue("Correct errorMessagesAsString", "message1".equals(status.getErrorMessagesAsString(",")));
+
+ tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb.*");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status != null);
+ assertTrue("Correct expression", "*".equals(status.getExpression()));
+ assertTrue("Correct value", status.getValue() == null);
+ assertTrue("Correct displayValue", "".equals(status.getDisplayValue()));
+ assertTrue("Correct isError", status.isError());
+ assertTrue("Correct errorCodes", status.getErrorCodes().length == 1);
+ assertTrue("Correct errorMessages", status.getErrorMessages().length == 1);
+ assertTrue("Correct errorCode", "code1".equals(status.getErrorCode()));
+ assertTrue("Correct errorMessage", "message1".equals(status.getErrorMessage()));
+ assertTrue("Correct errorMessagesAsString", "message1".equals(status.getErrorMessagesAsString(",")));
+ }
+
+ public void testBindTagWithGlobalErrorsAndNoDefaultMessage() throws JspException {
+ PageContext pc = createPageContext();
+ Errors errors = new ServletRequestDataBinder(new TestBean(), "tb").getBindingResult();
+ errors.reject("code1");
+ pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors);
+
+ BindTag tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status != null);
+ assertTrue("Correct expression", status.getExpression() == null);
+ assertTrue("Correct value", status.getValue() == null);
+ assertTrue("Correct displayValue", "".equals(status.getDisplayValue()));
+ assertTrue("Correct isError", status.isError());
+ assertTrue("Correct errorCodes", status.getErrorCodes().length == 1);
+ assertTrue("Correct errorCode", "code1".equals(status.getErrorCode()));
+
+ tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb.*");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status != null);
+ assertTrue("Correct expression", "*".equals(status.getExpression()));
+ assertTrue("Correct value", status.getValue() == null);
+ assertTrue("Correct displayValue", "".equals(status.getDisplayValue()));
+ assertTrue("Correct isError", status.isError());
+ assertTrue("Correct errorCodes", status.getErrorCodes().length == 1);
+ assertTrue("Correct errorCode", "code1".equals(status.getErrorCode()));
+ }
+
+ public void testBindTagWithGlobalErrorsAndDefaultMessageOnly() throws JspException {
+ PageContext pc = createPageContext();
+ Errors errors = new ServletRequestDataBinder(new TestBean(), "tb").getBindingResult();
+ errors.reject(null, "message1");
+ pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors);
+
+ BindTag tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status != null);
+ assertTrue("Correct expression", status.getExpression() == null);
+ assertTrue("Correct value", status.getValue() == null);
+ assertTrue("Correct displayValue", "".equals(status.getDisplayValue()));
+ assertTrue("Correct isError", status.isError());
+ assertTrue("Correct errorMessages", status.getErrorMessages().length == 1);
+ assertTrue("Correct errorMessage", "message1".equals(status.getErrorMessage()));
+ assertTrue("Correct errorMessagesAsString", "message1".equals(status.getErrorMessagesAsString(",")));
+
+ tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb.*");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status != null);
+ assertTrue("Correct expression", "*".equals(status.getExpression()));
+ assertTrue("Correct value", status.getValue() == null);
+ assertTrue("Correct displayValue", "".equals(status.getDisplayValue()));
+ assertTrue("Correct isError", status.isError());
+ assertTrue("Correct errorMessages", status.getErrorMessages().length == 1);
+ assertTrue("Correct errorMessage", "message1".equals(status.getErrorMessage()));
+ assertTrue("Correct errorMessagesAsString", "message1".equals(status.getErrorMessagesAsString(",")));
+ }
+
+ public void testBindStatusGetErrorMessagesAsString() throws JspException {
+ // one error (should not include delimiter)
+ PageContext pc = createPageContext();
+ Errors errors = new ServletRequestDataBinder(new TestBean(), "tb").getBindingResult();
+ errors.reject("code1", null, "message1");
+ pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors);
+ BindTag tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb");
+ tag.doStartTag();
+ BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertEquals("Error messages String should be 'message1'",
+ status.getErrorMessagesAsString(","), "message1");
+
+ // two errors
+ pc = createPageContext();
+ errors = new ServletRequestDataBinder(new TestBean(), "tb").getBindingResult();
+ errors.reject("code1", null, "message1");
+ errors.reject("code1", null, "message2");
+ pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors);
+ tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb");
+ tag.doStartTag();
+ status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertEquals("Error messages String should be 'message1,message2'",
+ status.getErrorMessagesAsString(","), "message1,message2");
+
+ // no errors
+ pc = createPageContext();
+ errors = new ServletRequestDataBinder(new TestBean(), "tb").getBindingResult();
+ pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors);
+ tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb");
+ tag.doStartTag();
+ status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertEquals("Error messages String should be ''", status.getErrorMessagesAsString(","), "");
+ }
+
+ public void testBindTagWithFieldErrors() throws JspException {
+ PageContext pc = createPageContext();
+ TestBean tb = new TestBean();
+ tb.setName("name1");
+ Errors errors = new ServletRequestDataBinder(tb, "tb").getBindingResult();
+ errors.rejectValue("name", "code1", "message & 1");
+ errors.rejectValue("name", "code2", "message2");
+ errors.rejectValue("age", "code2", "message2");
+ pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors);
+
+ BindTag tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb.name");
+ tag.setHtmlEscape("true");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status != null);
+ assertTrue("Correct expression", "name".equals(status.getExpression()));
+ assertTrue("Correct value", "name1".equals(status.getValue()));
+ assertTrue("Correct displayValue", "name1".equals(status.getDisplayValue()));
+ assertTrue("Correct isError", status.isError());
+ assertTrue("Correct errorCodes", status.getErrorCodes().length == 2);
+ assertTrue("Correct errorMessages", status.getErrorMessages().length == 2);
+ assertTrue("Correct errorCode", "code1".equals(status.getErrorCode()));
+ assertTrue("Correct errorCode", "code1".equals(status.getErrorCodes()[0]));
+ assertTrue("Correct errorCode", "code2".equals(status.getErrorCodes()[1]));
+ assertTrue("Correct errorMessage", "message & 1".equals(status.getErrorMessage()));
+ assertTrue("Correct errorMessage", "message & 1".equals(status.getErrorMessages()[0]));
+ assertTrue("Correct errorMessage", "message2".equals(status.getErrorMessages()[1]));
+ assertTrue("Correct errorMessagesAsString",
+ "message & 1 - message2".equals(status.getErrorMessagesAsString(" - ")));
+
+ tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb.age");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status != null);
+ assertTrue("Correct expression", "age".equals(status.getExpression()));
+ assertTrue("Correct value", new Integer(0).equals(status.getValue()));
+ assertTrue("Correct displayValue", "0".equals(status.getDisplayValue()));
+ assertTrue("Correct isError", status.isError());
+ assertTrue("Correct errorCodes", status.getErrorCodes().length == 1);
+ assertTrue("Correct errorMessages", status.getErrorMessages().length == 1);
+ assertTrue("Correct errorCode", "code2".equals(status.getErrorCode()));
+ assertTrue("Correct errorMessage", "message2".equals(status.getErrorMessage()));
+ assertTrue("Correct errorMessagesAsString", "message2".equals(status.getErrorMessagesAsString(" - ")));
+
+ tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb.*");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status != null);
+ assertTrue("Correct expression", "*".equals(status.getExpression()));
+ assertTrue("Correct value", status.getValue() == null);
+ assertTrue("Correct displayValue", "".equals(status.getDisplayValue()));
+ assertTrue("Correct isError", status.isError());
+ assertTrue("Correct errorCodes", status.getErrorCodes().length == 3);
+ assertTrue("Correct errorMessages", status.getErrorMessages().length == 3);
+ assertTrue("Correct errorCode", "code1".equals(status.getErrorCode()));
+ assertTrue("Correct errorCode", "code1".equals(status.getErrorCodes()[0]));
+ assertTrue("Correct errorCode", "code2".equals(status.getErrorCodes()[1]));
+ assertTrue("Correct errorCode", "code2".equals(status.getErrorCodes()[2]));
+ assertTrue("Correct errorMessage", "message & 1".equals(status.getErrorMessage()));
+ assertTrue("Correct errorMessage", "message & 1".equals(status.getErrorMessages()[0]));
+ assertTrue("Correct errorMessage", "message2".equals(status.getErrorMessages()[1]));
+ assertTrue("Correct errorMessage", "message2".equals(status.getErrorMessages()[2]));
+ }
+
+ public void testBindTagWithFieldErrorsAndNoDefaultMessage() throws JspException {
+ PageContext pc = createPageContext();
+ TestBean tb = new TestBean();
+ tb.setName("name1");
+ Errors errors = new ServletRequestDataBinder(tb, "tb").getBindingResult();
+ errors.rejectValue("name", "code1");
+ errors.rejectValue("name", "code2");
+ errors.rejectValue("age", "code2");
+ pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors);
+
+ BindTag tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb.name");
+ tag.setHtmlEscape("true");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status != null);
+ assertTrue("Correct expression", "name".equals(status.getExpression()));
+ assertTrue("Correct value", "name1".equals(status.getValue()));
+ assertTrue("Correct displayValue", "name1".equals(status.getDisplayValue()));
+ assertTrue("Correct isError", status.isError());
+ assertTrue("Correct errorCodes", status.getErrorCodes().length == 2);
+ assertTrue("Correct errorCode", "code1".equals(status.getErrorCode()));
+ assertTrue("Correct errorCode", "code1".equals(status.getErrorCodes()[0]));
+ assertTrue("Correct errorCode", "code2".equals(status.getErrorCodes()[1]));
+
+ tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb.age");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status != null);
+ assertTrue("Correct expression", "age".equals(status.getExpression()));
+ assertTrue("Correct value", new Integer(0).equals(status.getValue()));
+ assertTrue("Correct displayValue", "0".equals(status.getDisplayValue()));
+ assertTrue("Correct isError", status.isError());
+ assertTrue("Correct errorCodes", status.getErrorCodes().length == 1);
+ assertTrue("Correct errorCode", "code2".equals(status.getErrorCode()));
+
+ tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb.*");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status != null);
+ assertTrue("Correct expression", "*".equals(status.getExpression()));
+ assertTrue("Correct value", status.getValue() == null);
+ assertTrue("Correct displayValue", "".equals(status.getDisplayValue()));
+ assertTrue("Correct isError", status.isError());
+ assertTrue("Correct errorCodes", status.getErrorCodes().length == 3);
+ assertTrue("Correct errorCode", "code1".equals(status.getErrorCode()));
+ assertTrue("Correct errorCode", "code1".equals(status.getErrorCodes()[0]));
+ assertTrue("Correct errorCode", "code2".equals(status.getErrorCodes()[1]));
+ assertTrue("Correct errorCode", "code2".equals(status.getErrorCodes()[2]));
+ }
+
+ public void testBindTagWithFieldErrorsAndDefaultMessageOnly() throws JspException {
+ PageContext pc = createPageContext();
+ TestBean tb = new TestBean();
+ tb.setName("name1");
+ Errors errors = new ServletRequestDataBinder(tb, "tb").getBindingResult();
+ errors.rejectValue("name", null, "message & 1");
+ errors.rejectValue("name", null, "message2");
+ errors.rejectValue("age", null, "message2");
+ pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors);
+
+ BindTag tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb.name");
+ tag.setHtmlEscape("true");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status != null);
+ assertTrue("Correct expression", "name".equals(status.getExpression()));
+ assertTrue("Correct value", "name1".equals(status.getValue()));
+ assertTrue("Correct displayValue", "name1".equals(status.getDisplayValue()));
+ assertTrue("Correct isError", status.isError());
+ assertTrue("Correct errorMessages", status.getErrorMessages().length == 2);
+ assertTrue("Correct errorMessage", "message & 1".equals(status.getErrorMessage()));
+ assertTrue("Correct errorMessage", "message & 1".equals(status.getErrorMessages()[0]));
+ assertTrue("Correct errorMessage", "message2".equals(status.getErrorMessages()[1]));
+ assertTrue("Correct errorMessagesAsString",
+ "message & 1 - message2".equals(status.getErrorMessagesAsString(" - ")));
+
+ tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb.age");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status != null);
+ assertTrue("Correct expression", "age".equals(status.getExpression()));
+ assertTrue("Correct value", new Integer(0).equals(status.getValue()));
+ assertTrue("Correct displayValue", "0".equals(status.getDisplayValue()));
+ assertTrue("Correct isError", status.isError());
+ assertTrue("Correct errorMessages", status.getErrorMessages().length == 1);
+ assertTrue("Correct errorMessage", "message2".equals(status.getErrorMessage()));
+ assertTrue("Correct errorMessagesAsString", "message2".equals(status.getErrorMessagesAsString(" - ")));
+
+ tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb.*");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status != null);
+ assertTrue("Correct expression", "*".equals(status.getExpression()));
+ assertTrue("Correct value", status.getValue() == null);
+ assertTrue("Correct displayValue", "".equals(status.getDisplayValue()));
+ assertTrue("Correct isError", status.isError());
+ assertTrue("Correct errorMessages", status.getErrorMessages().length == 3);
+ assertTrue("Correct errorMessage", "message & 1".equals(status.getErrorMessage()));
+ assertTrue("Correct errorMessage", "message & 1".equals(status.getErrorMessages()[0]));
+ assertTrue("Correct errorMessage", "message2".equals(status.getErrorMessages()[1]));
+ assertTrue("Correct errorMessage", "message2".equals(status.getErrorMessages()[2]));
+ }
+
+ public void testBindTagWithNestedFieldErrors() throws JspException {
+ PageContext pc = createPageContext();
+ TestBean tb = new TestBean();
+ tb.setName("name1");
+ TestBean spouse = new TestBean();
+ spouse.setName("name2");
+ tb.setSpouse(spouse);
+ Errors errors = new ServletRequestDataBinder(tb, "tb").getBindingResult();
+ errors.rejectValue("spouse.name", "code1", "message1");
+ pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors);
+ BindTag tag = new BindTag();
+ tag.setPageContext(pc);
+ pc.setAttribute("myattr", "tb.spouse.name");
+ tag.setPath("${myattr}");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status != null);
+ assertTrue("Correct expression", "spouse.name".equals(status.getExpression()));
+ assertTrue("Correct value", "name2".equals(status.getValue()));
+ assertTrue("Correct displayValue", "name2".equals(status.getDisplayValue()));
+ assertTrue("Correct isError", status.isError());
+ assertTrue("Correct errorCodes", status.getErrorCodes().length == 1);
+ assertTrue("Correct errorMessages", status.getErrorMessages().length == 1);
+ assertTrue("Correct errorCode", "code1".equals(status.getErrorCode()));
+ assertTrue("Correct errorMessage", "message1".equals(status.getErrorMessage()));
+ assertTrue("Correct errorMessagesAsString", "message1".equals(status.getErrorMessagesAsString(" - ")));
+ }
+
+ public void testPropertyExposing() throws JspException {
+ PageContext pc = createPageContext();
+ TestBean tb = new TestBean();
+ tb.setName("name1");
+ Errors errors = new BindException(tb, "tb");
+ errors.rejectValue("name", "code1", null, "message & 1");
+ errors.rejectValue("name", "code2", null, "message2");
+ pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors);
+
+ // test global property (should be null)
+ BindTag tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ assertNull(tag.getProperty());
+
+ // test property set (tb.name)
+ tag.release();
+ tag.setPageContext(pc);
+ tag.setPath("tb.name");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ assertEquals("name", tag.getProperty());
+ }
+
+ public void testBindTagWithIndexedProperties() throws JspException {
+ PageContext pc = createPageContext();
+ IndexedTestBean tb = new IndexedTestBean();
+ Errors errors = new ServletRequestDataBinder(tb, "tb").getBindingResult();
+ errors.rejectValue("array[0]", "code1", "message1");
+ errors.rejectValue("array[0]", "code2", "message2");
+ pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors);
+
+ BindTag tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb.array[0]");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status != null);
+ assertTrue("Correct expression", "array[0]".equals(status.getExpression()));
+ assertTrue("Value is TestBean", status.getValue() instanceof TestBean);
+ assertTrue("Correct value", "name0".equals(((TestBean) status.getValue()).getName()));
+ assertTrue("Correct isError", status.isError());
+ assertTrue("Correct errorCodes", status.getErrorCodes().length == 2);
+ assertTrue("Correct errorMessages", status.getErrorMessages().length == 2);
+ assertTrue("Correct errorCode", "code1".equals(status.getErrorCodes()[0]));
+ assertTrue("Correct errorCode", "code2".equals(status.getErrorCodes()[1]));
+ assertTrue("Correct errorMessage", "message1".equals(status.getErrorMessages()[0]));
+ assertTrue("Correct errorMessage", "message2".equals(status.getErrorMessages()[1]));
+ }
+
+ public void testBindTagWithMappedProperties() throws JspException {
+ PageContext pc = createPageContext();
+ IndexedTestBean tb = new IndexedTestBean();
+ Errors errors = new ServletRequestDataBinder(tb, "tb").getBindingResult();
+ errors.rejectValue("map[key1]", "code1", "message1");
+ errors.rejectValue("map[key1]", "code2", "message2");
+ pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors);
+
+ BindTag tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb.map[key1]");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status != null);
+ assertTrue("Correct expression", "map[key1]".equals(status.getExpression()));
+ assertTrue("Value is TestBean", status.getValue() instanceof TestBean);
+ assertTrue("Correct value", "name4".equals(((TestBean) status.getValue()).getName()));
+ assertTrue("Correct isError", status.isError());
+ assertTrue("Correct errorCodes", status.getErrorCodes().length == 2);
+ assertTrue("Correct errorMessages", status.getErrorMessages().length == 2);
+ assertTrue("Correct errorCode", "code1".equals(status.getErrorCodes()[0]));
+ assertTrue("Correct errorCode", "code2".equals(status.getErrorCodes()[1]));
+ assertTrue("Correct errorMessage", "message1".equals(status.getErrorMessages()[0]));
+ assertTrue("Correct errorMessage", "message2".equals(status.getErrorMessages()[1]));
+ }
+
+ public void testBindTagWithIndexedPropertiesAndCustomEditor() throws JspException {
+ PageContext pc = createPageContext();
+ IndexedTestBean tb = new IndexedTestBean();
+ DataBinder binder = new ServletRequestDataBinder(tb, "tb");
+ binder.registerCustomEditor(TestBean.class, null, new PropertyEditorSupport() {
+ public String getAsText() {
+ return "something";
+ }
+ });
+ Errors errors = binder.getBindingResult();
+ errors.rejectValue("array[0]", "code1", "message1");
+ errors.rejectValue("array[0]", "code2", "message2");
+ pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors);
+
+ BindTag tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb.array[0]");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status != null);
+ assertTrue("Correct expression", "array[0]".equals(status.getExpression()));
+ // because of the custom editor getValue() should return a String
+ assertTrue("Value is TestBean", status.getValue() instanceof String);
+ assertTrue("Correct value", "something".equals(status.getValue()));
+ }
+
+ public void testBindTagWithToStringAndHtmlEscaping() throws JspException {
+ PageContext pc = createPageContext();
+ BindTag tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb.doctor");
+ tag.setHtmlEscape("true");
+ TestBean tb = new TestBean("somebody", 99);
+ NestedTestBean ntb = new NestedTestBean("juergen&eva");
+ tb.setDoctor(ntb);
+ pc.getRequest().setAttribute("tb", tb);
+ tag.doStartTag();
+ BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertEquals("doctor", status.getExpression());
+ assertTrue(status.getValue() instanceof NestedTestBean);
+ assertTrue(status.getDisplayValue().indexOf("juergen&eva") != -1);
+ }
+
+ public void testBindTagWithSetValueAndHtmlEscaping() throws JspException {
+ PageContext pc = createPageContext();
+ BindTag tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb.someSet");
+ tag.setHtmlEscape("true");
+ pc.getRequest().setAttribute("tb", new TestBean("juergen&eva", 99));
+ tag.doStartTag();
+ BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertEquals("someSet", status.getExpression());
+ assertTrue(status.getValue() instanceof Set);
+ }
+
+ public void testBindTagWithFieldButWithoutErrorsInstance() throws JspException {
+ PageContext pc = createPageContext();
+ BindTag tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb.name");
+ pc.getRequest().setAttribute("tb", new TestBean("juergen&eva", 99));
+ tag.doStartTag();
+ BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertEquals("name", status.getExpression());
+ assertEquals("juergen&eva", status.getValue());
+ }
+
+ public void testBindTagWithFieldButWithoutErrorsInstanceAndHtmlEscaping() throws JspException {
+ PageContext pc = createPageContext();
+ BindTag tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb.name");
+ tag.setHtmlEscape("true");
+ pc.getRequest().setAttribute("tb", new TestBean("juergen&eva", 99));
+ tag.doStartTag();
+ BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertEquals("name", status.getExpression());
+ assertEquals("juergen&eva", status.getValue());
+ }
+
+ public void testBindTagWithBeanButWithoutErrorsInstance() throws JspException {
+ PageContext pc = createPageContext();
+ BindTag tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb");
+ pc.getRequest().setAttribute("tb", new TestBean("juergen", 99));
+ tag.doStartTag();
+ BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertNull(status.getExpression());
+ assertNull(status.getValue());
+ }
+
+ public void testBindTagWithoutBean() throws JspException {
+ PageContext pc = createPageContext();
+ BindTag tag = new BindTag();
+ tag.setPageContext(pc);
+ tag.setPath("tb");
+ try {
+ tag.doStartTag();
+ fail("Should have thrown JspException");
+ }
+ catch (JspException ex) {
+ // expected
+ }
+ }
+
+
+ public void testBindErrorsTagWithoutErrors() throws JspException {
+ PageContext pc = createPageContext();
+ Errors errors = new ServletRequestDataBinder(new TestBean(), "tb").getBindingResult();
+ pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors);
+ BindErrorsTag tag = new BindErrorsTag();
+ tag.setPageContext(pc);
+ tag.setName("tb");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.SKIP_BODY);
+ assertTrue("Doesn't have errors variable", pc.getAttribute(BindErrorsTag.ERRORS_VARIABLE_NAME) == null);
+ }
+
+ public void testBindErrorsTagWithErrors() throws JspException {
+ PageContext pc = createPageContext();
+ Errors errors = new ServletRequestDataBinder(new TestBean(), "tb").getBindingResult();
+ errors.reject("test", null, "test");
+ pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors);
+ BindErrorsTag tag = new BindErrorsTag();
+ tag.setPageContext(pc);
+ tag.setName("tb");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ assertTrue("Has errors variable", pc.getAttribute(BindErrorsTag.ERRORS_VARIABLE_NAME, PageContext.REQUEST_SCOPE) == errors);
+ }
+
+ public void testBindErrorsTagWithoutBean() throws JspException {
+ PageContext pc = createPageContext();
+ BindErrorsTag tag = new BindErrorsTag();
+ tag.setPageContext(pc);
+ tag.setName("tb");
+ assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.SKIP_BODY);
+ }
+
+
+ public void testNestedPathDoEndTag() throws JspException {
+ PageContext pc = createPageContext();
+ NestedPathTag tag = new NestedPathTag();
+ tag.setPath("foo");
+ tag.setPageContext(pc);
+ tag.doStartTag();
+ int returnValue = tag.doEndTag();
+ assertEquals(Tag.EVAL_PAGE, returnValue);
+ assertNull(pc.getAttribute(NestedPathTag.NESTED_PATH_VARIABLE_NAME, PageContext.REQUEST_SCOPE));
+ }
+
+ public void testNestedPathDoEndTagWithNesting() throws JspException {
+ PageContext pc = createPageContext();
+ NestedPathTag tag = new NestedPathTag();
+ tag.setPath("foo");
+ tag.setPageContext(pc);
+ tag.doStartTag();
+
+ NestedPathTag anotherTag = new NestedPathTag();
+ anotherTag.setPageContext(pc);
+ anotherTag.setPath("bar");
+ anotherTag.doStartTag();
+ anotherTag.doEndTag();
+
+ assertEquals("foo.", pc.getAttribute(NestedPathTag.NESTED_PATH_VARIABLE_NAME, PageContext.REQUEST_SCOPE));
+
+ tag.doEndTag();
+ assertNull(pc.getAttribute(NestedPathTag.NESTED_PATH_VARIABLE_NAME, PageContext.REQUEST_SCOPE));
+ }
+
+ public void testNestedPathDoStartTagInternal() throws JspException {
+ PageContext pc = createPageContext();
+ NestedPathTag tag = new NestedPathTag();
+ tag.setPath("foo");
+ tag.setPageContext(pc);
+ int returnValue = tag.doStartTag();
+
+ assertEquals(Tag.EVAL_BODY_INCLUDE, returnValue);
+ assertEquals("foo.", pc.getAttribute(NestedPathTag.NESTED_PATH_VARIABLE_NAME, PageContext.REQUEST_SCOPE));
+ }
+
+ public void testNestedPathDoStartTagInternalWithNesting() throws JspException {
+ PageContext pc = createPageContext();
+ NestedPathTag tag = new NestedPathTag();
+ tag.setPath("foo");
+ tag.setPageContext(pc);
+ tag.doStartTag();
+ assertEquals("foo.", pc.getAttribute(NestedPathTag.NESTED_PATH_VARIABLE_NAME, PageContext.REQUEST_SCOPE));
+
+ NestedPathTag anotherTag = new NestedPathTag();
+ anotherTag.setPageContext(pc);
+ anotherTag.setPath("bar");
+ anotherTag.doStartTag();
+
+ assertEquals("foo.bar.", pc.getAttribute(NestedPathTag.NESTED_PATH_VARIABLE_NAME, PageContext.REQUEST_SCOPE));
+
+ NestedPathTag yetAnotherTag = new NestedPathTag();
+ yetAnotherTag.setPageContext(pc);
+ yetAnotherTag.setPath("boo");
+ yetAnotherTag.doStartTag();
+
+ assertEquals("foo.bar.boo.", pc.getAttribute(NestedPathTag.NESTED_PATH_VARIABLE_NAME, PageContext.REQUEST_SCOPE));
+
+ yetAnotherTag.doEndTag();
+
+ NestedPathTag andAnotherTag = new NestedPathTag();
+ andAnotherTag.setPageContext(pc);
+ andAnotherTag.setPath("boo2");
+ andAnotherTag.doStartTag();
+
+ assertEquals("foo.bar.boo2.", pc.getAttribute(NestedPathTag.NESTED_PATH_VARIABLE_NAME, PageContext.REQUEST_SCOPE));
+ }
+
+ public void testNestedPathWithBindTag() throws JspException {
+ PageContext pc = createPageContext();
+ Errors errors = new ServletRequestDataBinder(new TestBean(), "tb").getBindingResult();
+ pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors);
+
+ NestedPathTag nestedPathTag = new NestedPathTag();
+ nestedPathTag.setPath("tb");
+ nestedPathTag.setPageContext(pc);
+ nestedPathTag.doStartTag();
+
+ BindTag bindTag = new BindTag();
+ bindTag.setPageContext(pc);
+ bindTag.setPath("name");
+
+ assertTrue("Correct doStartTag return value", bindTag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status != null);
+ assertEquals("tb.name", status.getPath());
+ assertEquals("Correct field value", "", status.getDisplayValue());
+
+ BindTag bindTag2 = new BindTag();
+ bindTag2.setPageContext(pc);
+ bindTag2.setPath("age");
+
+ assertTrue("Correct doStartTag return value", bindTag2.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ BindStatus status2 = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status2 != null);
+ assertEquals("tb.age", status2.getPath());
+ assertEquals("Correct field value", "0", status2.getDisplayValue());
+
+ bindTag2.doEndTag();
+
+ BindStatus status3 = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertSame("Status matches previous status", status, status3);
+ assertEquals("tb.name", status.getPath());
+ assertEquals("Correct field value", "", status.getDisplayValue());
+
+ bindTag.doEndTag();
+ nestedPathTag.doEndTag();
+ }
+
+ public void testNestedPathWithBindTagWithIgnoreNestedPath() throws JspException {
+ PageContext pc = createPageContext();
+ Errors errors = new ServletRequestDataBinder(new TestBean(), "tb2").getBindingResult();
+ pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb2", errors);
+
+ NestedPathTag tag = new NestedPathTag();
+ tag.setPath("tb");
+ tag.setPageContext(pc);
+ tag.doStartTag();
+
+ BindTag bindTag = new BindTag();
+ bindTag.setPageContext(pc);
+ bindTag.setIgnoreNestedPath(true);
+ bindTag.setPath("tb2.name");
+
+ assertTrue("Correct doStartTag return value", bindTag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
+ BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
+ assertTrue("Has status variable", status != null);
+ assertEquals("tb2.name", status.getPath());
+ }
+
+ public void testTransformTagCorrectBehavior() throws JspException {
+ // first set up the pagecontext and the bean
+ PageContext pc = createPageContext();
+ TestBean tb = new TestBean();
+ DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
+ ServletRequestDataBinder binder = new ServletRequestDataBinder(tb, "tb");
+ CustomDateEditor l = new CustomDateEditor(df, true);
+ binder.registerCustomEditor(Date.class, l);
+ pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", binder.getBindingResult());
+
+ // execute the bind tag using the date property
+ BindTag bind = new BindTag();
+ bind.setPageContext(pc);
+ bind.setPath("tb.date");
+ bind.doStartTag();
+
+ // transform stuff
+ TransformTag transform = new TransformTag();
+ transform.setPageContext(pc);
+ pc.setAttribute("date", tb.getDate());
+ transform.setParent(bind);
+ transform.setValue("${date}");
+ transform.setVar("theDate");
+ transform.doStartTag();
+
+ assertNotNull(pc.getAttribute("theDate"));
+ assertEquals(pc.getAttribute("theDate"), df.format(tb.getDate()));
+
+ // try another time, this time using Strings
+ bind = new BindTag();
+ bind.setPageContext(pc);
+ bind.setPath("tb.name");
+ bind.doStartTag();
+
+ transform = new TransformTag();
+ transform.setPageContext(pc);
+ pc.setAttribute("string", "name");
+ transform.setValue("${string}");
+ transform.setParent(bind);
+ transform.setVar("theString");
+ transform.doStartTag();
+
+ assertNotNull(pc.getAttribute("theString"));
+ assertEquals(pc.getAttribute("theString"), "name");
+ }
+
+ public void testTransformTagWithHtmlEscape() throws JspException {
+ // first set up the PageContext and the bean
+ PageContext pc = createPageContext();
+ TestBean tb = new TestBean();
+ DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
+ ServletRequestDataBinder binder = new ServletRequestDataBinder(tb, "tb");
+ CustomDateEditor l = new CustomDateEditor(df, true);
+ binder.registerCustomEditor(Date.class, l);
+ pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", binder.getBindingResult());
+
+ // try another time, this time using Strings
+ BindTag bind = new BindTag();
+ bind.setPageContext(pc);
+ bind.setPath("tb.name");
+ bind.doStartTag();
+
+ TransformTag transform = new TransformTag();
+ transform.setPageContext(pc);
+ pc.setAttribute("string", "na -1);
+ }
+
+ protected final void assertAttributeNotPresent(String output, String attributeName) {
+ assertTrue("Unexpected attribute '" + attributeName + "' in output '" + output + "'.",
+ output.indexOf(attributeName + "=\"") < 0);
+ }
+
+ protected final void assertBlockTagContains(String output, String desiredContents) {
+ String contents = output.substring(output.indexOf(">") + 1, output.lastIndexOf("<"));
+ assertTrue("Expected to find '" + desiredContents + "' in the contents of block tag '" + output + "'",
+ contents.indexOf(desiredContents) > -1);
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/form/CheckboxTagTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/form/CheckboxTagTests.java
new file mode 100644
index 00000000000..0d81c67f52a
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/form/CheckboxTagTests.java
@@ -0,0 +1,624 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.web.servlet.tags.form;
+
+import java.beans.PropertyEditorSupport;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+import javax.servlet.jsp.tagext.Tag;
+
+import org.dom4j.Document;
+import org.dom4j.Element;
+import org.dom4j.io.SAXReader;
+
+import org.springframework.beans.Colour;
+import org.springframework.beans.Pet;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.propertyeditors.StringTrimmerEditor;
+import org.springframework.validation.BeanPropertyBindingResult;
+import org.springframework.validation.BindingResult;
+
+/**
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public class CheckboxTagTests extends AbstractFormTagTests {
+
+ private CheckboxTag tag;
+
+ private TestBean bean;
+
+ protected void onSetUp() {
+ this.tag = new CheckboxTag() {
+ protected TagWriter createTagWriter() {
+ return new TagWriter(getWriter());
+ }
+ };
+ this.tag.setPageContext(getPageContext());
+ }
+
+ public void testWithSingleValueBooleanObjectChecked() throws Exception {
+ this.tag.setPath("someBoolean");
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element rootElement = document.getRootElement();
+ assertEquals("Both tag and hidden element not rendered", 2, rootElement.elements().size());
+ Element checkboxElement = (Element) rootElement.elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("someBoolean", checkboxElement.attribute("name").getValue());
+ assertEquals("checked", checkboxElement.attribute("checked").getValue());
+ assertEquals("true", checkboxElement.attribute("value").getValue());
+ }
+
+ public void testWithSingleValueBooleanChecked() throws Exception {
+ this.tag.setPath("jedi");
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element checkboxElement = (Element) document.getRootElement().elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("jedi", checkboxElement.attribute("name").getValue());
+ assertEquals("checked", checkboxElement.attribute("checked").getValue());
+ assertEquals("true", checkboxElement.attribute("value").getValue());
+ }
+
+ public void testWithSingleValueBooleanObjectUnchecked() throws Exception {
+ this.bean.setSomeBoolean(new Boolean(false));
+ this.tag.setPath("someBoolean");
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element checkboxElement = (Element) document.getRootElement().elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("someBoolean", checkboxElement.attribute("name").getValue());
+ assertNull(checkboxElement.attribute("checked"));
+ assertEquals("true", checkboxElement.attribute("value").getValue());
+ }
+
+ public void testWithSingleValueBooleanUnchecked() throws Exception {
+ this.bean.setJedi(false);
+ this.tag.setPath("jedi");
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element checkboxElement = (Element) document.getRootElement().elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("jedi", checkboxElement.attribute("name").getValue());
+ assertNull(checkboxElement.attribute("checked"));
+ assertEquals("true", checkboxElement.attribute("value").getValue());
+ }
+
+ public void testWithSingleValueNull() throws Exception {
+ this.bean.setName(null);
+ this.tag.setPath("name");
+ this.tag.setValue("Rob Harrop");
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element checkboxElement = (Element) document.getRootElement().elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("name", checkboxElement.attribute("name").getValue());
+ assertNull(checkboxElement.attribute("checked"));
+ assertEquals("Rob Harrop", checkboxElement.attribute("value").getValue());
+ }
+
+ public void testWithSingleValueNotNull() throws Exception {
+ this.bean.setName("Rob Harrop");
+ this.tag.setPath("name");
+ this.tag.setValue("Rob Harrop");
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element checkboxElement = (Element) document.getRootElement().elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("name", checkboxElement.attribute("name").getValue());
+ assertEquals("checked", checkboxElement.attribute("checked").getValue());
+ assertEquals("Rob Harrop", checkboxElement.attribute("value").getValue());
+ }
+
+ public void testWithSingleValueAndEditor() throws Exception {
+ this.bean.setName("Rob Harrop");
+ this.tag.setPath("name");
+ this.tag.setValue(" Rob Harrop");
+ BeanPropertyBindingResult bindingResult = new BeanPropertyBindingResult(this.bean, COMMAND_NAME);
+ bindingResult.getPropertyEditorRegistry().registerCustomEditor(String.class, new StringTrimmerEditor(false));
+ getPageContext().getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + COMMAND_NAME, bindingResult);
+
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element checkboxElement = (Element) document.getRootElement().elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("name", checkboxElement.attribute("name").getValue());
+ assertEquals("checked", checkboxElement.attribute("checked").getValue());
+ assertEquals(" Rob Harrop", checkboxElement.attribute("value").getValue());
+ }
+
+ public void testWithMultiValueChecked() throws Exception {
+ this.tag.setPath("stringArray");
+ this.tag.setValue("foo");
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element checkboxElement = (Element) document.getRootElement().elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("stringArray", checkboxElement.attribute("name").getValue());
+ assertEquals("checked", checkboxElement.attribute("checked").getValue());
+ assertEquals("foo", checkboxElement.attribute("value").getValue());
+ }
+
+ public void testWithMultiValueUnchecked() throws Exception {
+ this.tag.setPath("stringArray");
+ this.tag.setValue("abc");
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element checkboxElement = (Element) document.getRootElement().elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("stringArray", checkboxElement.attribute("name").getValue());
+ assertNull(checkboxElement.attribute("checked"));
+ assertEquals("abc", checkboxElement.attribute("value").getValue());
+ }
+
+ public void testWithMultiValueWithEditor() throws Exception {
+ this.tag.setPath("stringArray");
+ this.tag.setValue(" foo");
+ BeanPropertyBindingResult bindingResult = new BeanPropertyBindingResult(this.bean, COMMAND_NAME);
+ MyStringTrimmerEditor editor = new MyStringTrimmerEditor();
+ bindingResult.getPropertyEditorRegistry().registerCustomEditor(String.class, editor);
+ getPageContext().getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + COMMAND_NAME, bindingResult);
+
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+ assertEquals(1, editor.count);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element checkboxElement = (Element) document.getRootElement().elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("stringArray", checkboxElement.attribute("name").getValue());
+ assertEquals("checked", checkboxElement.attribute("checked").getValue());
+ assertEquals(" foo", checkboxElement.attribute("value").getValue());
+ }
+
+ public void testWithMultiValueIntegerWithEditor() throws Exception {
+ this.tag.setPath("someIntegerArray");
+ this.tag.setValue(" 1");
+ BeanPropertyBindingResult bindingResult = new BeanPropertyBindingResult(this.bean, COMMAND_NAME);
+ MyIntegerEditor editor = new MyIntegerEditor();
+ bindingResult.getPropertyEditorRegistry().registerCustomEditor(Integer.class, editor);
+ getPageContext().getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + COMMAND_NAME, bindingResult);
+
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+ assertEquals(1, editor.count);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element checkboxElement = (Element) document.getRootElement().elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("someIntegerArray", checkboxElement.attribute("name").getValue());
+ assertEquals("checked", checkboxElement.attribute("checked").getValue());
+ assertEquals(" 1", checkboxElement.attribute("value").getValue());
+ }
+
+ public void testWithCollection() throws Exception {
+ this.tag.setPath("someList");
+ this.tag.setValue("foo");
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element checkboxElement = (Element) document.getRootElement().elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("someList", checkboxElement.attribute("name").getValue());
+ assertEquals("checked", checkboxElement.attribute("checked").getValue());
+ assertEquals("foo", checkboxElement.attribute("value").getValue());
+ }
+
+ public void testWithObjectChecked() throws Exception {
+ this.tag.setPath("date");
+ this.tag.setValue(getDate());
+
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element checkboxElement = (Element) document.getRootElement().elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("date", checkboxElement.attribute("name").getValue());
+ assertEquals("checked", checkboxElement.attribute("checked").getValue());
+ assertEquals(getDate().toString(), checkboxElement.attribute("value").getValue());
+ }
+
+ public void testWithObjectUnchecked() throws Exception {
+ this.tag.setPath("date");
+ Date date = new Date();
+ this.tag.setValue(date);
+
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element checkboxElement = (Element) document.getRootElement().elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("date", checkboxElement.attribute("name").getValue());
+ assertNull(checkboxElement.attribute("checked"));
+ assertEquals(date.toString(), checkboxElement.attribute("value").getValue());
+ }
+
+ public void testCollectionOfColoursSelected() throws Exception {
+ this.tag.setPath("otherColours");
+ this.tag.setValue("RED");
+
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element checkboxElement = (Element) document.getRootElement().elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("otherColours", checkboxElement.attribute("name").getValue());
+ assertEquals("checked", checkboxElement.attribute("checked").getValue());
+ }
+
+ public void testCollectionOfColoursNotSelected() throws Exception {
+ this.tag.setPath("otherColours");
+ this.tag.setValue("PURPLE");
+
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element checkboxElement = (Element) document.getRootElement().elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("otherColours", checkboxElement.attribute("name").getValue());
+ assertNull(checkboxElement.attribute("checked"));
+ }
+
+ public void testCollectionOfPetsAsString() throws Exception {
+ this.tag.setPath("pets");
+ this.tag.setValue("Spot");
+
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element checkboxElement = (Element) document.getRootElement().elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("pets", checkboxElement.attribute("name").getValue());
+ assertEquals("checked", checkboxElement.attribute("checked").getValue());
+ }
+
+ public void testCollectionOfPetsAsStringNotSelected() throws Exception {
+ this.tag.setPath("pets");
+ this.tag.setValue("Santa's Little Helper");
+
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element checkboxElement = (Element) document.getRootElement().elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("pets", checkboxElement.attribute("name").getValue());
+ assertNull(checkboxElement.attribute("checked"));
+ }
+
+ public void testCollectionOfPets() throws Exception {
+ this.tag.setPath("pets");
+ this.tag.setValue(new Pet("Rudiger"));
+
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element checkboxElement = (Element) document.getRootElement().elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("pets", checkboxElement.attribute("name").getValue());
+ assertEquals("Rudiger", checkboxElement.attribute("value").getValue());
+ assertEquals("checked", checkboxElement.attribute("checked").getValue());
+ }
+
+ public void testCollectionOfPetsNotSelected() throws Exception {
+ this.tag.setPath("pets");
+ this.tag.setValue(new Pet("Santa's Little Helper"));
+
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element checkboxElement = (Element) document.getRootElement().elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("pets", checkboxElement.attribute("name").getValue());
+ assertEquals("Santa's Little Helper", checkboxElement.attribute("value").getValue());
+ assertNull(checkboxElement.attribute("checked"));
+ }
+
+ public void testCollectionOfPetsWithEditor() throws Exception {
+ this.tag.setPath("pets");
+ this.tag.setValue(new ItemPet("Rudiger"));
+
+ BeanPropertyBindingResult bindingResult = new BeanPropertyBindingResult(this.bean, COMMAND_NAME);
+ PropertyEditorSupport editor = new ItemPet.CustomEditor();
+ bindingResult.getPropertyEditorRegistry().registerCustomEditor(ItemPet.class, editor);
+ getPageContext().getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + COMMAND_NAME, bindingResult);
+
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element checkboxElement = (Element) document.getRootElement().elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("pets", checkboxElement.attribute("name").getValue());
+ assertEquals("Rudiger", checkboxElement.attribute("value").getValue());
+ assertEquals("checked", checkboxElement.attribute("checked").getValue());
+ }
+
+ public void testWithNullValue() throws Exception {
+ try {
+ this.tag.setPath("name");
+ this.tag.doStartTag();
+ fail("Should not be able to render with a null value when binding to a non-boolean.");
+ }
+ catch (IllegalArgumentException e) {
+ // success
+ }
+ }
+
+ public void testHiddenElementOmittedOnDisabled() throws Exception {
+ this.tag.setPath("someBoolean");
+ this.tag.setDisabled("true");
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element rootElement = document.getRootElement();
+ assertEquals("Both tag and hidden element rendered incorrectly", 1, rootElement.elements().size());
+ Element checkboxElement = (Element) rootElement.elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("someBoolean", checkboxElement.attribute("name").getValue());
+ assertEquals("checked", checkboxElement.attribute("checked").getValue());
+ assertEquals("true", checkboxElement.attribute("value").getValue());
+ }
+ private Date getDate() {
+ Calendar cal = Calendar.getInstance();
+ cal.set(Calendar.YEAR, 10);
+ cal.set(Calendar.MONTH, 10);
+ cal.set(Calendar.DATE, 10);
+ cal.set(Calendar.HOUR, 10);
+ cal.set(Calendar.MINUTE, 10);
+ cal.set(Calendar.SECOND, 10);
+ return cal.getTime();
+ }
+
+ protected TestBean createTestBean() {
+ List colours = new ArrayList();
+ colours.add(Colour.BLUE);
+ colours.add(Colour.RED);
+ colours.add(Colour.GREEN);
+
+ List pets = new ArrayList();
+ pets.add(new Pet("Rudiger"));
+ pets.add(new Pet("Spot"));
+ pets.add(new Pet("Fluffy"));
+ pets.add(new Pet("Mufty"));
+
+ this.bean = new TestBean();
+ this.bean.setDate(getDate());
+ this.bean.setName("Rob Harrop");
+ this.bean.setJedi(true);
+ this.bean.setSomeBoolean(new Boolean(true));
+ this.bean.setStringArray(new String[] {"bar", "foo"});
+ this.bean.setSomeIntegerArray(new Integer[] {new Integer(2), new Integer(1)});
+ this.bean.setOtherColours(colours);
+ this.bean.setPets(pets);
+ List list = new ArrayList();
+ list.add("foo");
+ list.add("bar");
+ this.bean.setSomeList(list);
+ return this.bean;
+ }
+
+
+ private class MyStringTrimmerEditor extends StringTrimmerEditor {
+
+ public int count = 0;
+
+ public MyStringTrimmerEditor() {
+ super(false);
+ }
+
+ public void setAsText(String text) {
+ this.count++;
+ super.setAsText(text);
+ }
+ }
+
+
+ private class MyIntegerEditor extends PropertyEditorSupport {
+
+ public int count = 0;
+
+ public void setAsText(String text) {
+ this.count++;
+ setValue(new Integer(text.trim()));
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/form/CheckboxesTagTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/form/CheckboxesTagTests.java
new file mode 100644
index 00000000000..3bf0bcfce86
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/form/CheckboxesTagTests.java
@@ -0,0 +1,671 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.web.servlet.tags.form;
+
+import java.beans.PropertyEditorSupport;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.jsp.tagext.Tag;
+
+import org.dom4j.Document;
+import org.dom4j.Element;
+import org.dom4j.io.SAXReader;
+
+import org.springframework.beans.Colour;
+import org.springframework.beans.Pet;
+import org.springframework.beans.TestBean;
+import org.springframework.beans.propertyeditors.StringTrimmerEditor;
+import org.springframework.util.ObjectUtils;
+import org.springframework.validation.BeanPropertyBindingResult;
+import org.springframework.validation.BindingResult;
+
+/**
+ * @author Thomas Risberg
+ * @author Mark Fisher
+ * @author Juergen Hoeller
+ * @author Benjamin Hoffmann
+ */
+public class CheckboxesTagTests extends AbstractFormTagTests {
+
+ private CheckboxesTag tag;
+
+ private TestBean bean;
+
+ protected void onSetUp() {
+ this.tag = new CheckboxesTag() {
+ protected TagWriter createTagWriter() {
+ return new TagWriter(getWriter());
+ }
+ };
+ this.tag.setPageContext(getPageContext());
+ }
+
+ public void testWithMultiValueArray() throws Exception {
+ this.tag.setPath("stringArray");
+ this.tag.setItems(new Object[] {"foo", "bar", "baz"});
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element spanElement1 = (Element) document.getRootElement().elements().get(0);
+ Element checkboxElement1 = (Element) spanElement1.elements().get(0);
+ assertEquals("input", checkboxElement1.getName());
+ assertEquals("checkbox", checkboxElement1.attribute("type").getValue());
+ assertEquals("stringArray", checkboxElement1.attribute("name").getValue());
+ assertEquals("checked", checkboxElement1.attribute("checked").getValue());
+ assertEquals("foo", checkboxElement1.attribute("value").getValue());
+ assertEquals("foo", spanElement1.getStringValue());
+ Element spanElement2 = (Element) document.getRootElement().elements().get(1);
+ Element checkboxElement2 = (Element) spanElement2.elements().get(0);
+ assertEquals("input", checkboxElement2.getName());
+ assertEquals("checkbox", checkboxElement2.attribute("type").getValue());
+ assertEquals("stringArray", checkboxElement2.attribute("name").getValue());
+ assertEquals("checked", checkboxElement2.attribute("checked").getValue());
+ assertEquals("bar", checkboxElement2.attribute("value").getValue());
+ assertEquals("bar", spanElement2.getStringValue());
+ Element spanElement3 = (Element) document.getRootElement().elements().get(2);
+ Element checkboxElement3 = (Element) spanElement3.elements().get(0);
+ assertEquals("input", checkboxElement3.getName());
+ assertEquals("checkbox", checkboxElement3.attribute("type").getValue());
+ assertEquals("stringArray", checkboxElement3.attribute("name").getValue());
+ assertNull("not checked", checkboxElement3.attribute("checked"));
+ assertEquals("baz", checkboxElement3.attribute("value").getValue());
+ assertEquals("baz", spanElement3.getStringValue());
+ }
+
+ public void testWithMultiValueArrayWithDelimiter() throws Exception {
+ this.tag.setDelimiter(" ");
+ this.tag.setPath("stringArray");
+ this.tag.setItems(new Object[] {"foo", "bar", "baz"});
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element spanElement1 = (Element) document.getRootElement().elements().get(0);
+ Element delimiterElement1 = spanElement1.element("br");
+ assertNull(delimiterElement1);
+ Element checkboxElement1 = (Element) spanElement1.elements().get(0);
+ assertEquals("input", checkboxElement1.getName());
+ assertEquals("checkbox", checkboxElement1.attribute("type").getValue());
+ assertEquals("stringArray", checkboxElement1.attribute("name").getValue());
+ assertEquals("checked", checkboxElement1.attribute("checked").getValue());
+ assertEquals("foo", checkboxElement1.attribute("value").getValue());
+ assertEquals("foo", spanElement1.getStringValue());
+ Element spanElement2 = (Element) document.getRootElement().elements().get(1);
+ Element delimiterElement2 = (Element) spanElement2.elements().get(0);
+ assertEquals("br", delimiterElement2.getName());
+ Element checkboxElement2 = (Element) spanElement2.elements().get(1);
+ assertEquals("input", checkboxElement2.getName());
+ assertEquals("checkbox", checkboxElement2.attribute("type").getValue());
+ assertEquals("stringArray", checkboxElement2.attribute("name").getValue());
+ assertEquals("checked", checkboxElement2.attribute("checked").getValue());
+ assertEquals("bar", checkboxElement2.attribute("value").getValue());
+ assertEquals("bar", spanElement2.getStringValue());
+ Element spanElement3 = (Element) document.getRootElement().elements().get(2);
+ Element delimiterElement3 = (Element) spanElement3.elements().get(0);
+ assertEquals("br", delimiterElement3.getName());
+ Element checkboxElement3 = (Element) spanElement3.elements().get(1);
+ assertEquals("input", checkboxElement3.getName());
+ assertEquals("checkbox", checkboxElement3.attribute("type").getValue());
+ assertEquals("stringArray", checkboxElement3.attribute("name").getValue());
+ assertNull("not checked", checkboxElement3.attribute("checked"));
+ assertEquals("baz", checkboxElement3.attribute("value").getValue());
+ assertEquals("baz", spanElement3.getStringValue());
+ }
+
+ public void testWithMultiValueMap() throws Exception {
+ this.tag.setPath("stringArray");
+ Map m = new LinkedHashMap();
+ m.put("foo", "FOO");
+ m.put("bar", "BAR");
+ m.put("baz", "BAZ");
+ this.tag.setItems(m);
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element spanElement1 = (Element) document.getRootElement().elements().get(0);
+ Element checkboxElement1 = (Element) spanElement1.elements().get(0);
+ assertEquals("input", checkboxElement1.getName());
+ assertEquals("checkbox", checkboxElement1.attribute("type").getValue());
+ assertEquals("stringArray", checkboxElement1.attribute("name").getValue());
+ assertEquals("checked", checkboxElement1.attribute("checked").getValue());
+ assertEquals("foo", checkboxElement1.attribute("value").getValue());
+ assertEquals("FOO", spanElement1.getStringValue());
+ Element spanElement2 = (Element) document.getRootElement().elements().get(1);
+ Element checkboxElement2 = (Element) spanElement2.elements().get(0);
+ assertEquals("input", checkboxElement2.getName());
+ assertEquals("checkbox", checkboxElement2.attribute("type").getValue());
+ assertEquals("stringArray", checkboxElement2.attribute("name").getValue());
+ assertEquals("checked", checkboxElement2.attribute("checked").getValue());
+ assertEquals("bar", checkboxElement2.attribute("value").getValue());
+ assertEquals("BAR", spanElement2.getStringValue());
+ Element spanElement3 = (Element) document.getRootElement().elements().get(2);
+ Element checkboxElement3 = (Element) spanElement3.elements().get(0);
+ assertEquals("input", checkboxElement3.getName());
+ assertEquals("checkbox", checkboxElement3.attribute("type").getValue());
+ assertEquals("stringArray", checkboxElement3.attribute("name").getValue());
+ assertNull("not checked", checkboxElement3.attribute("checked"));
+ assertEquals("baz", checkboxElement3.attribute("value").getValue());
+ assertEquals("BAZ", spanElement3.getStringValue());
+ }
+
+ public void testWithPetItemsMap() throws Exception {
+ this.tag.setPath("someSet");
+ Map m = new LinkedHashMap();
+ m.put(new ItemPet("PET1"), "PET1Label");
+ m.put(new ItemPet("PET2"), "PET2Label");
+ m.put(new ItemPet("PET3"), "PET3Label");
+ this.tag.setItems(m);
+ tag.setItemValue("name");
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element spanElement1 = (Element) document.getRootElement().elements().get(0);
+ Element checkboxElement1 = (Element) spanElement1.elements().get(0);
+ assertEquals("input", checkboxElement1.getName());
+ assertEquals("checkbox", checkboxElement1.attribute("type").getValue());
+ assertEquals("someSet", checkboxElement1.attribute("name").getValue());
+ assertEquals("checked", checkboxElement1.attribute("checked").getValue());
+ assertEquals("PET1", checkboxElement1.attribute("value").getValue());
+ assertEquals("PET1Label", spanElement1.getStringValue());
+ Element spanElement2 = (Element) document.getRootElement().elements().get(1);
+ Element checkboxElement2 = (Element) spanElement2.elements().get(0);
+ assertEquals("input", checkboxElement2.getName());
+ assertEquals("checkbox", checkboxElement2.attribute("type").getValue());
+ assertEquals("someSet", checkboxElement2.attribute("name").getValue());
+ assertEquals("checked", checkboxElement2.attribute("checked").getValue());
+ assertEquals("PET2", checkboxElement2.attribute("value").getValue());
+ assertEquals("PET2Label", spanElement2.getStringValue());
+ Element spanElement3 = (Element) document.getRootElement().elements().get(2);
+ Element checkboxElement3 = (Element) spanElement3.elements().get(0);
+ assertEquals("input", checkboxElement3.getName());
+ assertEquals("checkbox", checkboxElement3.attribute("type").getValue());
+ assertEquals("someSet", checkboxElement3.attribute("name").getValue());
+ assertNull("not checked", checkboxElement3.attribute("checked"));
+ assertEquals("PET3", checkboxElement3.attribute("value").getValue());
+ assertEquals("PET3Label", spanElement3.getStringValue());
+ }
+
+ public void testWithMultiValueMapWithDelimiter() throws Exception {
+ String delimiter = " | ";
+ this.tag.setDelimiter(delimiter);
+ this.tag.setPath("stringArray");
+ Map m = new LinkedHashMap();
+ m.put("foo", "FOO");
+ m.put("bar", "BAR");
+ m.put("baz", "BAZ");
+ this.tag.setItems(m);
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element spanElement1 = (Element) document.getRootElement().elements().get(0);
+ Element checkboxElement1 = (Element) spanElement1.elements().get(0);
+ assertEquals("input", checkboxElement1.getName());
+ assertEquals("checkbox", checkboxElement1.attribute("type").getValue());
+ assertEquals("stringArray", checkboxElement1.attribute("name").getValue());
+ assertEquals("checked", checkboxElement1.attribute("checked").getValue());
+ assertEquals("foo", checkboxElement1.attribute("value").getValue());
+ assertEquals("FOO", spanElement1.getStringValue());
+ Element spanElement2 = (Element) document.getRootElement().elements().get(1);
+ Element checkboxElement2 = (Element) spanElement2.elements().get(0);
+ assertEquals("input", checkboxElement2.getName());
+ assertEquals("checkbox", checkboxElement2.attribute("type").getValue());
+ assertEquals("stringArray", checkboxElement2.attribute("name").getValue());
+ assertEquals("checked", checkboxElement2.attribute("checked").getValue());
+ assertEquals("bar", checkboxElement2.attribute("value").getValue());
+ assertEquals(delimiter + "BAR", spanElement2.getStringValue());
+ Element spanElement3 = (Element) document.getRootElement().elements().get(2);
+ Element checkboxElement3 = (Element) spanElement3.elements().get(0);
+ assertEquals("input", checkboxElement3.getName());
+ assertEquals("checkbox", checkboxElement3.attribute("type").getValue());
+ assertEquals("stringArray", checkboxElement3.attribute("name").getValue());
+ assertNull("not checked", checkboxElement3.attribute("checked"));
+ assertEquals("baz", checkboxElement3.attribute("value").getValue());
+ assertEquals(delimiter + "BAZ", spanElement3.getStringValue());
+ }
+
+ public void testWithMultiValueWithEditor() throws Exception {
+ this.tag.setPath("stringArray");
+ this.tag.setItems(new Object[] {" foo", " bar", " baz"});
+ BeanPropertyBindingResult bindingResult = new BeanPropertyBindingResult(this.bean, COMMAND_NAME);
+ MyStringTrimmerEditor editor = new MyStringTrimmerEditor();
+ bindingResult.getPropertyEditorRegistry().registerCustomEditor(String.class, editor);
+ getPageContext().getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + COMMAND_NAME, bindingResult);
+
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+ assertEquals(3, editor.allProcessedValues.size());
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element spanElement1 = (Element) document.getRootElement().elements().get(0);
+ Element checkboxElement1 = (Element) spanElement1.elements().get(0);
+ assertEquals("input", checkboxElement1.getName());
+ assertEquals("checkbox", checkboxElement1.attribute("type").getValue());
+ assertEquals("stringArray", checkboxElement1.attribute("name").getValue());
+ assertEquals("checked", checkboxElement1.attribute("checked").getValue());
+ assertEquals(" foo", checkboxElement1.attribute("value").getValue());
+ Element spanElement2 = (Element) document.getRootElement().elements().get(1);
+ Element checkboxElement2 = (Element) spanElement2.elements().get(0);
+ assertEquals("input", checkboxElement2.getName());
+ assertEquals("checkbox", checkboxElement2.attribute("type").getValue());
+ assertEquals("stringArray", checkboxElement2.attribute("name").getValue());
+ assertEquals("checked", checkboxElement2.attribute("checked").getValue());
+ assertEquals(" bar", checkboxElement2.attribute("value").getValue());
+ Element spanElement3 = (Element) document.getRootElement().elements().get(2);
+ Element checkboxElement3 = (Element) spanElement3.elements().get(0);
+ assertEquals("input", checkboxElement3.getName());
+ assertEquals("checkbox", checkboxElement3.attribute("type").getValue());
+ assertEquals("stringArray", checkboxElement3.attribute("name").getValue());
+ assertNull("not checked", checkboxElement3.attribute("checked"));
+ assertEquals(" baz", checkboxElement3.attribute("value").getValue());
+ }
+
+ public void testWithMultiValueWithReverseEditor() throws Exception {
+ this.tag.setPath("stringArray");
+ this.tag.setItems(new Object[] {"FOO", "BAR", "BAZ"});
+ BeanPropertyBindingResult bindingResult = new BeanPropertyBindingResult(this.bean, COMMAND_NAME);
+ MyLowerCaseEditor editor = new MyLowerCaseEditor();
+ bindingResult.getPropertyEditorRegistry().registerCustomEditor(String.class, editor);
+ getPageContext().getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + COMMAND_NAME, bindingResult);
+
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element spanElement1 = (Element) document.getRootElement().elements().get(0);
+ Element checkboxElement1 = (Element) spanElement1.elements().get(0);
+ assertEquals("input", checkboxElement1.getName());
+ assertEquals("checkbox", checkboxElement1.attribute("type").getValue());
+ assertEquals("stringArray", checkboxElement1.attribute("name").getValue());
+ assertEquals("checked", checkboxElement1.attribute("checked").getValue());
+ assertEquals("FOO", checkboxElement1.attribute("value").getValue());
+ Element spanElement2 = (Element) document.getRootElement().elements().get(1);
+ Element checkboxElement2 = (Element) spanElement2.elements().get(0);
+ assertEquals("input", checkboxElement2.getName());
+ assertEquals("checkbox", checkboxElement2.attribute("type").getValue());
+ assertEquals("stringArray", checkboxElement2.attribute("name").getValue());
+ assertEquals("checked", checkboxElement2.attribute("checked").getValue());
+ assertEquals("BAR", checkboxElement2.attribute("value").getValue());
+ Element spanElement3 = (Element) document.getRootElement().elements().get(2);
+ Element checkboxElement3 = (Element) spanElement3.elements().get(0);
+ assertEquals("input", checkboxElement3.getName());
+ assertEquals("checkbox", checkboxElement3.attribute("type").getValue());
+ assertEquals("stringArray", checkboxElement3.attribute("name").getValue());
+ assertNull("not checked", checkboxElement3.attribute("checked"));
+ assertEquals("BAZ", checkboxElement3.attribute("value").getValue());
+ }
+
+ public void testCollectionOfPets() throws Exception {
+ this.tag.setPath("pets");
+ List allPets = new ArrayList();
+ allPets.add(new ItemPet("Rudiger"));
+ allPets.add(new ItemPet("Spot"));
+ allPets.add(new ItemPet("Checkers"));
+ allPets.add(new ItemPet("Fluffy"));
+ allPets.add(new ItemPet("Mufty"));
+ this.tag.setItems(allPets);
+ this.tag.setItemValue("name");
+ this.tag.setItemLabel("label");
+
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element spanElement1 = (Element) document.getRootElement().elements().get(0);
+ Element checkboxElement1 = (Element) spanElement1.elements().get(0);
+ assertEquals("input", checkboxElement1.getName());
+ assertEquals("checkbox", checkboxElement1.attribute("type").getValue());
+ assertEquals("pets", checkboxElement1.attribute("name").getValue());
+ assertEquals("checked", checkboxElement1.attribute("checked").getValue());
+ assertEquals("Rudiger", checkboxElement1.attribute("value").getValue());
+ assertEquals("RUDIGER", spanElement1.getStringValue());
+ Element spanElement2 = (Element) document.getRootElement().elements().get(1);
+ Element checkboxElement2 = (Element) spanElement2.elements().get(0);
+ assertEquals("input", checkboxElement2.getName());
+ assertEquals("checkbox", checkboxElement2.attribute("type").getValue());
+ assertEquals("pets", checkboxElement2.attribute("name").getValue());
+ assertEquals("checked", checkboxElement2.attribute("checked").getValue());
+ assertEquals("Spot", checkboxElement2.attribute("value").getValue());
+ assertEquals("SPOT", spanElement2.getStringValue());
+ Element spanElement3 = (Element) document.getRootElement().elements().get(2);
+ Element checkboxElement3 = (Element) spanElement3.elements().get(0);
+ assertEquals("input", checkboxElement3.getName());
+ assertEquals("checkbox", checkboxElement3.attribute("type").getValue());
+ assertEquals("pets", checkboxElement3.attribute("name").getValue());
+ assertNull("not checked", checkboxElement3.attribute("checked"));
+ assertEquals("Checkers", checkboxElement3.attribute("value").getValue());
+ assertEquals("CHECKERS", spanElement3.getStringValue());
+ Element spanElement4 = (Element) document.getRootElement().elements().get(3);
+ Element checkboxElement4 = (Element) spanElement4.elements().get(0);
+ assertEquals("input", checkboxElement4.getName());
+ assertEquals("checkbox", checkboxElement4.attribute("type").getValue());
+ assertEquals("pets", checkboxElement4.attribute("name").getValue());
+ assertEquals("checked", checkboxElement4.attribute("checked").getValue());
+ assertEquals("Fluffy", checkboxElement4.attribute("value").getValue());
+ assertEquals("FLUFFY", spanElement4.getStringValue());
+ Element spanElement5 = (Element) document.getRootElement().elements().get(4);
+ Element checkboxElement5 = (Element) spanElement5.elements().get(0);
+ assertEquals("input", checkboxElement5.getName());
+ assertEquals("checkbox", checkboxElement5.attribute("type").getValue());
+ assertEquals("pets", checkboxElement5.attribute("name").getValue());
+ assertEquals("checked", checkboxElement5.attribute("checked").getValue());
+ assertEquals("Mufty", checkboxElement5.attribute("value").getValue());
+ assertEquals("MUFTY", spanElement5.getStringValue());
+ }
+
+ /**
+ * Test case where items toString() doesn't fit the item ID
+ */
+ public void testCollectionOfItemPets() throws Exception {
+ this.tag.setPath("someSet");
+ List allPets = new ArrayList();
+ allPets.add(new ItemPet("PET1"));
+ allPets.add(new ItemPet("PET2"));
+ allPets.add(new ItemPet("PET3"));
+ this.tag.setItems(allPets);
+ this.tag.setItemValue("name");
+ this.tag.setItemLabel("label");
+
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element spanElement1 = (Element) document.getRootElement().elements().get(0);
+ Element checkboxElement1 = (Element) spanElement1.elements().get(0);
+ assertEquals("input", checkboxElement1.getName());
+ assertEquals("checkbox", checkboxElement1.attribute("type").getValue());
+ assertEquals("someSet", checkboxElement1.attribute("name").getValue());
+ assertNotNull("should be checked", checkboxElement1.attribute("checked"));
+ assertEquals("checked", checkboxElement1.attribute("checked").getValue());
+ assertEquals("PET1", checkboxElement1.attribute("value").getValue());
+ assertEquals("PET1", spanElement1.getStringValue());
+ Element spanElement2 = (Element) document.getRootElement().elements().get(1);
+ Element checkboxElement2 = (Element) spanElement2.elements().get(0);
+ assertEquals("input", checkboxElement2.getName());
+ assertEquals("checkbox", checkboxElement2.attribute("type").getValue());
+ assertEquals("someSet", checkboxElement2.attribute("name").getValue());
+ assertNotNull("should be checked", checkboxElement2.attribute("checked"));
+ assertEquals("checked", checkboxElement2.attribute("checked").getValue());
+ assertEquals("PET2", checkboxElement2.attribute("value").getValue());
+ assertEquals("PET2", spanElement2.getStringValue());
+ Element spanElement3 = (Element) document.getRootElement().elements().get(2);
+ Element checkboxElement3 = (Element) spanElement3.elements().get(0);
+ assertEquals("input", checkboxElement3.getName());
+ assertEquals("checkbox", checkboxElement3.attribute("type").getValue());
+ assertEquals("someSet", checkboxElement3.attribute("name").getValue());
+ assertNull("not checked", checkboxElement3.attribute("checked"));
+ assertEquals("PET3", checkboxElement3.attribute("value").getValue());
+ assertEquals("PET3", spanElement3.getStringValue());
+ }
+
+ public void testCollectionOfPetsWithEditor() throws Exception {
+ this.tag.setPath("pets");
+ List allPets = new ArrayList();
+ allPets.add(new ItemPet("Rudiger"));
+ allPets.add(new ItemPet("Spot"));
+ allPets.add(new ItemPet("Checkers"));
+ allPets.add(new ItemPet("Fluffy"));
+ allPets.add(new ItemPet("Mufty"));
+ this.tag.setItems(allPets);
+ this.tag.setItemLabel("label");
+ this.tag.setId("myId");
+
+ BeanPropertyBindingResult bindingResult = new BeanPropertyBindingResult(this.bean, COMMAND_NAME);
+ PropertyEditorSupport editor = new ItemPet.CustomEditor();
+ bindingResult.getPropertyEditorRegistry().registerCustomEditor(ItemPet.class, editor);
+ getPageContext().getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + COMMAND_NAME, bindingResult);
+
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element spanElement1 = (Element) document.getRootElement().elements().get(0);
+ Element checkboxElement1 = (Element) spanElement1.elements().get(0);
+ assertEquals("input", checkboxElement1.getName());
+ assertEquals("checkbox", checkboxElement1.attribute("type").getValue());
+ assertEquals("pets", checkboxElement1.attribute("name").getValue());
+ assertEquals("checked", checkboxElement1.attribute("checked").getValue());
+ assertEquals("Rudiger", checkboxElement1.attribute("value").getValue());
+ assertEquals("RUDIGER", spanElement1.getStringValue());
+ Element spanElement2 = (Element) document.getRootElement().elements().get(1);
+ Element checkboxElement2 = (Element) spanElement2.elements().get(0);
+ assertEquals("input", checkboxElement2.getName());
+ assertEquals("checkbox", checkboxElement2.attribute("type").getValue());
+ assertEquals("pets", checkboxElement2.attribute("name").getValue());
+ assertEquals("checked", checkboxElement2.attribute("checked").getValue());
+ assertEquals("Spot", checkboxElement2.attribute("value").getValue());
+ assertEquals("SPOT", spanElement2.getStringValue());
+ Element spanElement3 = (Element) document.getRootElement().elements().get(2);
+ Element checkboxElement3 = (Element) spanElement3.elements().get(0);
+ assertEquals("input", checkboxElement3.getName());
+ assertEquals("checkbox", checkboxElement3.attribute("type").getValue());
+ assertEquals("pets", checkboxElement3.attribute("name").getValue());
+ assertNull("not checked", checkboxElement3.attribute("checked"));
+ assertEquals("Checkers", checkboxElement3.attribute("value").getValue());
+ assertEquals("CHECKERS", spanElement3.getStringValue());
+ Element spanElement4 = (Element) document.getRootElement().elements().get(3);
+ Element checkboxElement4 = (Element) spanElement4.elements().get(0);
+ assertEquals("input", checkboxElement4.getName());
+ assertEquals("checkbox", checkboxElement4.attribute("type").getValue());
+ assertEquals("pets", checkboxElement4.attribute("name").getValue());
+ assertEquals("checked", checkboxElement4.attribute("checked").getValue());
+ assertEquals("Fluffy", checkboxElement4.attribute("value").getValue());
+ assertEquals("FLUFFY", spanElement4.getStringValue());
+ Element spanElement5 = (Element) document.getRootElement().elements().get(4);
+ Element checkboxElement5 = (Element) spanElement5.elements().get(0);
+ assertEquals("input", checkboxElement5.getName());
+ assertEquals("checkbox", checkboxElement5.attribute("type").getValue());
+ assertEquals("pets", checkboxElement5.attribute("name").getValue());
+ assertEquals("checked", checkboxElement5.attribute("checked").getValue());
+ assertEquals("Mufty", checkboxElement5.attribute("value").getValue());
+ assertEquals("MUFTY", spanElement5.getStringValue());
+ }
+
+ public void testWithNullValue() throws Exception {
+ try {
+ this.tag.setPath("name");
+ this.tag.doStartTag();
+ fail("Should not be able to render with a null value when binding to a non-boolean.");
+ }
+ catch (IllegalArgumentException ex) {
+ // success
+ }
+ }
+
+ public void testHiddenElementOmittedOnDisabled() throws Exception {
+ this.tag.setPath("stringArray");
+ this.tag.setItems(new Object[] {"foo", "bar", "baz"});
+ this.tag.setDisabled("true");
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element rootElement = document.getRootElement();
+ assertEquals("Both tag and hidden element rendered incorrectly", 3, rootElement.elements().size());
+ Element spanElement = (Element) document.getRootElement().elements().get(0);
+ Element checkboxElement = (Element) spanElement.elements().get(0);
+ assertEquals("input", checkboxElement.getName());
+ assertEquals("checkbox", checkboxElement.attribute("type").getValue());
+ assertEquals("stringArray", checkboxElement.attribute("name").getValue());
+ assertEquals("checked", checkboxElement.attribute("checked").getValue());
+ assertEquals("disabled", checkboxElement.attribute("disabled").getValue());
+ assertEquals("foo", checkboxElement.attribute("value").getValue());
+ }
+
+ public void testSpanElementCustomizable() throws Exception {
+ this.tag.setPath("stringArray");
+ this.tag.setItems(new Object[] {"foo", "bar", "baz"});
+ this.tag.setElement("element");
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+ String output = getOutput();
+
+ // wrap the output so it is valid XML
+ output = "" + output + "";
+
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(new StringReader(output));
+ Element spanElement = (Element) document.getRootElement().elements().get(0);
+ assertEquals("element", spanElement.getName());
+ }
+
+ private Date getDate() {
+ Calendar cal = Calendar.getInstance();
+ cal.set(Calendar.YEAR, 10);
+ cal.set(Calendar.MONTH, 10);
+ cal.set(Calendar.DATE, 10);
+ cal.set(Calendar.HOUR, 10);
+ cal.set(Calendar.MINUTE, 10);
+ cal.set(Calendar.SECOND, 10);
+ return cal.getTime();
+ }
+
+ protected TestBean createTestBean() {
+ List colours = new ArrayList();
+ colours.add(Colour.BLUE);
+ colours.add(Colour.RED);
+ colours.add(Colour.GREEN);
+
+ List pets = new ArrayList();
+ pets.add(new Pet("Rudiger"));
+ pets.add(new Pet("Spot"));
+ pets.add(new Pet("Fluffy"));
+ pets.add(new Pet("Mufty"));
+
+ Set someObjects = new HashSet();
+ someObjects.add(new ItemPet("PET1"));
+ someObjects.add(new ItemPet("PET2"));
+
+ this.bean = new TestBean();
+ this.bean.setDate(getDate());
+ this.bean.setName("Rob Harrop");
+ this.bean.setJedi(true);
+ this.bean.setSomeBoolean(new Boolean(true));
+ this.bean.setStringArray(new String[] {"bar", "foo"});
+ this.bean.setSomeIntegerArray(new Integer[] {new Integer(2), new Integer(1)});
+ this.bean.setOtherColours(colours);
+ this.bean.setPets(pets);
+ this.bean.setSomeSet(someObjects);
+ List list = new ArrayList();
+ list.add("foo");
+ list.add("bar");
+ this.bean.setSomeList(list);
+ return this.bean;
+ }
+
+
+ private static class MyStringTrimmerEditor extends StringTrimmerEditor {
+
+ public final Set allProcessedValues = new HashSet();
+
+ public MyStringTrimmerEditor() {
+ super(false);
+ }
+
+ public void setAsText(String text) {
+ super.setAsText(text);
+ this.allProcessedValues.add(getValue());
+ }
+ }
+
+
+ private static class MyLowerCaseEditor extends PropertyEditorSupport {
+
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue(text.toLowerCase());
+ }
+
+ public String getAsText() {
+ return ObjectUtils.nullSafeToString(getValue()).toUpperCase();
+ }
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/form/Country.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/form/Country.java
new file mode 100644
index 00000000000..4f1e72264fc
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/form/Country.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2002-2007 the original author or authors.
+ *
+ * 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.springframework.web.servlet.tags.form;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Rob Harrop
+ * @author Sam Brannen
+ */
+public class Country {
+
+ public static final Country COUNTRY_AT = new Country("AT", "Austria");
+
+ public static final Country COUNTRY_NL = new Country("NL", "Netherlands");
+
+ public static final Country COUNTRY_UK = new Country("UK", "United Kingdom");
+
+ public static final Country COUNTRY_US = new Country("US", "United States");
+
+
+ private final String isoCode;
+
+ private final String name;
+
+
+ public Country(String isoCode, String name) {
+ this.isoCode = isoCode;
+ this.name = name;
+ }
+
+
+ public String getIsoCode() {
+ return this.isoCode;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+
+ public String toString() {
+ return this.name + "(" + this.isoCode + ")";
+ }
+
+ public static Country getCountryWithIsoCode(final String isoCode) {
+ if (COUNTRY_AT.isoCode.equals(isoCode)) {
+ return COUNTRY_AT;
+ }
+ if (COUNTRY_NL.isoCode.equals(isoCode)) {
+ return COUNTRY_NL;
+ }
+ if (COUNTRY_UK.isoCode.equals(isoCode)) {
+ return COUNTRY_UK;
+ }
+ if (COUNTRY_US.isoCode.equals(isoCode)) {
+ return COUNTRY_US;
+ }
+ return null;
+ }
+
+ public static List getCountries() {
+ List countries = new ArrayList();
+ countries.add(COUNTRY_AT);
+ countries.add(COUNTRY_NL);
+ countries.add(COUNTRY_UK);
+ countries.add(COUNTRY_US);
+ return countries;
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/form/ErrorsTagTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/form/ErrorsTagTests.java
new file mode 100644
index 00000000000..9d2e5faafc6
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/form/ErrorsTagTests.java
@@ -0,0 +1,408 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.web.servlet.tags.form;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.PageContext;
+import javax.servlet.jsp.tagext.BodyTag;
+import javax.servlet.jsp.tagext.Tag;
+
+import org.springframework.beans.TestBean;
+import org.springframework.mock.web.MockBodyContent;
+import org.springframework.mock.web.MockPageContext;
+import org.springframework.validation.BeanPropertyBindingResult;
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.Errors;
+import org.springframework.web.servlet.support.RequestContext;
+import org.springframework.web.servlet.tags.RequestContextAwareTag;
+
+/**
+ * @author Rob Harrop
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ * @author Mark Fisher
+ */
+public class ErrorsTagTests extends AbstractFormTagTests {
+
+ private static final String COMMAND_NAME = "testBean";
+
+ private ErrorsTag tag;
+
+
+ protected void onSetUp() {
+ this.tag = new ErrorsTag() {
+ protected TagWriter createTagWriter() {
+ return new TagWriter(getWriter());
+ }
+ };
+ this.tag.setPath("name");
+ this.tag.setParent(getFormTag());
+ this.tag.setPageContext(getPageContext());
+ }
+
+ protected TestBean createTestBean() {
+ return new TestBean();
+ }
+
+
+ public void testWithExplicitNonWhitespaceBodyContent() throws Exception {
+ String mockContent = "This is some explicit body content";
+ this.tag.setBodyContent(new MockBodyContent(mockContent, getWriter()));
+
+ // construct an errors instance of the tag
+ TestBean target = new TestBean();
+ target.setName("Rob Harrop");
+ Errors errors = new BeanPropertyBindingResult(target, COMMAND_NAME);
+ errors.rejectValue("name", "some.code", "Default Message");
+
+ exposeBindingResult(errors);
+
+ int result = this.tag.doStartTag();
+ assertEquals(BodyTag.EVAL_BODY_BUFFERED, result);
+
+ result = this.tag.doEndTag();
+ assertEquals(Tag.EVAL_PAGE, result);
+ assertEquals(mockContent, getOutput());
+ }
+
+ public void testWithExplicitWhitespaceBodyContent() throws Exception {
+ this.tag.setBodyContent(new MockBodyContent("\t\n ", getWriter()));
+
+ // construct an errors instance of the tag
+ TestBean target = new TestBean();
+ target.setName("Rob Harrop");
+ Errors errors = new BeanPropertyBindingResult(target, COMMAND_NAME);
+ errors.rejectValue("name", "some.code", "Default Message");
+
+ exposeBindingResult(errors);
+
+ int result = this.tag.doStartTag();
+ assertEquals(BodyTag.EVAL_BODY_BUFFERED, result);
+
+ result = this.tag.doEndTag();
+ assertEquals(Tag.EVAL_PAGE, result);
+
+ String output = getOutput();
+ assertElementTagOpened(output);
+ assertElementTagClosed(output);
+
+ assertContainsAttribute(output, "id", "name.errors");
+ assertBlockTagContains(output, "Default Message");
+ }
+
+ public void testWithExplicitEmptyWhitespaceBodyContent() throws Exception {
+ this.tag.setBodyContent(new MockBodyContent("", getWriter()));
+
+ // construct an errors instance of the tag
+ TestBean target = new TestBean();
+ target.setName("Rob Harrop");
+ Errors errors = new BeanPropertyBindingResult(target, COMMAND_NAME);
+ errors.rejectValue("name", "some.code", "Default Message");
+
+ exposeBindingResult(errors);
+
+ int result = this.tag.doStartTag();
+ assertEquals(BodyTag.EVAL_BODY_BUFFERED, result);
+
+ result = this.tag.doEndTag();
+ assertEquals(Tag.EVAL_PAGE, result);
+
+ String output = getOutput();
+ assertElementTagOpened(output);
+ assertElementTagClosed(output);
+
+ assertContainsAttribute(output, "id", "name.errors");
+ assertBlockTagContains(output, "Default Message");
+ }
+
+ public void testWithErrors() throws Exception {
+ // construct an errors instance of the tag
+ TestBean target = new TestBean();
+ target.setName("Rob Harrop");
+ Errors errors = new BeanPropertyBindingResult(target, COMMAND_NAME);
+ errors.rejectValue("name", "some.code", "Default Message");
+ errors.rejectValue("name", "too.short", "Too Short");
+
+ exposeBindingResult(errors);
+
+ int result = this.tag.doStartTag();
+ assertEquals(BodyTag.EVAL_BODY_BUFFERED, result);
+
+ result = this.tag.doEndTag();
+ assertEquals(Tag.EVAL_PAGE, result);
+
+ String output = getOutput();
+ assertElementTagOpened(output);
+ assertElementTagClosed(output);
+
+ assertContainsAttribute(output, "id", "name.errors");
+ assertBlockTagContains(output, " ");
+ assertBlockTagContains(output, "Default Message");
+ assertBlockTagContains(output, "Too Short");
+ }
+
+ public void testWithEscapedErrors() throws Exception {
+ // construct an errors instance of the tag
+ TestBean target = new TestBean();
+ target.setName("Rob Harrop");
+ Errors errors = new BeanPropertyBindingResult(target, COMMAND_NAME);
+ errors.rejectValue("name", "some.code", "Default <> Message");
+ errors.rejectValue("name", "too.short", "Too & Short");
+
+ exposeBindingResult(errors);
+
+ int result = this.tag.doStartTag();
+ assertEquals(BodyTag.EVAL_BODY_BUFFERED, result);
+
+ result = this.tag.doEndTag();
+ assertEquals(Tag.EVAL_PAGE, result);
+
+ String output = getOutput();
+ assertElementTagOpened(output);
+ assertElementTagClosed(output);
+
+ assertContainsAttribute(output, "id", "name.errors");
+ assertBlockTagContains(output, " ");
+ assertBlockTagContains(output, "Default <> Message");
+ assertBlockTagContains(output, "Too & Short");
+ }
+
+ public void testWithNonEscapedErrors() throws Exception {
+ this.tag.setHtmlEscape("false");
+
+ // construct an errors instance of the tag
+ TestBean target = new TestBean();
+ target.setName("Rob Harrop");
+ Errors errors = new BeanPropertyBindingResult(target, COMMAND_NAME);
+ errors.rejectValue("name", "some.code", "Default <> Message");
+ errors.rejectValue("name", "too.short", "Too & Short");
+
+ exposeBindingResult(errors);
+
+ int result = this.tag.doStartTag();
+ assertEquals(BodyTag.EVAL_BODY_BUFFERED, result);
+
+ result = this.tag.doEndTag();
+ assertEquals(Tag.EVAL_PAGE, result);
+
+ String output = getOutput();
+ assertElementTagOpened(output);
+ assertElementTagClosed(output);
+
+ assertContainsAttribute(output, "id", "name.errors");
+ assertBlockTagContains(output, " ");
+ assertBlockTagContains(output, "Default <> Message");
+ assertBlockTagContains(output, "Too & Short");
+ }
+
+ public void testWithErrorsAndCustomElement() throws Exception {
+ // construct an errors instance of the tag
+ TestBean target = new TestBean();
+ target.setName("Rob Harrop");
+ Errors errors = new BeanPropertyBindingResult(target, COMMAND_NAME);
+ errors.rejectValue("name", "some.code", "Default Message");
+ errors.rejectValue("name", "too.short", "Too Short");
+
+ exposeBindingResult(errors);
+
+ this.tag.setElement("div");
+ int result = this.tag.doStartTag();
+ assertEquals(BodyTag.EVAL_BODY_BUFFERED, result);
+
+ result = this.tag.doEndTag();
+ assertEquals(Tag.EVAL_PAGE, result);
+
+ String output = getOutput();
+ assertElementTagOpened(output);
+ assertElementTagClosed(output);
+
+ assertContainsAttribute(output, "id", "name.errors");
+ assertBlockTagContains(output, " ");
+ assertBlockTagContains(output, "Default Message");
+ assertBlockTagContains(output, "Too Short");
+ }
+
+ public void testWithoutErrors() throws Exception {
+ Errors errors = new BeanPropertyBindingResult(new TestBean(), "COMMAND_NAME");
+ exposeBindingResult(errors);
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ result = this.tag.doEndTag();
+ assertEquals(Tag.EVAL_PAGE, result);
+
+ String output = getOutput();
+ assertEquals(0, output.length());
+ }
+
+ public void testWithoutErrorsInstance() throws Exception {
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ result = this.tag.doEndTag();
+ assertEquals(Tag.EVAL_PAGE, result);
+
+ String output = getOutput();
+ assertEquals(0, output.length());
+ }
+
+ public void testAsBodyTag() throws Exception {
+ Errors errors = new BeanPropertyBindingResult(new TestBean(), "COMMAND_NAME");
+ errors.rejectValue("name", "some.code", "Default Message");
+ errors.rejectValue("name", "too.short", "Too Short");
+ exposeBindingResult(errors);
+ int result = this.tag.doStartTag();
+ assertEquals(BodyTag.EVAL_BODY_BUFFERED, result);
+ assertNotNull(getPageContext().getAttribute(ErrorsTag.MESSAGES_ATTRIBUTE));
+ String bodyContent = "Foo";
+ this.tag.setBodyContent(new MockBodyContent(bodyContent, getWriter()));
+ this.tag.doEndTag();
+ this.tag.doFinally();
+ assertEquals(bodyContent, getOutput());
+ assertNull(getPageContext().getAttribute(ErrorsTag.MESSAGES_ATTRIBUTE));
+ }
+
+ public void testAsBodyTagWithExistingMessagesAttribute() throws Exception {
+ String existingAttribute = "something";
+ getPageContext().setAttribute(ErrorsTag.MESSAGES_ATTRIBUTE, existingAttribute);
+ Errors errors = new BeanPropertyBindingResult(new TestBean(), "COMMAND_NAME");
+ errors.rejectValue("name", "some.code", "Default Message");
+ errors.rejectValue("name", "too.short", "Too Short");
+ exposeBindingResult(errors);
+ int result = this.tag.doStartTag();
+ assertEquals(BodyTag.EVAL_BODY_BUFFERED, result);
+ assertNotNull(getPageContext().getAttribute(ErrorsTag.MESSAGES_ATTRIBUTE));
+ assertTrue(getPageContext().getAttribute(ErrorsTag.MESSAGES_ATTRIBUTE) instanceof List);
+ String bodyContent = "Foo";
+ this.tag.setBodyContent(new MockBodyContent(bodyContent, getWriter()));
+ this.tag.doEndTag();
+ this.tag.doFinally();
+ assertEquals(bodyContent, getOutput());
+ assertEquals(existingAttribute, getPageContext().getAttribute(ErrorsTag.MESSAGES_ATTRIBUTE));
+ }
+
+ /**
+ * http://opensource.atlassian.com/projects/spring/browse/SPR-2788
+ */
+ public void testAsBodyTagWithErrorsAndExistingMessagesAttributeInNonPageScopeAreNotClobbered() throws Exception {
+ String existingAttribute = "something";
+ getPageContext().setAttribute(ErrorsTag.MESSAGES_ATTRIBUTE, existingAttribute, PageContext.APPLICATION_SCOPE);
+ Errors errors = new BeanPropertyBindingResult(new TestBean(), "COMMAND_NAME");
+ errors.rejectValue("name", "some.code", "Default Message");
+ errors.rejectValue("name", "too.short", "Too Short");
+ exposeBindingResult(errors);
+ int result = this.tag.doStartTag();
+ assertEquals(BodyTag.EVAL_BODY_BUFFERED, result);
+ assertNotNull(getPageContext().getAttribute(ErrorsTag.MESSAGES_ATTRIBUTE));
+ assertTrue(getPageContext().getAttribute(ErrorsTag.MESSAGES_ATTRIBUTE) instanceof List);
+ String bodyContent = "Foo";
+ this.tag.setBodyContent(new MockBodyContent(bodyContent, getWriter()));
+ this.tag.doEndTag();
+ this.tag.doFinally();
+ assertEquals(bodyContent, getOutput());
+ assertEquals(existingAttribute,
+ getPageContext().getAttribute(ErrorsTag.MESSAGES_ATTRIBUTE, PageContext.APPLICATION_SCOPE));
+ }
+
+ /**
+ * http://opensource.atlassian.com/projects/spring/browse/SPR-2788
+ */
+ public void testAsBodyTagWithNoErrorsAndExistingMessagesAttributeInApplicationScopeAreNotClobbered() throws Exception {
+ assertWhenNoErrorsExistingMessagesInScopeAreNotClobbered(PageContext.APPLICATION_SCOPE);
+ }
+
+ /**
+ * http://opensource.atlassian.com/projects/spring/browse/SPR-2788
+ */
+ public void testAsBodyTagWithNoErrorsAndExistingMessagesAttributeInSessionScopeAreNotClobbered() throws Exception {
+ assertWhenNoErrorsExistingMessagesInScopeAreNotClobbered(PageContext.SESSION_SCOPE);
+ }
+
+ /**
+ * http://opensource.atlassian.com/projects/spring/browse/SPR-2788
+ */
+ public void testAsBodyTagWithNoErrorsAndExistingMessagesAttributeInPageScopeAreNotClobbered() throws Exception {
+ assertWhenNoErrorsExistingMessagesInScopeAreNotClobbered(PageContext.PAGE_SCOPE);
+ }
+
+ /**
+ * http://opensource.atlassian.com/projects/spring/browse/SPR-2788
+ */
+ public void testAsBodyTagWithNoErrorsAndExistingMessagesAttributeInRequestScopeAreNotClobbered() throws Exception {
+ assertWhenNoErrorsExistingMessagesInScopeAreNotClobbered(PageContext.REQUEST_SCOPE);
+ }
+
+ /**
+ * http://opensource.atlassian.com/projects/spring/browse/SPR-4005
+ */
+ public void testOmittedPathMatchesObjectErrorsOnly() throws Exception {
+ this.tag.setPath(null);
+ Errors errors = new BeanPropertyBindingResult(new TestBean(), "COMMAND_NAME");
+ errors.reject("some.code", "object error");
+ errors.rejectValue("name", "some.code", "field error");
+ exposeBindingResult(errors);
+ this.tag.doStartTag();
+ assertNotNull(getPageContext().getAttribute(ErrorsTag.MESSAGES_ATTRIBUTE));
+ this.tag.doEndTag();
+ String output = getOutput();
+ assertBlockTagContains(output, "object error");
+ assertFalse(output.indexOf("field error") != -1);
+ }
+
+ protected void exposeBindingResult(Errors errors) {
+ // wrap errors in a Model
+ Map model = new HashMap();
+ model.put(BindingResult.MODEL_KEY_PREFIX + COMMAND_NAME, errors);
+
+ // replace the request context with one containing the errors
+ MockPageContext pageContext = getPageContext();
+ RequestContext context = new RequestContext((HttpServletRequest) pageContext.getRequest(), model);
+ pageContext.setAttribute(RequestContextAwareTag.REQUEST_CONTEXT_PAGE_ATTRIBUTE, context);
+ }
+
+ private void assertElementTagOpened(String output) {
+ assertTrue(output.startsWith("<" + this.tag.getElement() + " "));
+ }
+
+ private void assertElementTagClosed(String output) {
+ assertTrue(output.endsWith("" + this.tag.getElement() + ">"));
+ }
+
+ private void assertWhenNoErrorsExistingMessagesInScopeAreNotClobbered(int scope) throws JspException {
+ String existingAttribute = "something";
+ getPageContext().setAttribute(ErrorsTag.MESSAGES_ATTRIBUTE, existingAttribute, scope);
+
+ Errors errors = new BeanPropertyBindingResult(new TestBean(), "COMMAND_NAME");
+ exposeBindingResult(errors);
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.SKIP_BODY, result);
+
+ result = this.tag.doEndTag();
+ assertEquals(Tag.EVAL_PAGE, result);
+
+ String output = getOutput();
+ assertEquals(0, output.length());
+
+ assertEquals(existingAttribute, getPageContext().getAttribute(ErrorsTag.MESSAGES_ATTRIBUTE, scope));
+ }
+
+}
diff --git a/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/form/FormTagTests.java b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/form/FormTagTests.java
new file mode 100644
index 00000000000..24b22bc25ef
--- /dev/null
+++ b/org.springframework.testsuite/src/test/java/org/springframework/web/servlet/tags/form/FormTagTests.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2002-2008 the original author or authors.
+ *
+ * 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.springframework.web.servlet.tags.form;
+
+import javax.servlet.jsp.PageContext;
+import javax.servlet.jsp.tagext.Tag;
+
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.test.AssertThrows;
+
+/**
+ * @author Rob Harrop
+ * @author Rick Evans
+ * @author Juergen Hoeller
+ */
+public class FormTagTests extends AbstractHtmlElementTagTests {
+
+ private static final String REQUEST_URI = "/my/form";
+
+ private static final String QUERY_STRING = "foo=bar";
+
+
+ private FormTag tag;
+
+ private MockHttpServletRequest request;
+
+
+ protected void onSetUp() {
+ this.tag = new FormTag() {
+ protected TagWriter createTagWriter() {
+ return new TagWriter(getWriter());
+ }
+ };
+ this.tag.setPageContext(getPageContext());
+ }
+
+ protected void extendRequest(MockHttpServletRequest request) {
+ request.setRequestURI(REQUEST_URI);
+ request.setQueryString(QUERY_STRING);
+ this.request = request;
+ }
+
+
+ public void testWriteForm() throws Exception {
+ String commandName = "myCommand";
+ String name = "formName";
+ String action = "/form.html";
+ String method = "POST";
+ String target = "myTarget";
+ String enctype = "my/enctype";
+ String acceptCharset = "iso-8859-1";
+ String onsubmit = "onsubmit";
+ String onreset = "onreset";
+ String autocomplete = "off";
+ String cssClass = "myClass";
+ String cssStyle = "myStyle";
+
+ this.tag.setName(name);
+ this.tag.setCssClass(cssClass);
+ this.tag.setCssStyle(cssStyle);
+ this.tag.setCommandName(commandName);
+ this.tag.setAction(action);
+ this.tag.setMethod(method);
+ this.tag.setTarget(target);
+ this.tag.setEnctype(enctype);
+ this.tag.setAcceptCharset(acceptCharset);
+ this.tag.setOnsubmit(onsubmit);
+ this.tag.setOnreset(onreset);
+ this.tag.setAutocomplete(autocomplete);
+
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.EVAL_BODY_INCLUDE, result);
+ assertEquals("Form attribute not exposed", commandName,
+ getPageContext().getRequest().getAttribute(FormTag.MODEL_ATTRIBUTE_VARIABLE_NAME));
+
+ result = this.tag.doEndTag();
+ assertEquals(Tag.EVAL_PAGE, result);
+
+ this.tag.doFinally();
+ assertNull("Form attribute not cleared after tag ends",
+ getPageContext().getRequest().getAttribute(FormTag.MODEL_ATTRIBUTE_VARIABLE_NAME));
+
+ String output = getOutput();
+ assertFormTagOpened(output);
+ assertFormTagClosed(output);
+
+ assertContainsAttribute(output, "class", cssClass);
+ assertContainsAttribute(output, "style", cssStyle);
+ assertContainsAttribute(output, "action", action);
+ assertContainsAttribute(output, "method", method);
+ assertContainsAttribute(output, "target", target);
+ assertContainsAttribute(output, "enctype", enctype);
+ assertContainsAttribute(output, "accept-charset", acceptCharset);
+ assertContainsAttribute(output, "onsubmit", onsubmit);
+ assertContainsAttribute(output, "onreset", onreset);
+ assertContainsAttribute(output, "autocomplete", autocomplete);
+ assertContainsAttribute(output, "id", commandName);
+ assertContainsAttribute(output, "name", name);
+ }
+
+ public void testWithActionFromRequest() throws Exception {
+ String commandName = "myCommand";
+ String enctype = "my/enctype";
+ String method = "POST";
+ String onsubmit = "onsubmit";
+ String onreset = "onreset";
+
+ this.tag.setCommandName(commandName);
+ this.tag.setMethod(method);
+ this.tag.setEnctype(enctype);
+ this.tag.setOnsubmit(onsubmit);
+ this.tag.setOnreset(onreset);
+
+ int result = this.tag.doStartTag();
+ assertEquals(Tag.EVAL_BODY_INCLUDE, result);
+ assertEquals("Form attribute not exposed", commandName,
+ getPageContext().getAttribute(FormTag.MODEL_ATTRIBUTE_VARIABLE_NAME, PageContext.REQUEST_SCOPE));
+
+ result = this.tag.doEndTag();
+ assertEquals(Tag.EVAL_PAGE, result);
+
+ this.tag.doFinally();
+ assertNull("Form attribute not cleared after tag ends",
+ getPageContext().getAttribute(FormTag.MODEL_ATTRIBUTE_VARIABLE_NAME, PageContext.REQUEST_SCOPE));
+
+ String output = getOutput();
+ assertFormTagOpened(output);
+ assertFormTagClosed(output);
+
+ assertContainsAttribute(output, "action", REQUEST_URI + "?" + QUERY_STRING);
+ assertContainsAttribute(output, "method", method);
+ assertContainsAttribute(output, "enctype", enctype);
+ assertContainsAttribute(output, "onsubmit", onsubmit);
+ assertContainsAttribute(output, "onreset", onreset);
+ assertAttributeNotPresent(output, "name");
+ }
+
+ public void testWithNullResolvedCommand() throws Exception {
+ new AssertThrows(IllegalArgumentException.class,
+ "Must not be able to have a command name that resolves to null") {
+ public void test() throws Exception {
+ tag.setCommandName("${null}");
+ tag.doStartTag();
+ }
+ }.runTest();
+ }
+
+ /*
+ * See http://opensource.atlassian.com/projects/spring/browse/SPR-2645
+ */
+ public void testXSSScriptingExploitWhenActionIsResolvedFromQueryString() throws Exception {
+ String xssQueryString = QUERY_STRING + "&stuff=\">";
+ request.setQueryString(xssQueryString);
+ tag.doStartTag();
+ assertEquals("