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