View Javadoc
1   /*
2    * Copyright 2002-2013 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.beans.factory.groovy;
18  
19  import java.util.ArrayList;
20  import java.util.Collection;
21  import java.util.List;
22  
23  import groovy.lang.GroovyObjectSupport;
24  
25  import org.springframework.beans.BeanWrapper;
26  import org.springframework.beans.BeanWrapperImpl;
27  import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
28  import org.springframework.beans.factory.config.BeanDefinition;
29  import org.springframework.beans.factory.config.BeanDefinitionHolder;
30  import org.springframework.beans.factory.config.ConstructorArgumentValues;
31  import org.springframework.beans.factory.config.RuntimeBeanReference;
32  import org.springframework.beans.factory.support.AbstractBeanDefinition;
33  import org.springframework.beans.factory.support.GenericBeanDefinition;
34  import org.springframework.util.CollectionUtils;
35  
36  /**
37   * Internal wrapper for a Spring BeanDefinition, allowing for Groovy-style
38   * property access within a {@link GroovyBeanDefinitionReader} closure.
39   *
40   * @author Jeff Brown
41   * @author Juergen Hoeller
42   * @since 4.0
43   */
44  class GroovyBeanDefinitionWrapper extends GroovyObjectSupport {
45  
46  	private static final String PARENT = "parent";
47  	private static final String AUTOWIRE = "autowire";
48  	private static final String CONSTRUCTOR_ARGS = "constructorArgs";
49  	private static final String FACTORY_BEAN = "factoryBean";
50  	private static final String FACTORY_METHOD = "factoryMethod";
51  	private static final String INIT_METHOD = "initMethod";
52  	private static final String DESTROY_METHOD = "destroyMethod";
53  	private static final String SINGLETON = "singleton";
54  
55  	private static final List<String> dynamicProperties = new ArrayList<String>(8);
56  
57  	static {
58  		dynamicProperties.add(PARENT);
59  		dynamicProperties.add(AUTOWIRE);
60  		dynamicProperties.add(CONSTRUCTOR_ARGS);
61  		dynamicProperties.add(FACTORY_BEAN);
62  		dynamicProperties.add(FACTORY_METHOD);
63  		dynamicProperties.add(INIT_METHOD);
64  		dynamicProperties.add(DESTROY_METHOD);
65  		dynamicProperties.add(SINGLETON);
66  	}
67  
68  
69  	private String beanName;
70  
71  	private Class<?> clazz;
72  
73  	private Collection<?> constructorArgs;
74  
75  	private AbstractBeanDefinition definition;
76  
77  	private BeanWrapper definitionWrapper;
78  
79  	private String parentName;
80  
81  
82  	public GroovyBeanDefinitionWrapper(String beanName) {
83  		this.beanName = beanName;
84  	}
85  
86  	public GroovyBeanDefinitionWrapper(String beanName, Class<?> clazz) {
87  		this.beanName = beanName;
88  		this.clazz = clazz;
89  	}
90  
91  	public GroovyBeanDefinitionWrapper(String beanName, Class<?> clazz, Collection<?> constructorArgs) {
92  		this.beanName = beanName;
93  		this.clazz = clazz;
94  		this.constructorArgs = constructorArgs;
95  	}
96  
97  
98  	public String getBeanName() {
99  		return this.beanName;
100 	}
101 
102 	public void setBeanDefinition(AbstractBeanDefinition definition) {
103 		this.definition = definition;
104 	}
105 
106 	public AbstractBeanDefinition getBeanDefinition() {
107 		if (this.definition == null) {
108 			this.definition = createBeanDefinition();
109 		}
110 		return this.definition;
111 	}
112 
113 	protected AbstractBeanDefinition createBeanDefinition() {
114 		AbstractBeanDefinition bd = new GenericBeanDefinition();
115 		bd.setBeanClass(this.clazz);
116 		if (!CollectionUtils.isEmpty(this.constructorArgs)) {
117 			ConstructorArgumentValues cav = new ConstructorArgumentValues();
118 			for (Object constructorArg : this.constructorArgs) {
119 				cav.addGenericArgumentValue(constructorArg);
120 			}
121 			bd.setConstructorArgumentValues(cav);
122 		}
123 		if (this.parentName != null) {
124 			bd.setParentName(this.parentName);
125 		}
126 		this.definitionWrapper = new BeanWrapperImpl(bd);
127 		return bd;
128 	}
129 
130 	public void setBeanDefinitionHolder(BeanDefinitionHolder holder) {
131 		this.definition = (AbstractBeanDefinition) holder.getBeanDefinition();
132 		this.beanName = holder.getBeanName();
133 	}
134 
135 	public BeanDefinitionHolder getBeanDefinitionHolder() {
136 		return new BeanDefinitionHolder(getBeanDefinition(), getBeanName());
137 	}
138 
139 	public void setParent(Object obj) {
140 		if (obj == null) {
141 			throw new IllegalArgumentException("Parent bean cannot be set to a null runtime bean reference!");
142 		}
143 		if (obj instanceof String) {
144 			this.parentName = (String) obj;
145 		}
146 		else if (obj instanceof RuntimeBeanReference) {
147 			this.parentName = ((RuntimeBeanReference) obj).getBeanName();
148 		}
149 		else if (obj instanceof GroovyBeanDefinitionWrapper) {
150 			this.parentName = ((GroovyBeanDefinitionWrapper) obj).getBeanName();
151 		}
152 		getBeanDefinition().setParentName(this.parentName);
153 		getBeanDefinition().setAbstract(false);
154 	}
155 
156 	public GroovyBeanDefinitionWrapper addProperty(String propertyName, Object propertyValue) {
157 		if (propertyValue instanceof GroovyBeanDefinitionWrapper) {
158 			propertyValue = ((GroovyBeanDefinitionWrapper) propertyValue).getBeanDefinition();
159 		}
160 		getBeanDefinition().getPropertyValues().add(propertyName, propertyValue);
161 		return this;
162 	}
163 
164 
165 	public Object getProperty(String property) {
166 		if (this.definitionWrapper.isReadableProperty(property)) {
167 			return this.definitionWrapper.getPropertyValue(property);
168 		}
169 		else if (dynamicProperties.contains(property)) {
170 			return null;
171 		}
172 		return super.getProperty(property);
173 	}
174 
175 	public void setProperty(String property, Object newValue) {
176 		if (PARENT.equals(property)) {
177 			setParent(newValue);
178 		}
179 		else {
180 			AbstractBeanDefinition bd = getBeanDefinition();
181 			if (AUTOWIRE.equals(property)) {
182 				if ("byName".equals(newValue)) {
183 					bd.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME);
184 				}
185 				else if ("byType".equals(newValue)) {
186 					bd.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE);
187 				}
188 				else if ("constructor".equals(newValue)) {
189 					bd.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
190 				}
191 				else if (Boolean.TRUE.equals(newValue)) {
192 					bd.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME);
193 				}
194 			}
195 			// constructorArgs
196 			else if (CONSTRUCTOR_ARGS.equals(property) && newValue instanceof List) {
197 				ConstructorArgumentValues cav = new ConstructorArgumentValues();
198 				List args = (List) newValue;
199 				for (Object arg : args) {
200 					cav.addGenericArgumentValue(arg);
201 				}
202 				bd.setConstructorArgumentValues(cav);
203 			}
204 			// factoryBean
205 			else if (FACTORY_BEAN.equals(property)) {
206 				if (newValue != null) {
207 					bd.setFactoryBeanName(newValue.toString());
208 				}
209 			}
210 			// factoryMethod
211 			else if (FACTORY_METHOD.equals(property)) {
212 				if (newValue != null)
213 					bd.setFactoryMethodName(newValue.toString());
214 			}
215 			// initMethod
216 			else if (INIT_METHOD.equals(property)) {
217 				if (newValue != null) {
218 					bd.setInitMethodName(newValue.toString());
219 				}
220 			}
221 			// destroyMethod
222 			else if (DESTROY_METHOD.equals(property)) {
223 				if (newValue != null) {
224 					bd.setDestroyMethodName(newValue.toString());
225 				}
226 			}
227 			// singleton property
228 			else if (SINGLETON.equals(property)) {
229 				bd.setScope(Boolean.TRUE.equals(newValue) ?
230 						BeanDefinition.SCOPE_SINGLETON : BeanDefinition.SCOPE_PROTOTYPE);
231 			}
232 			else if (this.definitionWrapper.isWritableProperty(property)) {
233 				this.definitionWrapper.setPropertyValue(property, newValue);
234 			}
235 			else {
236 				super.setProperty(property, newValue);
237 			}
238 		}
239 	}
240 
241 }