Browse Source
Had to override the test.do definition in build.xml. Need to consult the spring-build team to add the change to spring-build itself. Since classes in test sources from another project cannot be shared, had to duplicate those classes.pull/23217/head
26 changed files with 2216 additions and 17 deletions
@ -1,15 +1,19 @@ |
|||||||
<?xml version="1.0" encoding="UTF-8"?> |
<?xml version="1.0" encoding="UTF-8"?> |
||||||
<classpath> |
<classpath> |
||||||
<classpathentry kind="src" path="src/main/java"/> |
<classpathentry kind="src" path="src/main/java"/> |
||||||
<classpathentry kind="src" path="src/main/resources"/> |
<classpathentry kind="src" path="src/main/resources"/> |
||||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/> |
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/> |
||||||
<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/> |
<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/> |
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> |
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> |
||||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.beans"/> |
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.beans"/> |
||||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.transaction"/> |
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.transaction"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-sources-1.1.1.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-sources-1.1.1.jar"/> |
||||||
<classpathentry kind="con" path="org.eclipse.ajdt.core.ASPECTJRT_CONTAINER"/> |
<classpathentry kind="con" path="org.eclipse.ajdt.core.ASPECTJRT_CONTAINER"/> |
||||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.core"/> |
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.core"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.aspectj/com.springsource.org.aspectj.weaver/1.6.2.RELEASE/com.springsource.org.aspectj.weaver-1.6.2.RELEASE.jar" sourcepath="/IVY_CACHE/org.aspectj/com.springsource.org.aspectj.weaver/1.6.2.RELEASE/com.springsource.org.aspectj.weaver-sources-1.6.2.RELEASE.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.aspectj/com.springsource.org.aspectj.weaver/1.6.2.RELEASE/com.springsource.org.aspectj.weaver-1.6.2.RELEASE.jar" sourcepath="/IVY_CACHE/org.aspectj/com.springsource.org.aspectj.weaver/1.6.2.RELEASE/com.springsource.org.aspectj.weaver-sources-1.6.2.RELEASE.jar"/> |
||||||
<classpathentry kind="output" path="target/classes"/> |
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.test"/> |
||||||
</classpath> |
<classpathentry kind="var" path="IVY_CACHE/org.junit/com.springsource.org.junit/4.6.0/com.springsource.org.junit-4.6.0.jar" sourcepath="/IVY_CACHE/org.junit/com.springsource.org.junit/4.6.0/com.springsource.org.junit-sources-4.6.0.jar"/> |
||||||
|
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.context"/> |
||||||
|
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.context.support"/> |
||||||
|
<classpathentry kind="output" path="target/classes"/> |
||||||
|
</classpath> |
||||||
|
|||||||
@ -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.autoproxy; |
||||||
|
|
||||||
|
import org.springframework.context.support.ClassPathXmlApplicationContext; |
||||||
|
|
||||||
|
import junit.framework.TestCase; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Adrian Colyer |
||||||
|
*/ |
||||||
|
public class AutoProxyWithCodeStyleAspectsTests extends TestCase { |
||||||
|
|
||||||
|
public void testNoAutoproxyingOfAjcCompiledAspects() { |
||||||
|
new ClassPathXmlApplicationContext("org/springframework/aop/aspectj/autoproxy/ajcAutoproxyTests.xml"); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -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.aop.aspectj.autoproxy; |
||||||
|
|
||||||
|
import org.aspectj.lang.annotation.Aspect; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Adrian Colyer |
||||||
|
*/ |
||||||
|
@Aspect |
||||||
|
public aspect CodeStyleAspect { |
||||||
|
|
||||||
|
private String foo; |
||||||
|
|
||||||
|
pointcut somePC() : call(* someMethod()); |
||||||
|
|
||||||
|
before() : somePC() { |
||||||
|
System.out.println("match"); |
||||||
|
} |
||||||
|
|
||||||
|
public void setFoo(String foo) { |
||||||
|
this.foo = foo; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,17 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans" |
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||||
|
xmlns:aop="http://www.springframework.org/schema/aop" |
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd |
||||||
|
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> |
||||||
|
|
||||||
|
<aop:aspectj-autoproxy/> |
||||||
|
|
||||||
|
<bean id="myAspect" class="org.springframework.aop.aspectj.autoproxy.CodeStyleAspect" |
||||||
|
factory-method="aspectOf"> |
||||||
|
<property name="foo" value="bar"/> |
||||||
|
</bean> |
||||||
|
|
||||||
|
<bean id="otherBean" class="java.lang.Object"/> |
||||||
|
|
||||||
|
</beans> |
||||||
@ -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); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -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; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -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(); |
||||||
|
|
||||||
|
} |
||||||
@ -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(); |
||||||
|
|
||||||
|
} |
||||||
@ -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 org.springframework.beans.TestBean}. |
||||||
|
* |
||||||
|
* <p>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; |
||||||
|
|
||||||
|
} |
||||||
@ -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; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -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; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -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 org.springframework.beans.ITestBean#exceptional(Throwable) |
||||||
|
*/ |
||||||
|
public void exceptional(Throwable t) throws Throwable { |
||||||
|
if (t != null) { |
||||||
|
throw t; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void unreliableFileOperation() throws IOException { |
||||||
|
throw new IOException(); |
||||||
|
} |
||||||
|
/** |
||||||
|
* @see org.springframework.beans.ITestBean#returnsThis() |
||||||
|
*/ |
||||||
|
public Object returnsThis() { |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see org.springframework.beans.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; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,622 @@ |
|||||||
|
/* |
||||||
|
* 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.aspectj; |
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream; |
||||||
|
import java.io.ByteArrayOutputStream; |
||||||
|
import java.io.ObjectInputStream; |
||||||
|
import java.io.ObjectOutputStream; |
||||||
|
import java.io.ObjectStreamException; |
||||||
|
import java.io.Serializable; |
||||||
|
|
||||||
|
import junit.framework.TestCase; |
||||||
|
import org.aspectj.lang.annotation.Aspect; |
||||||
|
import org.aspectj.lang.annotation.Pointcut; |
||||||
|
|
||||||
|
import org.springframework.beans.TestBean; |
||||||
|
import org.springframework.beans.factory.FactoryBean; |
||||||
|
import org.springframework.beans.factory.UnsatisfiedDependencyException; |
||||||
|
import org.springframework.beans.factory.annotation.Autowire; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.beans.factory.annotation.Configurable; |
||||||
|
import org.springframework.context.support.ClassPathXmlApplicationContext; |
||||||
|
import org.springframework.mail.MailSender; |
||||||
|
import org.springframework.mail.javamail.JavaMailSenderImpl; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Adrian Colyer |
||||||
|
* @author Rod Johnson |
||||||
|
* @author Ramnivas Laddad |
||||||
|
* @author Juergen Hoeller |
||||||
|
*/ |
||||||
|
public class BeanConfigurerTests extends TestCase { |
||||||
|
|
||||||
|
private ClassPathXmlApplicationContext context; |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void setUp() throws Exception { |
||||||
|
this.context = |
||||||
|
new ClassPathXmlApplicationContext("org/springframework/beans/factory/aspectj/beanConfigurerTests.xml"); |
||||||
|
} |
||||||
|
|
||||||
|
public void testConfigurableWithExplicitBeanName() { |
||||||
|
ShouldBeConfiguredBySpring myObject = new ShouldBeConfiguredBySpring(); |
||||||
|
assertEquals("Rod", myObject.getName()); |
||||||
|
} |
||||||
|
|
||||||
|
public void testInjectionAfterRefresh() { |
||||||
|
context.refresh(); |
||||||
|
ShouldBeConfiguredBySpring myObject = new ShouldBeConfiguredBySpring(); |
||||||
|
assertEquals("Rod", myObject.getName()); |
||||||
|
} |
||||||
|
|
||||||
|
public void testWithoutAnnotation() { |
||||||
|
ShouldNotBeConfiguredBySpring myObject = new ShouldNotBeConfiguredBySpring(); |
||||||
|
assertNull("Name should not have been set", myObject.getName()); |
||||||
|
} |
||||||
|
|
||||||
|
public void testConfigurableWithImplicitBeanName() { |
||||||
|
ShouldBeConfiguredBySpringUsingTypeNameAsBeanName myObject = |
||||||
|
new ShouldBeConfiguredBySpringUsingTypeNameAsBeanName(); |
||||||
|
assertEquals("Rob", myObject.getName()); |
||||||
|
} |
||||||
|
|
||||||
|
public void testConfigurableUsingAutowireByType() { |
||||||
|
ShouldBeConfiguredBySpringUsingAutowireByType myObject = |
||||||
|
new ShouldBeConfiguredBySpringUsingAutowireByType(); |
||||||
|
assertNotNull(myObject.getFriend()); |
||||||
|
assertEquals("Ramnivas", myObject.getFriend().getName()); |
||||||
|
} |
||||||
|
|
||||||
|
public void testConfigurableUsingAutowireByName() { |
||||||
|
ValidAutowireByName myObject = new ValidAutowireByName(); |
||||||
|
assertNotNull(myObject.getRamnivas()); |
||||||
|
assertEquals("Ramnivas", myObject.getRamnivas().getName()); |
||||||
|
} |
||||||
|
|
||||||
|
public void testInvalidAutowireByName() { |
||||||
|
try { |
||||||
|
new InvalidAutowireByName(); |
||||||
|
fail("Autowire by name cannot work"); |
||||||
|
} |
||||||
|
catch (UnsatisfiedDependencyException ex) { |
||||||
|
// Ok
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void testNewAspectAppliesToArbitraryNonAnnotatedPojo() { |
||||||
|
ArbitraryExistingPojo aep = new ArbitraryExistingPojo(); |
||||||
|
assertNotNull(aep.friend); |
||||||
|
assertEquals("Ramnivas", aep.friend.getName()); |
||||||
|
} |
||||||
|
|
||||||
|
public void testNewAspectThatWasNotAddedToSpringContainer() { |
||||||
|
try{ |
||||||
|
new ClassThatWillNotActuallyBeWired(); |
||||||
|
} |
||||||
|
catch (IllegalStateException ex) { |
||||||
|
assertTrue(ex.getMessage().indexOf("BeanFactory") != -1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void testInjectionOnDeserialization() throws Exception { |
||||||
|
ShouldBeConfiguredBySpring domainObject = new ShouldBeConfiguredBySpring(); |
||||||
|
domainObject.setName("Anonymous"); |
||||||
|
ShouldBeConfiguredBySpring deserializedDomainObject = |
||||||
|
serializeAndDeserialize(domainObject); |
||||||
|
assertEquals("Dependency injected on deserialization","Rod",deserializedDomainObject.getName()); |
||||||
|
} |
||||||
|
|
||||||
|
public void testInjectionOnDeserializationForClassesThatContainsPublicReadResolve() throws Exception { |
||||||
|
ShouldBeConfiguredBySpringContainsPublicReadResolve domainObject = new ShouldBeConfiguredBySpringContainsPublicReadResolve(); |
||||||
|
domainObject.setName("Anonymous"); |
||||||
|
ShouldBeConfiguredBySpringContainsPublicReadResolve deserializedDomainObject = |
||||||
|
serializeAndDeserialize(domainObject); |
||||||
|
assertEquals("Dependency injected on deserialization","Rod",deserializedDomainObject.getName()); |
||||||
|
assertEquals("User readResolve should take precedence", 1, deserializedDomainObject.readResolveInvocationCount); |
||||||
|
} |
||||||
|
|
||||||
|
// See ShouldBeConfiguredBySpringContainsPrivateReadResolve
|
||||||
|
// public void testInjectionOnDeserializationForClassesThatContainsPrivateReadResolve() throws Exception {
|
||||||
|
// ShouldBeConfiguredBySpringContainsPrivateReadResolve domainObject = new ShouldBeConfiguredBySpringContainsPrivateReadResolve();
|
||||||
|
// domainObject.setName("Anonymous");
|
||||||
|
// ShouldBeConfiguredBySpringContainsPrivateReadResolve deserializedDomainObject =
|
||||||
|
// serializeAndDeserialize(domainObject);
|
||||||
|
// assertEquals("Dependency injected on deserialization","Rod",deserializedDomainObject.getName());
|
||||||
|
// }
|
||||||
|
|
||||||
|
public void testNonInjectionOnDeserializationForSerializedButNotConfigured() throws Exception { |
||||||
|
SerializableThatShouldNotBeConfiguredBySpring domainObject = new SerializableThatShouldNotBeConfiguredBySpring(); |
||||||
|
domainObject.setName("Anonymous"); |
||||||
|
SerializableThatShouldNotBeConfiguredBySpring deserializedDomainObject = |
||||||
|
serializeAndDeserialize(domainObject); |
||||||
|
assertEquals("Dependency injected on deserialization","Anonymous",deserializedDomainObject.getName()); |
||||||
|
} |
||||||
|
|
||||||
|
public void testSubBeanConfiguredOnlyOnce() throws Exception { |
||||||
|
SubBean subBean = new SubBean(); |
||||||
|
assertEquals("Property injected more than once", 1, subBean.setterCount); |
||||||
|
} |
||||||
|
|
||||||
|
public void testSubBeanConfiguredOnlyOnceForPreConstruction() throws Exception { |
||||||
|
SubBeanPreConstruction subBean = new SubBeanPreConstruction(); |
||||||
|
assertEquals("Property injected more than once", 1, subBean.setterCount); |
||||||
|
} |
||||||
|
|
||||||
|
public void testSubSerializableBeanConfiguredOnlyOnce() throws Exception { |
||||||
|
SubSerializableBean subBean = new SubSerializableBean(); |
||||||
|
assertEquals("Property injected more than once", 1, subBean.setterCount); |
||||||
|
subBean.setterCount = 0; |
||||||
|
|
||||||
|
SubSerializableBean deserializedSubBean = serializeAndDeserialize(subBean); |
||||||
|
assertEquals("Property injected more than once", 1, deserializedSubBean.setterCount); |
||||||
|
} |
||||||
|
|
||||||
|
public void testPreConstructionConfiguredBean() { |
||||||
|
PreConstructionConfiguredBean bean = new PreConstructionConfiguredBean(); |
||||||
|
assertTrue("Injection didn't occur before construction", bean.preConstructionConfigured); |
||||||
|
} |
||||||
|
|
||||||
|
public void testPreConstructionConfiguredBeanDeserializationReinjection() throws Exception { |
||||||
|
PreConstructionConfiguredBean bean = new PreConstructionConfiguredBean(); |
||||||
|
PreConstructionConfiguredBean deserialized = serializeAndDeserialize(bean); |
||||||
|
assertEquals("Injection didn't occur upon deserialization", "ramnivas", deserialized.getName()); |
||||||
|
} |
||||||
|
|
||||||
|
public void testPostConstructionConfiguredBean() { |
||||||
|
PostConstructionConfiguredBean bean = new PostConstructionConfiguredBean(); |
||||||
|
assertFalse("Injection occurred before construction", bean.preConstructionConfigured); |
||||||
|
} |
||||||
|
|
||||||
|
public void testPostConstructionConfiguredBeanDeserializationReinjection() throws Exception { |
||||||
|
PostConstructionConfiguredBean bean = new PostConstructionConfiguredBean(); |
||||||
|
PostConstructionConfiguredBean deserialized = serializeAndDeserialize(bean); |
||||||
|
assertEquals("Injection didn't occur upon deserialization", "ramnivas", deserialized.getName()); |
||||||
|
} |
||||||
|
|
||||||
|
public void testInterfaceDrivenDependencyInjection() { |
||||||
|
MailClientDependencyInjectionAspect.aspectOf().setMailSender(new JavaMailSenderImpl()); |
||||||
|
Order testOrder = new Order(); |
||||||
|
assertNotNull("Interface driven injection didn't occur for direct construction", testOrder.mailSender); |
||||||
|
} |
||||||
|
|
||||||
|
public void testInterfaceDrivenDependencyInjectionMultipleInterfaces() { |
||||||
|
MailClientDependencyInjectionAspect.aspectOf().setMailSender(new JavaMailSenderImpl()); |
||||||
|
PaymentProcessorDependencyInjectionAspect.aspectOf().setPaymentProcessor(new PaymentProcessor()); |
||||||
|
|
||||||
|
ShoppingCart testCart = new ShoppingCart(); |
||||||
|
|
||||||
|
assertNotNull("Interface driven injection didn't occur for direct construction", testCart.mailSender); |
||||||
|
assertNotNull("Interface driven injection didn't occur for direct construction", testCart.paymentProcessor); |
||||||
|
} |
||||||
|
|
||||||
|
public void testInterfaceDrivenDependencyInjectionUponDeserialization() throws Exception { |
||||||
|
MailClientDependencyInjectionAspect.aspectOf().setMailSender(new JavaMailSenderImpl()); |
||||||
|
Order testOrder = new Order(); |
||||||
|
Order deserializedOrder = serializeAndDeserialize(testOrder); |
||||||
|
assertNotNull("Interface driven injection didn't occur for deserialization", testOrder.mailSender); |
||||||
|
} |
||||||
|
|
||||||
|
public void testFieldAutoWiredAnnotationInjection() { |
||||||
|
FieldAutoWiredServiceBean bean = new FieldAutoWiredServiceBean(); |
||||||
|
assertNotNull(bean.testService); |
||||||
|
} |
||||||
|
|
||||||
|
public void testMethodAutoWiredAnnotationInjection() { |
||||||
|
MethodAutoWiredServiceBean bean = new MethodAutoWiredServiceBean(); |
||||||
|
assertNotNull(bean.testService); |
||||||
|
} |
||||||
|
|
||||||
|
public void testMultiArgumentMethodAutoWiredAnnotationInjection() { |
||||||
|
MultiArgumentMethodAutoWiredServiceBean bean = new MultiArgumentMethodAutoWiredServiceBean(); |
||||||
|
assertNotNull(bean.testService); |
||||||
|
assertNotNull(bean.paymentService); |
||||||
|
} |
||||||
|
|
||||||
|
public void testGenericParameterConfigurableBean() { |
||||||
|
GenericParameterConfigurableBean bean = new GenericParameterConfigurableBean(); |
||||||
|
assertNotNull(bean.testService); |
||||||
|
} |
||||||
|
|
||||||
|
@SuppressWarnings("unchecked") |
||||||
|
private <T> T serializeAndDeserialize(T serializable) throws Exception { |
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
||||||
|
ObjectOutputStream oos = new ObjectOutputStream(baos); |
||||||
|
oos.writeObject(serializable); |
||||||
|
oos.close(); |
||||||
|
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); |
||||||
|
ObjectInputStream ois = new ObjectInputStream(bais); |
||||||
|
return (T)ois.readObject(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Configurable("beanOne") |
||||||
|
private static class ShouldBeConfiguredBySpring implements Serializable { |
||||||
|
|
||||||
|
private String name; |
||||||
|
|
||||||
|
public void setName(String name) { |
||||||
|
this.name = name; |
||||||
|
} |
||||||
|
|
||||||
|
public String getName() { |
||||||
|
return this.name; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Configurable("beanOne") |
||||||
|
private static class ShouldBeConfiguredBySpringContainsPublicReadResolve implements Serializable { |
||||||
|
|
||||||
|
private String name; |
||||||
|
|
||||||
|
private int readResolveInvocationCount = 0; |
||||||
|
|
||||||
|
public void setName(String name) { |
||||||
|
this.name = name; |
||||||
|
} |
||||||
|
|
||||||
|
public String getName() { |
||||||
|
return this.name; |
||||||
|
} |
||||||
|
|
||||||
|
public Object readResolve() throws ObjectStreamException { |
||||||
|
readResolveInvocationCount++; |
||||||
|
return this; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// Won't work until we use hasmethod() experimental pointcut in AspectJ.
|
||||||
|
// @Configurable("beanOne")
|
||||||
|
// private static class ShouldBeConfiguredBySpringContainsPrivateReadResolve implements Serializable {
|
||||||
|
//
|
||||||
|
// private String name;
|
||||||
|
//
|
||||||
|
// public void setName(String name) {
|
||||||
|
// this.name = name;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public String getName() {
|
||||||
|
// return this.name;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private Object readResolve() throws ObjectStreamException {
|
||||||
|
// return this;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
private static class ShouldNotBeConfiguredBySpring { |
||||||
|
|
||||||
|
private String name; |
||||||
|
|
||||||
|
public void setName(String name) { |
||||||
|
this.name = name; |
||||||
|
} |
||||||
|
|
||||||
|
public String getName() { |
||||||
|
return this.name; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static class SerializableThatShouldNotBeConfiguredBySpring implements Serializable { |
||||||
|
|
||||||
|
private String name; |
||||||
|
|
||||||
|
public void setName(String name) { |
||||||
|
this.name = name; |
||||||
|
} |
||||||
|
|
||||||
|
public String getName() { |
||||||
|
return this.name; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Configurable |
||||||
|
private static class ShouldBeConfiguredBySpringUsingTypeNameAsBeanName { |
||||||
|
|
||||||
|
private String name; |
||||||
|
|
||||||
|
public void setName(String name) { |
||||||
|
this.name = name; |
||||||
|
} |
||||||
|
|
||||||
|
public String getName() { |
||||||
|
return this.name; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Configurable(autowire=Autowire.BY_TYPE) |
||||||
|
private static class ShouldBeConfiguredBySpringUsingAutowireByType { |
||||||
|
|
||||||
|
private TestBean friend = null; |
||||||
|
|
||||||
|
public TestBean getFriend() { |
||||||
|
return friend; |
||||||
|
} |
||||||
|
|
||||||
|
public void setFriend(TestBean friend) { |
||||||
|
this.friend = friend; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Configurable(autowire=Autowire.BY_NAME) |
||||||
|
private static class ValidAutowireByName { |
||||||
|
|
||||||
|
private TestBean friend = null; |
||||||
|
|
||||||
|
public TestBean getRamnivas() { |
||||||
|
return friend; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRamnivas(TestBean friend) { |
||||||
|
this.friend = friend; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Configurable(autowire=Autowire.BY_NAME, dependencyCheck=true) |
||||||
|
private static class InvalidAutowireByName { |
||||||
|
|
||||||
|
private TestBean friend; |
||||||
|
|
||||||
|
public TestBean getFriend() { |
||||||
|
return friend; |
||||||
|
} |
||||||
|
|
||||||
|
public void setFriend(TestBean friend) { |
||||||
|
this.friend = friend; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static class ArbitraryExistingPojo { |
||||||
|
|
||||||
|
private TestBean friend; |
||||||
|
|
||||||
|
public void setFriend(TestBean f) { |
||||||
|
this.friend = f; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public static class CircularFactoryBean implements FactoryBean{ |
||||||
|
|
||||||
|
public CircularFactoryBean() { |
||||||
|
// ValidAutowireByName autowired = new ValidAutowireByName();
|
||||||
|
// assertNull(autowired.getRamnivas());
|
||||||
|
} |
||||||
|
|
||||||
|
public Object getObject() throws Exception { |
||||||
|
return new TestBean(); |
||||||
|
} |
||||||
|
|
||||||
|
public Class getObjectType() { |
||||||
|
return TestBean.class; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isSingleton() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Configurable |
||||||
|
private static class BaseBean { |
||||||
|
|
||||||
|
public int setterCount; |
||||||
|
|
||||||
|
private String name; |
||||||
|
|
||||||
|
public void setName(String name) { |
||||||
|
this.name = name; |
||||||
|
setterCount++; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static class SubBean extends BaseBean { |
||||||
|
} |
||||||
|
|
||||||
|
@Configurable(preConstruction=true) |
||||||
|
private static class SubBeanPreConstruction extends BaseBean { |
||||||
|
} |
||||||
|
|
||||||
|
@Configurable |
||||||
|
private static class BaseSerializableBean implements Serializable { |
||||||
|
|
||||||
|
public int setterCount; |
||||||
|
|
||||||
|
private String name; |
||||||
|
|
||||||
|
public void setName(String name) { |
||||||
|
this.name = name; |
||||||
|
setterCount++; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static class SubSerializableBean extends BaseSerializableBean { |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Aspect |
||||||
|
private static class WireArbitraryExistingPojo extends AbstractBeanConfigurerAspect { |
||||||
|
|
||||||
|
@Pointcut("initialization(ArbitraryExistingPojo.new(..)) && this(beanInstance)") |
||||||
|
protected void beanCreation(Object beanInstance){ |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Aspect |
||||||
|
private static class AspectThatWillNotBeUsed extends AbstractBeanConfigurerAspect { |
||||||
|
|
||||||
|
@Pointcut("initialization(ClassThatWillNotActuallyBeWired.new(..)) && this(beanInstance)") |
||||||
|
protected void beanCreation(Object beanInstance){ |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static aspect MailClientDependencyInjectionAspect extends AbstractInterfaceDrivenDependencyInjectionAspect { |
||||||
|
private MailSender mailSender; |
||||||
|
|
||||||
|
public pointcut inConfigurableBean() : within(MailSenderClient+); |
||||||
|
|
||||||
|
public void configureBean(Object bean) { |
||||||
|
((MailSenderClient)bean).setMailSender(this.mailSender); |
||||||
|
} |
||||||
|
|
||||||
|
declare parents: MailSenderClient implements ConfigurableObject; |
||||||
|
|
||||||
|
public void setMailSender(MailSender mailSender) { |
||||||
|
this.mailSender = mailSender; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static aspect PaymentProcessorDependencyInjectionAspect extends AbstractInterfaceDrivenDependencyInjectionAspect { |
||||||
|
private PaymentProcessor paymentProcessor; |
||||||
|
|
||||||
|
public pointcut inConfigurableBean() : within(PaymentProcessorClient+); |
||||||
|
|
||||||
|
public void configureBean(Object bean) { |
||||||
|
((PaymentProcessorClient)bean).setPaymentProcessor(this.paymentProcessor); |
||||||
|
} |
||||||
|
|
||||||
|
declare parents: PaymentProcessorClient implements ConfigurableObject; |
||||||
|
|
||||||
|
public void setPaymentProcessor(PaymentProcessor paymentProcessor) { |
||||||
|
this.paymentProcessor = paymentProcessor; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static interface MailSenderClient { |
||||||
|
public void setMailSender(MailSender mailSender); |
||||||
|
} |
||||||
|
|
||||||
|
public static interface PaymentProcessorClient { |
||||||
|
public void setPaymentProcessor(PaymentProcessor paymentProcessor); |
||||||
|
} |
||||||
|
|
||||||
|
public static class PaymentProcessor { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public static class Order implements MailSenderClient, Serializable { |
||||||
|
private transient MailSender mailSender; |
||||||
|
|
||||||
|
public void setMailSender(MailSender mailSender) { |
||||||
|
this.mailSender = mailSender; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static class ShoppingCart implements MailSenderClient, PaymentProcessorClient { |
||||||
|
private transient MailSender mailSender; |
||||||
|
private transient PaymentProcessor paymentProcessor; |
||||||
|
|
||||||
|
public void setMailSender(MailSender mailSender) { |
||||||
|
this.mailSender = mailSender; |
||||||
|
} |
||||||
|
|
||||||
|
public void setPaymentProcessor(PaymentProcessor paymentProcessor) { |
||||||
|
this.paymentProcessor = paymentProcessor; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static class ClassThatWillNotActuallyBeWired { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Configurable |
||||||
|
private static class PreOrPostConstructionConfiguredBean implements Serializable { |
||||||
|
private transient String name; |
||||||
|
protected transient boolean preConstructionConfigured; |
||||||
|
transient int count; |
||||||
|
|
||||||
|
public PreOrPostConstructionConfiguredBean() { |
||||||
|
preConstructionConfigured = (this.name != null); |
||||||
|
} |
||||||
|
|
||||||
|
public void setName(String name) { |
||||||
|
this.name = name; |
||||||
|
} |
||||||
|
|
||||||
|
public String getName() { |
||||||
|
return this.name; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Configurable(preConstruction=true) |
||||||
|
public static class PreConstructionConfiguredBean extends PreOrPostConstructionConfiguredBean { |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Configurable(preConstruction=false) |
||||||
|
private static class PostConstructionConfiguredBean extends PreOrPostConstructionConfiguredBean { |
||||||
|
} |
||||||
|
|
||||||
|
@Configurable |
||||||
|
public static class FieldAutoWiredServiceBean { |
||||||
|
@Autowired transient private TestService testService; |
||||||
|
} |
||||||
|
|
||||||
|
@Configurable |
||||||
|
public static class MethodAutoWiredServiceBean { |
||||||
|
transient private TestService testService; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
public void setTestService(TestService testService) { |
||||||
|
this.testService = testService; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Configurable |
||||||
|
public static class MultiArgumentMethodAutoWiredServiceBean { |
||||||
|
transient private TestService testService; |
||||||
|
transient private PaymentService paymentService; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
public void setDependencies(TestService testService, PaymentService paymentService) { |
||||||
|
this.testService = testService; |
||||||
|
this.paymentService = paymentService; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Configurable |
||||||
|
public static class GenericParameterConfigurableBean { |
||||||
|
private TestService testService; |
||||||
|
|
||||||
|
public void setTestService(TestService testService) { |
||||||
|
this.testService = testService; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static class TestService { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public static class PaymentService { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -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.beans.factory.aspectj; |
||||||
|
|
||||||
|
import org.springframework.context.support.ClassPathXmlApplicationContext; |
||||||
|
|
||||||
|
import junit.framework.TestCase; |
||||||
|
|
||||||
|
public class SpringConfiguredWithAutoProxyingTests extends TestCase { |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void setUp() throws Exception { |
||||||
|
new ClassPathXmlApplicationContext("org/springframework/beans/factory/aspectj/springConfigured.xml"); |
||||||
|
} |
||||||
|
|
||||||
|
public void testSpringConfiguredAndAutoProxyUsedTogether() { |
||||||
|
; // set up is sufficient to trigger failure if this is going to fail...
|
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,68 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans" |
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||||
|
xmlns:context="http://www.springframework.org/schema/context" |
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd |
||||||
|
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> |
||||||
|
|
||||||
|
<context:spring-configured/> |
||||||
|
|
||||||
|
<context:annotation-config/> |
||||||
|
|
||||||
|
<bean class="org.springframework.beans.factory.aspectj.BeanConfigurerTests$WireArbitraryExistingPojo" |
||||||
|
factory-method="aspectOf"/> |
||||||
|
|
||||||
|
<bean id="beanOne" class="org.springframework.beans.factory.aspectj.BeanConfigurerTests$ShouldBeConfiguredBySpring" |
||||||
|
lazy-init="true"> |
||||||
|
<property name="name" value="Rod"/> |
||||||
|
</bean> |
||||||
|
|
||||||
|
<bean class="org.springframework.beans.factory.aspectj.BeanConfigurerTests$ShouldBeConfiguredBySpringUsingTypeNameAsBeanName" |
||||||
|
lazy-init="true"> |
||||||
|
<property name="name" value="Rob"/> |
||||||
|
</bean> |
||||||
|
|
||||||
|
<bean class="org.springframework.beans.factory.aspectj.BeanConfigurerTests$SubBean" |
||||||
|
lazy-init="true"> |
||||||
|
<property name="name" value="Ramnivas"/> |
||||||
|
</bean> |
||||||
|
|
||||||
|
<bean class="org.springframework.beans.factory.aspectj.BeanConfigurerTests$SubBeanPreConstruction" |
||||||
|
lazy-init="true"> |
||||||
|
<property name="name" value="Ramnivas"/> |
||||||
|
</bean> |
||||||
|
|
||||||
|
<bean class="org.springframework.beans.factory.aspectj.BeanConfigurerTests$SubSerializableBean" |
||||||
|
lazy-init="true"> |
||||||
|
<property name="name" value="Ramnivas"/> |
||||||
|
</bean> |
||||||
|
|
||||||
|
<bean id="circular" class="org.springframework.beans.factory.aspectj.BeanConfigurerTests$CircularFactoryBean" |
||||||
|
autowire-candidate="false"/> |
||||||
|
|
||||||
|
<!-- Used as a target for autowiring by type --> |
||||||
|
<bean id="ramnivas" class="org.springframework.beans.TestBean" depends-on="circular"> |
||||||
|
<property name="name" value="Ramnivas"/> |
||||||
|
<property name="spouse" ref="circular"/> |
||||||
|
</bean> |
||||||
|
|
||||||
|
<bean class="org.springframework.beans.factory.aspectj.BeanConfigurerTests$ArbitraryExistingPojo"> |
||||||
|
<property name="friend" ref="ramnivas"/> |
||||||
|
</bean> |
||||||
|
|
||||||
|
<bean class="org.springframework.beans.factory.aspectj.BeanConfigurerTests$PreConstructionConfiguredBean"> |
||||||
|
<property name="name" value="ramnivas"/> |
||||||
|
</bean> |
||||||
|
|
||||||
|
<bean class="org.springframework.beans.factory.aspectj.BeanConfigurerTests$PostConstructionConfiguredBean"> |
||||||
|
<property name="name" value="ramnivas"/> |
||||||
|
</bean> |
||||||
|
|
||||||
|
<bean class="org.springframework.beans.factory.aspectj.BeanConfigurerTests$GenericParameterConfigurableBean" scope="prototype"> |
||||||
|
<property name="testService" ref="testService"/> |
||||||
|
</bean> |
||||||
|
|
||||||
|
<bean id="testService" class="org.springframework.beans.factory.aspectj.BeanConfigurerTests$TestService"/> |
||||||
|
<bean id="paymentService" class="org.springframework.beans.factory.aspectj.BeanConfigurerTests$PaymentService"/> |
||||||
|
|
||||||
|
</beans> |
||||||
@ -0,0 +1,14 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans" |
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||||
|
xmlns:aop="http://www.springframework.org/schema/aop" |
||||||
|
xmlns:context="http://www.springframework.org/schema/context" |
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd |
||||||
|
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd |
||||||
|
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> |
||||||
|
|
||||||
|
<context:spring-configured/> |
||||||
|
|
||||||
|
<aop:aspectj-autoproxy/> |
||||||
|
|
||||||
|
</beans> |
||||||
@ -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; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -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. |
||||||
|
* |
||||||
|
* Created on 11 Sep 2006 by Adrian Colyer |
||||||
|
*/ |
||||||
|
package org.springframework.transaction.aspectj; |
||||||
|
|
||||||
|
import org.springframework.transaction.annotation.Transactional; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Adrian Colyer |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
public class ClassWithPrivateAnnotatedMember { |
||||||
|
|
||||||
|
public void doSomething() { |
||||||
|
doInTransaction(); |
||||||
|
} |
||||||
|
|
||||||
|
@Transactional |
||||||
|
private void doInTransaction() {} |
||||||
|
} |
||||||
@ -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. |
||||||
|
* |
||||||
|
* Created on 11 Sep 2006 by Adrian Colyer |
||||||
|
*/ |
||||||
|
package org.springframework.transaction.aspectj; |
||||||
|
|
||||||
|
import org.springframework.transaction.annotation.Transactional; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Adrian Colyer |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
public class ClassWithProtectedAnnotatedMember { |
||||||
|
|
||||||
|
public void doSomething() { |
||||||
|
doInTransaction(); |
||||||
|
} |
||||||
|
|
||||||
|
@Transactional |
||||||
|
protected void doInTransaction() {} |
||||||
|
} |
||||||
@ -0,0 +1,10 @@ |
|||||||
|
package org.springframework.transaction.aspectj; |
||||||
|
|
||||||
|
import org.springframework.transaction.annotation.Transactional; |
||||||
|
|
||||||
|
@Transactional |
||||||
|
public interface ITransactional { |
||||||
|
|
||||||
|
Object echo(Throwable t) throws Throwable; |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,19 @@ |
|||||||
|
package org.springframework.transaction.aspectj; |
||||||
|
|
||||||
|
import org.springframework.transaction.annotation.Transactional; |
||||||
|
|
||||||
|
public class MethodAnnotationOnClassWithNoInterface { |
||||||
|
|
||||||
|
@Transactional(rollbackFor=InterruptedException.class) |
||||||
|
public Object echo(Throwable t) throws Throwable { |
||||||
|
if (t != null) { |
||||||
|
throw t; |
||||||
|
} |
||||||
|
return t; |
||||||
|
} |
||||||
|
|
||||||
|
public void noTransactionAttribute() { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,18 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> |
||||||
|
|
||||||
|
<beans> |
||||||
|
|
||||||
|
<bean id="transactionManager" class="org.springframework.transaction.CallCountingTransactionManager"/> |
||||||
|
|
||||||
|
<bean class="org.springframework.transaction.aspectj.AnnotationTransactionAspect" factory-method="aspectOf"> |
||||||
|
<property name="transactionManager" ref="transactionManager"/> |
||||||
|
</bean> |
||||||
|
|
||||||
|
<bean class="org.springframework.transaction.aspectj.TransactionalAnnotationOnlyOnClassWithNoInterface"/> |
||||||
|
|
||||||
|
<bean class="org.springframework.transaction.aspectj.ClassWithProtectedAnnotatedMember"/> |
||||||
|
|
||||||
|
<bean class="org.springframework.transaction.aspectj.ClassWithPrivateAnnotatedMember"/> |
||||||
|
|
||||||
|
</beans> |
||||||
@ -0,0 +1,261 @@ |
|||||||
|
/* |
||||||
|
* 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.aspectj; |
||||||
|
|
||||||
|
import java.lang.reflect.Method; |
||||||
|
|
||||||
|
import junit.framework.AssertionFailedError; |
||||||
|
|
||||||
|
import org.springframework.test.AbstractDependencyInjectionSpringContextTests; |
||||||
|
import org.springframework.transaction.CallCountingTransactionManager; |
||||||
|
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource; |
||||||
|
import org.springframework.transaction.interceptor.TransactionAspectSupport; |
||||||
|
import org.springframework.transaction.interceptor.TransactionAttribute; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Rod Johnson |
||||||
|
* @author Ramnivas Laddad |
||||||
|
*/ |
||||||
|
public class TransactionAspectTests extends AbstractDependencyInjectionSpringContextTests { |
||||||
|
|
||||||
|
private TransactionAspectSupport transactionAspect; |
||||||
|
|
||||||
|
private CallCountingTransactionManager txManager; |
||||||
|
|
||||||
|
private TransactionalAnnotationOnlyOnClassWithNoInterface annotationOnlyOnClassWithNoInterface; |
||||||
|
|
||||||
|
private ClassWithProtectedAnnotatedMember beanWithAnnotatedProtectedMethod; |
||||||
|
|
||||||
|
private ClassWithPrivateAnnotatedMember beanWithAnnotatedPrivateMethod; |
||||||
|
|
||||||
|
private MethodAnnotationOnClassWithNoInterface methodAnnotationOnly = new MethodAnnotationOnClassWithNoInterface(); |
||||||
|
|
||||||
|
|
||||||
|
public void setAnnotationOnlyOnClassWithNoInterface( |
||||||
|
TransactionalAnnotationOnlyOnClassWithNoInterface annotationOnlyOnClassWithNoInterface) { |
||||||
|
this.annotationOnlyOnClassWithNoInterface = annotationOnlyOnClassWithNoInterface; |
||||||
|
} |
||||||
|
|
||||||
|
public void setClassWithAnnotatedProtectedMethod(ClassWithProtectedAnnotatedMember aBean) { |
||||||
|
this.beanWithAnnotatedProtectedMethod = aBean; |
||||||
|
} |
||||||
|
|
||||||
|
public void setClassWithAnnotatedPrivateMethod(ClassWithPrivateAnnotatedMember aBean) { |
||||||
|
this.beanWithAnnotatedPrivateMethod = aBean; |
||||||
|
} |
||||||
|
|
||||||
|
public void setTransactionAspect(TransactionAspectSupport transactionAspect) { |
||||||
|
this.transactionAspect = transactionAspect; |
||||||
|
this.txManager = (CallCountingTransactionManager) transactionAspect.getTransactionManager(); |
||||||
|
} |
||||||
|
|
||||||
|
public TransactionAspectSupport getTransactionAspect() { |
||||||
|
return this.transactionAspect; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String getConfigPath() { |
||||||
|
return "TransactionAspectTests-context.xml"; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public void testCommitOnAnnotatedClass() throws Throwable { |
||||||
|
txManager.clear(); |
||||||
|
assertEquals(0, txManager.begun); |
||||||
|
annotationOnlyOnClassWithNoInterface.echo(null); |
||||||
|
assertEquals(1, txManager.commits); |
||||||
|
} |
||||||
|
|
||||||
|
public void testCommitOnAnnotatedProtectedMethod() throws Throwable { |
||||||
|
txManager.clear(); |
||||||
|
assertEquals(0, txManager.begun); |
||||||
|
beanWithAnnotatedProtectedMethod.doInTransaction(); |
||||||
|
assertEquals(1, txManager.commits); |
||||||
|
} |
||||||
|
|
||||||
|
public void testCommitOnAnnotatedPrivateMethod() throws Throwable { |
||||||
|
txManager.clear(); |
||||||
|
assertEquals(0, txManager.begun); |
||||||
|
beanWithAnnotatedPrivateMethod.doSomething(); |
||||||
|
assertEquals(1, txManager.commits); |
||||||
|
} |
||||||
|
|
||||||
|
public void testNoCommitOnNonAnnotatedNonPublicMethodInTransactionalType() throws Throwable { |
||||||
|
txManager.clear(); |
||||||
|
assertEquals(0,txManager.begun); |
||||||
|
annotationOnlyOnClassWithNoInterface.nonTransactionalMethod(); |
||||||
|
assertEquals(0,txManager.begun); |
||||||
|
} |
||||||
|
|
||||||
|
public void testCommitOnAnnotatedMethod() throws Throwable { |
||||||
|
txManager.clear(); |
||||||
|
assertEquals(0, txManager.begun); |
||||||
|
methodAnnotationOnly.echo(null); |
||||||
|
assertEquals(1, txManager.commits); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public static class NotTransactional { |
||||||
|
public void noop() { |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void testNotTransactional() throws Throwable { |
||||||
|
txManager.clear(); |
||||||
|
assertEquals(0, txManager.begun); |
||||||
|
new NotTransactional().noop(); |
||||||
|
assertEquals(0, txManager.begun); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public void testDefaultCommitOnAnnotatedClass() throws Throwable { |
||||||
|
testRollback(new TransactionOperationCallback() { |
||||||
|
public Object performTransactionalOperation() throws Throwable { |
||||||
|
return annotationOnlyOnClassWithNoInterface.echo(new Exception()); |
||||||
|
} |
||||||
|
}, false); |
||||||
|
} |
||||||
|
|
||||||
|
public void testDefaultRollbackOnAnnotatedClass() throws Throwable { |
||||||
|
testRollback(new TransactionOperationCallback() { |
||||||
|
public Object performTransactionalOperation() throws Throwable { |
||||||
|
return annotationOnlyOnClassWithNoInterface.echo(new RuntimeException()); |
||||||
|
} |
||||||
|
}, true); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public static class SubclassOfClassWithTransactionalAnnotation extends TransactionalAnnotationOnlyOnClassWithNoInterface { |
||||||
|
} |
||||||
|
|
||||||
|
public void testDefaultCommitOnSubclassOfAnnotatedClass() throws Throwable { |
||||||
|
testRollback(new TransactionOperationCallback() { |
||||||
|
public Object performTransactionalOperation() throws Throwable { |
||||||
|
return new SubclassOfClassWithTransactionalAnnotation().echo(new Exception()); |
||||||
|
} |
||||||
|
}, false); |
||||||
|
} |
||||||
|
|
||||||
|
public static class SubclassOfClassWithTransactionalMethodAnnotation extends MethodAnnotationOnClassWithNoInterface { |
||||||
|
} |
||||||
|
|
||||||
|
public void testDefaultCommitOnSubclassOfClassWithTransactionalMethodAnnotated() throws Throwable { |
||||||
|
testRollback(new TransactionOperationCallback() { |
||||||
|
public Object performTransactionalOperation() throws Throwable { |
||||||
|
return new SubclassOfClassWithTransactionalMethodAnnotation().echo(new Exception()); |
||||||
|
} |
||||||
|
}, false); |
||||||
|
} |
||||||
|
|
||||||
|
public static class ImplementsAnnotatedInterface implements ITransactional { |
||||||
|
public Object echo(Throwable t) throws Throwable { |
||||||
|
if (t != null) { |
||||||
|
throw t; |
||||||
|
} |
||||||
|
return t; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void testDefaultCommitOnImplementationOfAnnotatedInterface() throws Throwable { |
||||||
|
// testRollback(new TransactionOperationCallback() {
|
||||||
|
// public Object performTransactionalOperation() throws Throwable {
|
||||||
|
// return new ImplementsAnnotatedInterface().echo(new Exception());
|
||||||
|
// }
|
||||||
|
// }, false);
|
||||||
|
|
||||||
|
final Exception ex = new Exception(); |
||||||
|
testNotTransactional(new TransactionOperationCallback() { |
||||||
|
public Object performTransactionalOperation() throws Throwable { |
||||||
|
return new ImplementsAnnotatedInterface().echo(ex); |
||||||
|
} |
||||||
|
}, ex); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Note: resolution does not occur. Thus we can't make a class transactional if |
||||||
|
* it implements a transactionally annotated interface. This behaviour could only |
||||||
|
* be changed in AbstractFallbackTransactionAttributeSource in Spring proper. |
||||||
|
* @throws SecurityException |
||||||
|
* @throws NoSuchMethodException |
||||||
|
*/ |
||||||
|
public void testDoesNotResolveTxAnnotationOnMethodFromClassImplementingAnnotatedInterface() throws SecurityException, NoSuchMethodException { |
||||||
|
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource(); |
||||||
|
Method m = ImplementsAnnotatedInterface.class.getMethod("echo", Throwable.class); |
||||||
|
TransactionAttribute ta = atas.getTransactionAttribute(m, ImplementsAnnotatedInterface.class); |
||||||
|
assertNull(ta); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public void testDefaultRollbackOnImplementationOfAnnotatedInterface() throws Throwable { |
||||||
|
// testRollback(new TransactionOperationCallback() {
|
||||||
|
// public Object performTransactionalOperation() throws Throwable {
|
||||||
|
// return new ImplementsAnnotatedInterface().echo(new RuntimeException());
|
||||||
|
// }
|
||||||
|
// }, true);
|
||||||
|
|
||||||
|
final Exception rollbackProvokingException = new RuntimeException(); |
||||||
|
testNotTransactional(new TransactionOperationCallback() { |
||||||
|
public Object performTransactionalOperation() throws Throwable { |
||||||
|
return new ImplementsAnnotatedInterface().echo(rollbackProvokingException); |
||||||
|
} |
||||||
|
}, rollbackProvokingException); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
protected void testRollback(TransactionOperationCallback toc, boolean rollback) throws Throwable { |
||||||
|
txManager.clear(); |
||||||
|
assertEquals(0, txManager.begun); |
||||||
|
try { |
||||||
|
toc.performTransactionalOperation(); |
||||||
|
assertEquals(1, txManager.commits); |
||||||
|
} |
||||||
|
catch (Throwable caught) { |
||||||
|
if (caught instanceof AssertionFailedError) { |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (rollback) { |
||||||
|
assertEquals(1, txManager.rollbacks); |
||||||
|
} |
||||||
|
assertEquals(1, txManager.begun); |
||||||
|
} |
||||||
|
|
||||||
|
protected void testNotTransactional(TransactionOperationCallback toc, Throwable expected) throws Throwable { |
||||||
|
txManager.clear(); |
||||||
|
assertEquals(0, txManager.begun); |
||||||
|
try { |
||||||
|
toc.performTransactionalOperation(); |
||||||
|
} |
||||||
|
catch (Throwable t) { |
||||||
|
if (expected == null) { |
||||||
|
fail("Expected " + expected); |
||||||
|
} |
||||||
|
assertSame(expected, t); |
||||||
|
} |
||||||
|
finally { |
||||||
|
assertEquals(0, txManager.begun); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private interface TransactionOperationCallback { |
||||||
|
|
||||||
|
Object performTransactionalOperation() throws Throwable; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,20 @@ |
|||||||
|
package org.springframework.transaction.aspectj; |
||||||
|
|
||||||
|
import org.springframework.transaction.annotation.Transactional; |
||||||
|
|
||||||
|
@Transactional |
||||||
|
public class TransactionalAnnotationOnlyOnClassWithNoInterface { |
||||||
|
|
||||||
|
public Object echo(Throwable t) throws Throwable { |
||||||
|
if (t != null) { |
||||||
|
throw t; |
||||||
|
} |
||||||
|
return t; |
||||||
|
} |
||||||
|
|
||||||
|
void nonTransactionalMethod() { |
||||||
|
// no-op
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
Loading…
Reference in new issue