1
2
3
4
5
6
7 package org.mule.config.spring.parsers;
8
9 import org.mule.api.MuleContext;
10 import org.mule.api.component.Component;
11 import org.mule.api.config.MuleProperties;
12 import org.mule.api.lifecycle.Disposable;
13 import org.mule.api.lifecycle.Initialisable;
14 import org.mule.api.routing.OutboundRouter;
15 import org.mule.api.routing.OutboundRouterCollection;
16 import org.mule.api.source.MessageSource;
17 import org.mule.api.transformer.Transformer;
18 import org.mule.config.spring.MuleHierarchicalBeanDefinitionParserDelegate;
19 import org.mule.config.spring.parsers.assembly.BeanAssembler;
20 import org.mule.config.spring.parsers.assembly.BeanAssemblerFactory;
21 import org.mule.config.spring.parsers.assembly.DefaultBeanAssemblerFactory;
22 import org.mule.config.spring.parsers.assembly.configuration.ReusablePropertyConfiguration;
23 import org.mule.config.spring.parsers.assembly.configuration.ValueMap;
24 import org.mule.config.spring.parsers.generic.AutoIdUtils;
25 import org.mule.enricher.MessageEnricher;
26 import org.mule.exception.AbstractExceptionListener;
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.LinkedList;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Set;
36
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39 import org.springframework.beans.factory.BeanDefinitionStoreException;
40 import org.springframework.beans.factory.config.BeanDefinition;
41 import org.springframework.beans.factory.support.AbstractBeanDefinition;
42 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
43 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
44 import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
45 import org.springframework.beans.factory.xml.ParserContext;
46 import org.w3c.dom.Attr;
47 import org.w3c.dom.Element;
48 import org.w3c.dom.NamedNodeMap;
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
88
89
90
91
92
93 public abstract class AbstractMuleBeanDefinitionParser extends AbstractBeanDefinitionParser
94 implements MuleDefinitionParser
95 {
96 public static final String ROOT_ELEMENT = "mule";
97 public static final String ATTRIBUTE_ID = "id";
98 public static final String ATTRIBUTE_NAME = "name";
99 public static final String ATTRIBUTE_CLASS = "class";
100 public static final String ATTRIBUTE_REF = "ref";
101 public static final String ATTRIBUTE_REFS = "refs";
102 public static final String ATTRIBUTE_REF_SUFFIX = "-" + ATTRIBUTE_REF;
103 public static final String ATTRIBUTE_REFS_SUFFIX = "-" + ATTRIBUTE_REFS;
104
105
106
107
108 protected transient Log logger = LogFactory.getLog(getClass());
109
110 private BeanAssemblerFactory beanAssemblerFactory = new DefaultBeanAssemblerFactory();
111 protected ReusablePropertyConfiguration beanPropertyConfiguration = new ReusablePropertyConfiguration();
112 private ParserContext parserContext;
113 private BeanDefinitionRegistry registry;
114 private LinkedList<PreProcessor> preProcessors = new LinkedList<PreProcessor>();
115 private List<PostProcessor> postProcessors = new LinkedList<PostProcessor>();
116 private Set<String> beanAttributes = new HashSet<String>();
117
118 protected boolean singleton = false;
119
120
121 private boolean allowClassAttribute = true;
122 private Class<?> classConstraint = null;
123
124 private String deprecationWarning;
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 (String attribute : beanAttributes)
215 {
216 assembler.setBeanFlag(attribute);
217 }
218 for (PostProcessor processor : postProcessors)
219 {
220 processor.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 for (PreProcessor processor : preProcessors)
237 {
238 processor.preProcess(beanPropertyConfiguration, element);
239 }
240 }
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255 @Override
256 protected AbstractBeanDefinition parseInternal(Element element, ParserContext context)
257 {
258 preProcess(element);
259 setParserContext(context);
260 setRegistry(context.getRegistry());
261 checkElementNameUnique(element);
262 Class<?> beanClass = getClassInternal(element);
263 BeanDefinitionBuilder builder = createBeanDefinitionBuilder(element, beanClass);
264 builder.getRawBeanDefinition().setSource(context.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 && !AbstractExceptionListener.class.isAssignableFrom(beanClass)
273 && !MessageEnricher.class.isAssignableFrom(beanClass)
274 && !Transformer.class.isAssignableFrom(beanClass))
275 {
276 if (Initialisable.class.isAssignableFrom(beanClass))
277 {
278 builder.setInitMethodName(Initialisable.PHASE_NAME);
279 }
280
281 if (Disposable.class.isAssignableFrom(beanClass))
282 {
283 builder.setDestroyMethodName(Disposable.PHASE_NAME);
284 }
285 }
286
287 if (context.isNested())
288 {
289
290 builder.setScope(context.getContainingBeanDefinition().isSingleton()
291 ? BeanDefinition.SCOPE_SINGLETON : BeanDefinition.SCOPE_PROTOTYPE);
292 }
293
294 doParse(element, context, builder);
295 return builder.getBeanDefinition();
296 }
297
298 protected void setRegistry(BeanDefinitionRegistry registry)
299 {
300 this.registry = registry;
301 }
302
303 protected BeanDefinitionRegistry getRegistry()
304 {
305 if (null == registry)
306 {
307 throw new IllegalStateException("Set the registry from within doParse");
308 }
309 return registry;
310 }
311
312 protected void checkElementNameUnique(Element element)
313 {
314 if (null != element.getAttributeNode(ATTRIBUTE_NAME))
315 {
316 String name = element.getAttribute(ATTRIBUTE_NAME);
317 if (getRegistry().containsBeanDefinition(name))
318 {
319 throw new IllegalArgumentException("A service named " + name + " already exists.");
320 }
321 }
322 }
323
324 protected BeanDefinitionBuilder createBeanDefinitionBuilder(Element element, Class<?> beanClass)
325 {
326 BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(beanClass);
327
328 if (ClassUtils.getConstructor(beanClass, new Class[]{MuleContext.class}, true) != null)
329 {
330 builder.addConstructorArgReference(MuleProperties.OBJECT_MULE_CONTEXT);
331 }
332 return builder;
333 }
334
335 protected Class<?> getClassInternal(Element element)
336 {
337 Class<?> beanClass = null;
338 if (isAllowClassAttribute())
339 {
340 beanClass = getBeanClassFromAttribute(element);
341 }
342 if (beanClass == null)
343 {
344 beanClass = getBeanClass(element);
345 }
346 if (null != beanClass && null != classConstraint && !classConstraint.isAssignableFrom(beanClass))
347 {
348 throw new IllegalStateException(beanClass + " not a subclass of " + classConstraint +
349 " for " + XMLUtils.elementToString(element));
350 }
351 if (null == beanClass)
352 {
353 throw new IllegalStateException("No class for element " + XMLUtils.elementToString(element));
354 }
355 return beanClass;
356 }
357
358
359
360
361
362
363
364
365
366
367 protected Class<?> getBeanClassFromAttribute(Element element)
368 {
369 String att = beanPropertyConfiguration.getAttributeAlias(ATTRIBUTE_CLASS);
370 String className = element.getAttribute(att);
371 Class<?> clazz = null;
372 if (StringUtils.isNotBlank(className))
373 {
374 try
375 {
376 element.removeAttribute(att);
377 clazz = ClassUtils.loadClass(className, getClass());
378 }
379 catch (ClassNotFoundException e)
380 {
381 logger.error("could not load class: " + className, e);
382 }
383 }
384 return clazz;
385 }
386
387
388
389
390
391
392
393
394
395 protected abstract Class<?> getBeanClass(Element element);
396
397
398
399
400
401
402
403
404
405
406
407
408
409 protected void doParse(Element element, ParserContext context, BeanDefinitionBuilder builder)
410 {
411 if (deprecationWarning != null && logger.isWarnEnabled())
412 {
413 logger.warn("Schema warning: Use of element <" + element.getLocalName() + "> is deprecated. " + deprecationWarning);
414 }
415
416 BeanAssembler assembler = getBeanAssembler(element, builder);
417 NamedNodeMap attributes = element.getAttributes();
418 for (int x = 0; x < attributes.getLength(); x++)
419 {
420 Attr attribute = (Attr) attributes.item(x);
421 processProperty(attribute, assembler);
422 }
423 postProcess(getParserContext(), assembler, element);
424 }
425
426 @Override
427 protected String resolveId(Element element, AbstractBeanDefinition definition,
428 ParserContext context) throws BeanDefinitionStoreException
429 {
430 return getBeanName(element);
431 }
432
433 protected boolean isSingleton()
434 {
435 return singleton;
436 }
437
438
439
440
441
442
443
444
445 protected BeanAssembler getBeanAssembler(Element element, BeanDefinitionBuilder bean)
446 {
447 return getBeanAssemblerFactory().newBeanAssembler(
448 beanPropertyConfiguration, bean, beanPropertyConfiguration, null);
449 }
450
451 protected boolean isAllowClassAttribute()
452 {
453 return allowClassAttribute;
454 }
455
456 protected void setAllowClassAttribute(boolean allowClassAttribute)
457 {
458 this.allowClassAttribute = allowClassAttribute;
459 }
460
461 protected Class<?> getClassConstraint()
462 {
463 return classConstraint;
464 }
465
466 protected void setClassConstraint(Class<?> classConstraint)
467 {
468 this.classConstraint = classConstraint;
469 }
470
471 protected ParserContext getParserContext()
472 {
473 return parserContext;
474 }
475
476 protected void setParserContext(ParserContext parserContext)
477 {
478 this.parserContext = parserContext;
479 }
480
481
482
483
484
485 protected boolean isTopLevel(Element element)
486 {
487 return element.getParentNode().getLocalName().equals(ROOT_ELEMENT);
488 }
489
490 public AbstractBeanDefinition muleParse(Element element, ParserContext context)
491 {
492 return parseInternal(element, context);
493 }
494
495 public MuleDefinitionParserConfiguration registerPreProcessor(PreProcessor preProcessor)
496 {
497 preProcessors.addFirst(preProcessor);
498 return this;
499 }
500
501 public MuleDefinitionParserConfiguration registerPostProcessor(PostProcessor postProcessor)
502 {
503 postProcessors.add(postProcessor);
504 return this;
505 }
506
507 public BeanAssemblerFactory getBeanAssemblerFactory()
508 {
509 return beanAssemblerFactory;
510 }
511
512 public void setBeanAssemblerFactory(BeanAssemblerFactory beanAssemblerFactory)
513 {
514 this.beanAssemblerFactory = beanAssemblerFactory;
515 }
516
517 public String getBeanName(Element element)
518 {
519 return AutoIdUtils.getUniqueName(element, "mule-bean");
520 }
521
522 public MuleDefinitionParserConfiguration addBeanFlag(String flag)
523 {
524 beanAttributes.add(flag);
525 return this;
526 }
527
528 public void setDeprecationWarning(String deprecationWarning)
529 {
530 this.deprecationWarning = deprecationWarning;
531 }
532 }