1
2
3
4
5
6
7
8
9
10 package org.mule.config.spring.parsers;
11
12 import org.mule.api.lifecycle.Disposable;
13 import org.mule.api.lifecycle.Initialisable;
14 import org.mule.config.spring.MuleHierarchicalBeanDefinitionParserDelegate;
15 import org.mule.config.spring.parsers.assembly.BeanAssembler;
16 import org.mule.config.spring.parsers.assembly.BeanAssemblerFactory;
17 import org.mule.config.spring.parsers.assembly.DefaultBeanAssemblerFactory;
18 import org.mule.config.spring.parsers.assembly.configuration.ReusablePropertyConfiguration;
19 import org.mule.config.spring.parsers.assembly.configuration.ValueMap;
20 import org.mule.config.spring.parsers.generic.AutoIdUtils;
21 import org.mule.util.ClassUtils;
22 import org.mule.util.XMLUtils;
23
24 import java.util.HashSet;
25 import java.util.Iterator;
26 import java.util.LinkedList;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.springframework.beans.factory.BeanDefinitionStoreException;
34 import org.springframework.beans.factory.config.BeanDefinition;
35 import org.springframework.beans.factory.support.AbstractBeanDefinition;
36 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
37 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
38 import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
39 import org.springframework.beans.factory.xml.ParserContext;
40 import org.w3c.dom.Attr;
41 import org.w3c.dom.Element;
42 import org.w3c.dom.NamedNodeMap;
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 public abstract class AbstractMuleBeanDefinitionParser extends AbstractBeanDefinitionParser
88 implements MuleDefinitionParser
89 {
90
91 public static final String ROOT_ELEMENT = "mule";
92 public static final String ATTRIBUTE_ID = "id";
93 public static final String ATTRIBUTE_NAME = "name";
94 public static final String ATTRIBUTE_CLASS = "class";
95 public static final String ATTRIBUTE_REF = "ref";
96 public static final String ATTRIBUTE_REFS = "refs";
97 public static final String ATTRIBUTE_REF_SUFFIX = "-" + ATTRIBUTE_REF;
98 public static final String ATTRIBUTE_REFS_SUFFIX = "-" + ATTRIBUTE_REFS;
99
100
101
102
103 protected transient Log logger = LogFactory.getLog(getClass());
104
105 private BeanAssemblerFactory beanAssemblerFactory = new DefaultBeanAssemblerFactory();
106 protected ReusablePropertyConfiguration beanPropertyConfiguration = new ReusablePropertyConfiguration();
107 private ParserContext parserContext;
108 private BeanDefinitionRegistry registry;
109 private LinkedList preProcessors = new LinkedList();
110 private List postProcessors = new LinkedList();
111 private Set beanAttributes = new HashSet();
112
113 protected boolean singleton = false;
114
115
116 private boolean allowClassAttribute = true;
117 private Class classConstraint = null;
118
119 public AbstractMuleBeanDefinitionParser()
120 {
121 addIgnored(ATTRIBUTE_ID);
122 addBeanFlag(MuleHierarchicalBeanDefinitionParserDelegate.MULE_FORCE_RECURSE);
123 }
124
125 public MuleDefinitionParserConfiguration addReference(String propertyName)
126 {
127 beanPropertyConfiguration.addReference(propertyName);
128 return this;
129 }
130
131 public MuleDefinitionParserConfiguration addMapping(String propertyName, Map mappings)
132 {
133 beanPropertyConfiguration.addMapping(propertyName, mappings);
134 return this;
135 }
136
137 public MuleDefinitionParserConfiguration addMapping(String propertyName, String mappings)
138 {
139 beanPropertyConfiguration.addMapping(propertyName, mappings);
140 return this;
141 }
142
143 public MuleDefinitionParserConfiguration addMapping(String propertyName, ValueMap mappings)
144 {
145 beanPropertyConfiguration.addMapping(propertyName, mappings);
146 return this;
147 }
148
149
150
151
152
153
154 public MuleDefinitionParserConfiguration addAlias(String alias, String propertyName)
155 {
156 beanPropertyConfiguration.addAlias(alias, propertyName);
157 return this;
158 }
159
160
161
162
163
164 public MuleDefinitionParserConfiguration addCollection(String propertyName)
165 {
166 beanPropertyConfiguration.addCollection(propertyName);
167 return this;
168 }
169
170
171
172
173
174 public MuleDefinitionParserConfiguration addIgnored(String propertyName)
175 {
176 beanPropertyConfiguration.addIgnored(propertyName);
177 return this;
178 }
179
180 public MuleDefinitionParserConfiguration removeIgnored(String propertyName)
181 {
182 beanPropertyConfiguration.removeIgnored(propertyName);
183 return this;
184 }
185
186 public MuleDefinitionParserConfiguration setIgnoredDefault(boolean ignoreAll)
187 {
188 beanPropertyConfiguration.setIgnoredDefault(ignoreAll);
189 return this;
190 }
191
192 protected void processProperty(Attr attribute, BeanAssembler assembler)
193 {
194 assembler.extendBean(attribute);
195 }
196
197
198
199
200
201
202
203
204 protected void postProcess(ParserContext context, BeanAssembler assembler, Element element)
205 {
206 element.setAttribute(ATTRIBUTE_NAME, getBeanName(element));
207 for (Iterator attributes = beanAttributes.iterator(); attributes.hasNext();)
208 {
209 assembler.setBeanFlag((String) attributes.next());
210 }
211 for (Iterator processes = postProcessors.iterator(); processes.hasNext();)
212 {
213 ((PostProcessor) processes.next()).postProcess(context, assembler, element);
214 }
215 }
216
217
218
219
220
221
222
223
224 protected void preProcess(Element element)
225 {
226 parserContext = null;
227 registry = null;
228 beanPropertyConfiguration.reset();
229 Iterator processes = preProcessors.iterator();
230 while (processes.hasNext())
231 {
232 ((PreProcessor) processes.next()).preProcess(beanPropertyConfiguration, element);
233 }
234 }
235
236
237
238
239
240
241
242
243
244
245
246
247
248 protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext)
249 {
250 preProcess(element);
251 setParserContext(parserContext);
252 setRegistry(parserContext.getRegistry());
253 checkElementNameUnique(element);
254 Class beanClass = getClassInternal(element);
255 BeanDefinitionBuilder builder = createBeanDefinitionBuilder(element, beanClass);
256 builder.getRawBeanDefinition().setSource(parserContext.extractSource(element));
257 builder.setScope(isSingleton() ? BeanDefinition.SCOPE_SINGLETON : BeanDefinition.SCOPE_PROTOTYPE);
258
259 List interfaces = ClassUtils.getAllInterfaces(beanClass);
260 if(interfaces!=null)
261 {
262 if(interfaces.contains(Initialisable.class))
263 {
264 builder.setInitMethodName(Initialisable.PHASE_NAME);
265 }
266
267 if(interfaces.contains(Disposable.class))
268 {
269 builder.setDestroyMethodName(Disposable.PHASE_NAME);
270 }
271 }
272
273 if (parserContext.isNested())
274 {
275
276 builder.setScope(parserContext.getContainingBeanDefinition().isSingleton()
277 ? BeanDefinition.SCOPE_SINGLETON : BeanDefinition.SCOPE_PROTOTYPE);
278 }
279
280 doParse(element, parserContext, builder);
281 return builder.getBeanDefinition();
282 }
283
284 protected void setRegistry(BeanDefinitionRegistry registry)
285 {
286 this.registry = registry;
287 }
288
289 protected BeanDefinitionRegistry getRegistry()
290 {
291 if (null == registry)
292 {
293 throw new IllegalStateException("Set the registry from within doParse");
294 }
295 return registry;
296 }
297
298 protected void checkElementNameUnique(Element element)
299 {
300 if (null != element.getAttributeNode(ATTRIBUTE_NAME))
301 {
302 String name = element.getAttribute(ATTRIBUTE_NAME);
303 if (getRegistry().containsBeanDefinition(name))
304 {
305 throw new IllegalArgumentException("A service named " + name + " already exists.");
306 }
307 }
308 }
309
310 protected BeanDefinitionBuilder createBeanDefinitionBuilder(Element element, Class beanClass)
311 {
312 return BeanDefinitionBuilder.rootBeanDefinition(beanClass);
313 }
314
315 protected Class getClassInternal(Element element)
316 {
317 Class beanClass = null;
318 if (isAllowClassAttribute())
319 {
320 beanClass = getBeanClassFromAttribute(element);
321 }
322 if (beanClass == null)
323 {
324 beanClass = getBeanClass(element);
325 }
326 if (null != beanClass && null != classConstraint && !classConstraint.isAssignableFrom(beanClass))
327 {
328 throw new IllegalStateException(beanClass + " not a subclass of " + classConstraint +
329 " for " + XMLUtils.elementToString(element));
330 }
331 if (null == beanClass)
332 {
333 throw new IllegalStateException("No class for element " + XMLUtils.elementToString(element));
334 }
335 return beanClass;
336 }
337
338
339
340
341
342
343
344
345
346
347 protected Class getBeanClassFromAttribute(Element element)
348 {
349 String att= beanPropertyConfiguration.getAttributeAlias(ATTRIBUTE_CLASS);
350 String className = element.getAttribute(att);
351 Class clazz = null;
352 if (org.mule.util.StringUtils.isNotBlank(className))
353 {
354 try
355 {
356 element.removeAttribute(att);
357
358 clazz = ClassUtils.loadClass(className, getClass());
359 }
360 catch (ClassNotFoundException e)
361 {
362 logger.error("could not load class: " + className, e);
363 }
364 }
365 return clazz;
366 }
367
368
369
370
371
372
373
374
375
376 protected abstract Class getBeanClass(Element element);
377
378
379
380
381
382
383
384
385
386
387
388 protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder)
389 {
390 BeanAssembler assembler = getBeanAssembler(element, builder);
391 NamedNodeMap attributes = element.getAttributes();
392 for (int x = 0; x < attributes.getLength(); x++)
393 {
394 Attr attribute = (Attr) attributes.item(x);
395 processProperty(attribute, assembler);
396 }
397 postProcess(getParserContext(), assembler, element);
398 }
399
400
401 protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) throws BeanDefinitionStoreException
402 {
403 return getBeanName(element);
404 }
405
406 protected boolean isSingleton()
407 {
408 return singleton;
409 }
410
411
412
413
414
415
416
417
418 protected BeanAssembler getBeanAssembler(Element element, BeanDefinitionBuilder bean)
419 {
420 return getBeanAssemblerFactory().newBeanAssembler(
421 beanPropertyConfiguration, bean, beanPropertyConfiguration, null);
422 }
423
424 protected boolean isAllowClassAttribute()
425 {
426 return allowClassAttribute;
427 }
428
429 protected void setAllowClassAttribute(boolean allowClassAttribute)
430 {
431 this.allowClassAttribute = allowClassAttribute;
432 }
433
434 protected Class getClassConstraint()
435 {
436 return classConstraint;
437 }
438
439 protected void setClassConstraint(Class classConstraint)
440 {
441 this.classConstraint = classConstraint;
442 }
443
444 protected ParserContext getParserContext()
445 {
446 return parserContext;
447 }
448
449 protected void setParserContext(ParserContext parserContext)
450 {
451 this.parserContext = parserContext;
452 }
453
454
455
456
457
458 protected boolean isTopLevel(Element element)
459 {
460 return element.getParentNode().getLocalName().equals(ROOT_ELEMENT);
461 }
462
463 public AbstractBeanDefinition muleParse(Element element, ParserContext parserContext)
464 {
465 return parseInternal(element, parserContext);
466 }
467
468 public MuleDefinitionParserConfiguration registerPreProcessor(PreProcessor preProcessor)
469 {
470 preProcessors.addFirst(preProcessor);
471 return this;
472 }
473
474 public MuleDefinitionParserConfiguration registerPostProcessor(PostProcessor postProcessor)
475 {
476 postProcessors.add(postProcessor);
477 return this;
478 }
479
480 public BeanAssemblerFactory getBeanAssemblerFactory()
481 {
482 return beanAssemblerFactory;
483 }
484
485 public void setBeanAssemblerFactory(BeanAssemblerFactory beanAssemblerFactory)
486 {
487 this.beanAssemblerFactory = beanAssemblerFactory;
488 }
489
490 public String getBeanName(Element element)
491 {
492 return AutoIdUtils.getUniqueName(element, "mule-bean");
493 }
494
495 public MuleDefinitionParserConfiguration addBeanFlag(String flag)
496 {
497 beanAttributes.add(flag);
498 return this;
499 }
500
501 }