/*
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS 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.beans.ConstructorProperties;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.sql.DataSource;
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;
import org.springframework.beans.factory.support.MethodReplacer;
import org.springframework.tests.sample.beans.ITestBean;
import org.springframework.tests.sample.beans.IndexedTestBean;
import org.springframework.tests.sample.beans.TestBean;
import org.springframework.tests.sample.beans.factory.DummyFactory;
/**
* Types used by {@link XmlBeanFactoryTests} and its attendant XML config files.
*
* @author Chris Beams
*/
final class XmlBeanFactoryTestTypes {
}
/**
* Simple bean used to check constructor dependency checking.
*
* @author Juergen Hoeller
* @since 09.11.2003
*/
@SuppressWarnings("serial")
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;
}
@ConstructorProperties({"spouse", "otherSpouse", "myAge"})
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;
}
}
class SimpleConstructorArgBean {
private int age;
private String name;
public SimpleConstructorArgBean() {
}
public SimpleConstructorArgBean(int age) {
this.age = age;
}
public SimpleConstructorArgBean(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
}
/**
* 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
*/
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();
public String getSetterString() {
return setterString;
}
public void setSetterString(String setterString) {
this.setterString = setterString;
}
}
/**
* Simple bean used to check constructor dependency checking.
*
* @author Juergen Hoeller
* @since 09.11.2003
*/
@SuppressWarnings({ "serial", "unused" })
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;
}
}
/**
* @author Rod Johnson
*/
interface DummyBo {
void something();
}
/**
* @author Rod Johnson
*/
class DummyBoImpl implements DummyBo {
DummyDao dao;
public DummyBoImpl(DummyDao dao) {
this.dao = dao;
}
@Override
public void something() {
}
}
/**
* @author Rod Johnson
*/
class DummyDao {
}
/**
* @author Juergen Hoeller
* @since 21.07.2003
*/
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;
}
}
/**
* Test class for Spring's ability to create objects using static
* factory methods, rather than constructors.
*
* @author Rod Johnson
* @author Juergen Hoeller
*/
@SuppressWarnings("unused")
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;
}
}
/**
* Fixed method replacer for String return types
* @author Rod Johnson
*/
class FixedMethodReplacer implements MethodReplacer {
public static final String VALUE = "fixedMethodReplacer";
@Override
public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
return VALUE;
}
}
/**
* @author Chris Beams
*/
class MapAndSet {
private Object obj;
public MapAndSet(Map<?, ?> map) {
this.obj = map;
}
public MapAndSet(Set<?> set) {
this.obj = set;
}
public Object getObject() {
return obj;
}
}
/**
* @author Rod Johnson
*/
class MethodReplaceCandidate {
public String replaceMe(String echo) {
return echo;
}
}
/**
* Bean that exposes a simple property that can be set
* to a mix of references and individual values.
*/
class MixedCollectionBean {
private Collection<?> jumble;
public void setJumble(Collection<?> jumble) {
this.jumble = jumble;
}
public Collection<?> getJumble() {
return jumble;
}
}
/**
* @author Juergen Hoeller
*/
interface OverrideInterface {
TestBean getPrototypeDependency();
TestBean getPrototypeDependency(Object someParam);
}
/**
* @author Rod Johnson
* @author Juergen Hoeller
*/
abstract class OverrideOneMethod extends MethodReplaceCandidate implements OverrideInterface {
protected abstract TestBean protectedOverrideSingleton();
@Override
public TestBean getPrototypeDependency(Object someParam) {
return new TestBean();
}
public TestBean invokesOverriddenMethodOnSelf() {
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;
}
@Override
public String replaceMe(String someParam) {
return "replaceMe:" + someParam;
}
}
/**
* Subclass of OverrideOneMethod, to check that overriding is
* supported for inherited methods.
*
* @author Rod Johnson
*/
abstract class OverrideOneMethodSubclass extends OverrideOneMethod {
protected void doSomething(String arg) {
// This implementation does nothing!
// It's not overloaded
}
}
/**
* 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;
}
@Override
public void setBeanName(String name) {
this.beanName = name;
}
public String getBeanName() {
return beanName;
}
@Override
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;
}
@Override
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");
}
}
@Override
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 {
@Override
public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
if (bean instanceof ProtectedLifecycleBean) {
((ProtectedLifecycleBean) bean).postProcessBeforeInit();
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
if (bean instanceof ProtectedLifecycleBean) {
((ProtectedLifecycleBean) bean).postProcessAfterInit();
}
return bean;
}
}
}
/**
* @author Rod Johnson
*/
@SuppressWarnings("serial")
class ReverseMethodReplacer implements MethodReplacer, Serializable {
@Override
public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
String s = (String) args[0];
return new StringBuffer(s).reverse().toString();
}
}
/**
* @author Rod Johnson
*/
@SuppressWarnings("serial")
abstract class SerializableMethodReplacerCandidate extends MethodReplaceCandidate implements Serializable {
//public abstract Point getPoint();
}
/**
* @author Juergen Hoeller
* @since 23.10.2004
*/
class SingleSimpleTypeConstructorBean {
private boolean singleBoolean;
private boolean secondBoolean;
private String testString;
public SingleSimpleTypeConstructorBean(boolean singleBoolean) {
this.singleBoolean = singleBoolean;
}
protected 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;
}
}