1 package org
.argeo
.slc
.core
.execution
;
3 import java
.beans
.PropertyDescriptor
;
4 import java
.util
.HashSet
;
5 import java
.util
.Iterator
;
10 import org
.apache
.commons
.logging
.Log
;
11 import org
.apache
.commons
.logging
.LogFactory
;
12 import org
.argeo
.slc
.SlcException
;
13 import org
.argeo
.slc
.execution
.ExecutionContext
;
14 import org
.argeo
.slc
.execution
.ExecutionFlow
;
15 import org
.springframework
.beans
.BeansException
;
16 import org
.springframework
.beans
.MutablePropertyValues
;
17 import org
.springframework
.beans
.PropertyValue
;
18 import org
.springframework
.beans
.PropertyValues
;
19 import org
.springframework
.beans
.factory
.BeanDefinitionStoreException
;
20 import org
.springframework
.beans
.factory
.config
.InstantiationAwareBeanPostProcessorAdapter
;
21 import org
.springframework
.beans
.factory
.config
.TypedStringValue
;
22 import org
.springframework
.beans
.factory
.support
.ManagedList
;
23 import org
.springframework
.beans
.factory
.support
.ManagedMap
;
24 import org
.springframework
.beans
.factory
.support
.ManagedSet
;
25 import org
.springframework
.util
.ObjectUtils
;
26 import org
.springframework
.util
.StringUtils
;
28 public class ExecutionParameterPostProcessor
extends
29 InstantiationAwareBeanPostProcessorAdapter
{
31 private final static Log log
= LogFactory
32 .getLog(ExecutionParameterPostProcessor
.class);
34 private ExecutionContext executionContext
;
35 private InstantiationManager instantiationManager
;
37 private String placeholderPrefix
= "@{";
38 private String placeholderSuffix
= "}";
39 private String nullValue
;
42 public PropertyValues
postProcessPropertyValues(PropertyValues pvs
,
43 PropertyDescriptor
[] pds
, Object bean
, String beanName
)
44 throws BeansException
{
46 // TODO: resolve at execution only if scope is execution
47 // TODO: deal with placeholders in RuntimeBeanReference and
48 // RuntimeBeanNameReference
50 MutablePropertyValues newPvs
= new MutablePropertyValues();
52 boolean changesOccured
= false;
54 for (PropertyValue pv
: pvs
.getPropertyValues()) {
55 Object convertedValue
= resolveValue(beanName
, bean
, pv
.getValue());
56 newPvs
.addPropertyValue(new PropertyValue(pv
, convertedValue
));
57 if (convertedValue
!= pv
.getValue()) {
58 changesOccured
= true;
62 return changesOccured ? newPvs
: pvs
;
66 public boolean postProcessAfterInstantiation(Object bean
, String beanName
)
67 throws BeansException
{
68 if (bean
instanceof ExecutionFlow
)
69 instantiationManager
.flowInitializationStarted(
70 (ExecutionFlow
) bean
, beanName
);
75 public Object
postProcessAfterInitialization(Object bean
, String beanName
)
76 throws BeansException
{
77 if (bean
instanceof ExecutionFlow
)
78 instantiationManager
.flowInitializationFinished(
79 (ExecutionFlow
) bean
, beanName
);
83 protected String
resolvePlaceholder(Object bean
, String placeholder
) {
84 if (instantiationManager
.isInFlowInitialization())
85 return instantiationManager
.getInitializingFlowParameter(
86 placeholder
).toString();
89 // next call fail if no execution context available
90 Object obj
= executionContext
.getVariable(placeholder
);
92 return obj
.toString();
99 @SuppressWarnings(value
= { "unchecked" })
100 public Object
resolveValue(String beanName
, Object bean
, Object value
) {
101 if (value
instanceof TypedStringValue
) {
102 TypedStringValue tsv
= (TypedStringValue
) value
;
103 String originalValue
= tsv
.getValue();
105 String convertedValue
= resolveString(beanName
, bean
, originalValue
);
106 if (convertedValue
== null)
108 return convertedValue
.equals(originalValue
) ? value
109 : new TypedStringValue(convertedValue
);
110 } else if (value
instanceof String
) {
111 String originalValue
= value
.toString();
112 String convertedValue
= resolveString(beanName
, bean
, originalValue
);
113 if (convertedValue
== null)
115 return convertedValue
.equals(originalValue
) ? value
117 } else if (value
instanceof ManagedMap
) {
118 Map mapVal
= (Map
) value
;
120 Map newContent
= new ManagedMap();
121 boolean entriesModified
= false;
122 for (Iterator it
= mapVal
.entrySet().iterator(); it
.hasNext();) {
123 Map
.Entry entry
= (Map
.Entry
) it
.next();
124 Object key
= entry
.getKey();
125 int keyHash
= (key
!= null ? key
.hashCode() : 0);
126 Object newKey
= resolveValue(beanName
, bean
, key
);
127 int newKeyHash
= (newKey
!= null ? newKey
.hashCode() : 0);
128 Object val
= entry
.getValue();
129 Object newVal
= resolveValue(beanName
, bean
, val
);
130 newContent
.put(newKey
, newVal
);
131 entriesModified
= entriesModified
132 || (newVal
!= val
|| newKey
!= key
|| newKeyHash
!= keyHash
);
135 return entriesModified ? newContent
: value
;
136 } else if (value
instanceof ManagedList
) {
137 List listVal
= (List
) value
;
138 List newContent
= new ManagedList();
139 boolean valueModified
= false;
141 for (int i
= 0; i
< listVal
.size(); i
++) {
142 Object elem
= listVal
.get(i
);
143 Object newVal
= resolveValue(beanName
, bean
, elem
);
144 newContent
.add(newVal
);
145 if (!ObjectUtils
.nullSafeEquals(newVal
, elem
)) {
146 valueModified
= true;
149 return valueModified ? newContent
: value
;
150 } else if (value
instanceof ManagedSet
) {
151 Set setVal
= (Set
) value
;
152 Set newContent
= new ManagedSet();
153 boolean entriesModified
= false;
154 for (Iterator it
= setVal
.iterator(); it
.hasNext();) {
155 Object elem
= it
.next();
156 int elemHash
= (elem
!= null ? elem
.hashCode() : 0);
157 Object newVal
= resolveValue(beanName
, bean
, elem
);
158 int newValHash
= (newVal
!= null ? newVal
.hashCode() : 0);
159 newContent
.add(newVal
);
160 entriesModified
= entriesModified
161 || (newVal
!= elem
|| newValHash
!= elemHash
);
163 return entriesModified ? newContent
: value
;
165 // log.debug(beanName + ": " + value.getClass() + " : " + value);
171 private String
resolveString(String beanName
, Object bean
, String strVal
) {
172 // in case <null/> is passed
176 String value
= parseStringValue(bean
, strVal
, new HashSet
<String
>());
179 throw new SlcException("Could not resolve placeholder '" + strVal
180 + "' in bean '" + beanName
+ "'");
182 return (value
.equals(nullValue
) ?
null : value
);
185 public void setPlaceholderPrefix(String placeholderPrefix
) {
186 this.placeholderPrefix
= placeholderPrefix
;
189 public void setPlaceholderSuffix(String placeholderSuffix
) {
190 this.placeholderSuffix
= placeholderSuffix
;
193 public void setNullValue(String nullValue
) {
194 this.nullValue
= nullValue
;
197 public void setInstantiationManager(
198 InstantiationManager instantiationManager
) {
199 this.instantiationManager
= instantiationManager
;
202 public void setExecutionContext(ExecutionContext executionContext
) {
203 this.executionContext
= executionContext
;
207 // Following methods hacked from the internals of
208 // PropertyPlaceholderConfigurer
211 protected String
parseStringValue(Object bean
, String strVal
,
212 Set
<String
> visitedPlaceholders
)
213 throws BeanDefinitionStoreException
{
215 // in case <null/> is passed
219 StringBuffer buf
= new StringBuffer(strVal
);
221 int startIndex
= strVal
.indexOf(placeholderPrefix
);
222 while (startIndex
!= -1) {
223 int endIndex
= findPlaceholderEndIndex(buf
, startIndex
);
224 if (endIndex
!= -1) {
225 String placeholder
= buf
.substring(startIndex
226 + placeholderPrefix
.length(), endIndex
);
227 if (!visitedPlaceholders
.add(placeholder
)) {
228 throw new BeanDefinitionStoreException(
229 "Circular placeholder reference '" + placeholder
230 + "' in property definitions");
232 // Recursive invocation, parsing placeholders contained in
233 // the placeholder key.
234 placeholder
= parseStringValue(bean
, placeholder
,
235 visitedPlaceholders
);
236 // Now obtain the value for the fully resolved key...
237 String propVal
= resolvePlaceholder(bean
, placeholder
);
238 if (propVal
!= null) {
239 // Recursive invocation, parsing placeholders contained
241 // previously resolved placeholder value.
242 propVal
= parseStringValue(bean
, propVal
,
243 visitedPlaceholders
);
244 buf
.replace(startIndex
, endIndex
245 + placeholderSuffix
.length(), propVal
);
246 if (log
.isTraceEnabled()) {
247 log
.trace("Resolved placeholder '" + placeholder
+ "'");
249 startIndex
= buf
.indexOf(placeholderPrefix
, startIndex
252 throw new BeanDefinitionStoreException(
253 "Could not resolve placeholder '" + placeholder
256 visitedPlaceholders
.remove(placeholder
);
262 return buf
.toString();
265 private int findPlaceholderEndIndex(CharSequence buf
, int startIndex
) {
266 int index
= startIndex
+ placeholderPrefix
.length();
267 int withinNestedPlaceholder
= 0;
268 while (index
< buf
.length()) {
269 if (StringUtils
.substringMatch(buf
, index
, placeholderSuffix
)) {
270 if (withinNestedPlaceholder
> 0) {
271 withinNestedPlaceholder
--;
272 index
= index
+ placeholderSuffix
.length();
276 } else if (StringUtils
277 .substringMatch(buf
, index
, placeholderPrefix
)) {
278 withinNestedPlaceholder
++;
279 index
= index
+ placeholderPrefix
.length();