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