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