View Javadoc

1   /*
2    * $Id: MuleXmlConfigurationBuilder.java 9540 2007-11-01 14:14:52Z akuzmin $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.config.builders;
12  
13  import org.mule.MuleManager;
14  import org.mule.config.ConfigurationBuilder;
15  import org.mule.config.ConfigurationException;
16  import org.mule.config.MuleConfiguration;
17  import org.mule.config.MuleDtdResolver;
18  import org.mule.config.MuleProperties;
19  import org.mule.config.PoolingProfile;
20  import org.mule.config.QueueProfile;
21  import org.mule.config.ReaderResource;
22  import org.mule.config.ThreadingProfile;
23  import org.mule.config.converters.ConnectorConverter;
24  import org.mule.config.converters.EndpointConverter;
25  import org.mule.config.converters.EndpointURIConverter;
26  import org.mule.config.converters.TransactionFactoryConverter;
27  import org.mule.config.converters.TransformerConverter;
28  import org.mule.config.i18n.CoreMessages;
29  import org.mule.config.pool.CommonsPoolFactory;
30  import org.mule.impl.DefaultLifecycleAdapter;
31  import org.mule.impl.MuleDescriptor;
32  import org.mule.impl.MuleTransactionConfig;
33  import org.mule.impl.endpoint.MuleEndpoint;
34  import org.mule.impl.model.ModelFactory;
35  import org.mule.impl.model.resolvers.DynamicEntryPointResolver;
36  import org.mule.impl.security.MuleSecurityManager;
37  import org.mule.interceptors.InterceptorStack;
38  import org.mule.providers.AbstractConnector;
39  import org.mule.providers.ConnectionStrategy;
40  import org.mule.providers.service.TransportFactory;
41  import org.mule.providers.service.TransportFactoryException;
42  import org.mule.routing.LoggingCatchAllStrategy;
43  import org.mule.routing.inbound.InboundRouterCollection;
44  import org.mule.routing.nested.NestedRouter;
45  import org.mule.routing.nested.NestedRouterCollection;
46  import org.mule.routing.outbound.OutboundRouterCollection;
47  import org.mule.routing.response.ResponseRouterCollection;
48  import org.mule.transaction.constraints.BatchConstraint;
49  import org.mule.umo.UMODescriptor;
50  import org.mule.umo.UMOEncryptionStrategy;
51  import org.mule.umo.UMOInterceptor;
52  import org.mule.umo.UMOInterceptorStack;
53  import org.mule.umo.UMOTransactionFactory;
54  import org.mule.umo.endpoint.UMOEndpoint;
55  import org.mule.umo.endpoint.UMOEndpointURI;
56  import org.mule.umo.lifecycle.InitialisationException;
57  import org.mule.umo.manager.ContainerException;
58  import org.mule.umo.manager.UMOAgent;
59  import org.mule.umo.manager.UMOContainerContext;
60  import org.mule.umo.manager.UMOManager;
61  import org.mule.umo.manager.UMOTransactionManagerFactory;
62  import org.mule.umo.model.UMOModel;
63  import org.mule.umo.provider.UMOConnector;
64  import org.mule.umo.routing.UMOInboundRouterCollection;
65  import org.mule.umo.routing.UMONestedRouterCollection;
66  import org.mule.umo.routing.UMOOutboundRouter;
67  import org.mule.umo.routing.UMOOutboundRouterCollection;
68  import org.mule.umo.routing.UMOResponseRouterCollection;
69  import org.mule.umo.security.UMOEndpointSecurityFilter;
70  import org.mule.umo.security.UMOSecurityManager;
71  import org.mule.umo.security.UMOSecurityProvider;
72  import org.mule.umo.transformer.UMOTransformer;
73  import org.mule.util.ArrayUtils;
74  import org.mule.util.ClassUtils;
75  import org.mule.util.IOUtils;
76  import org.mule.util.PropertiesUtils;
77  import org.mule.util.StringUtils;
78  import org.mule.util.queue.EventFilePersistenceStrategy;
79  
80  import java.beans.ExceptionListener;
81  import java.io.IOException;
82  import java.io.InputStream;
83  import java.io.InputStreamReader;
84  import java.util.ArrayList;
85  import java.util.HashMap;
86  import java.util.Iterator;
87  import java.util.List;
88  import java.util.Map;
89  import java.util.Properties;
90  
91  import org.apache.commons.beanutils.ConvertUtils;
92  import org.apache.commons.digester.AbstractObjectCreationFactory;
93  import org.apache.commons.digester.Digester;
94  import org.apache.commons.digester.ObjectCreateRule;
95  import org.apache.commons.digester.Rule;
96  import org.apache.commons.digester.SetNextRule;
97  import org.apache.commons.digester.SetPropertiesRule;
98  import org.xml.sax.Attributes;
99  
100 /**
101  * <code>MuleXmlConfigurationBuilder</code> is a configuration parser that builds a
102  * MuleManager instance based on a mule xml configration file defined in the
103  * mule-configuration.dtd.
104  */
105 public class MuleXmlConfigurationBuilder extends AbstractDigesterConfiguration
106     implements ConfigurationBuilder
107 {
108     public static final String DEFAULT_ENTRY_POINT_RESOLVER = DynamicEntryPointResolver.class.getName();
109     public static final String DEFAULT_LIFECYCLE_ADAPTER = DefaultLifecycleAdapter.class.getName();
110     public static final String DEFAULT_ENDPOINT = MuleEndpoint.class.getName();
111     public static final String DEFAULT_TRANSACTION_CONFIG = MuleTransactionConfig.class.getName();
112     public static final String DEFAULT_DESCRIPTOR = MuleDescriptor.class.getName();
113     public static final String DEFAULT_SECURITY_MANAGER = MuleSecurityManager.class.getName();
114     public static final String DEFAULT_OUTBOUND_ROUTER_COLLECTION = OutboundRouterCollection.class.getName();
115     public static final String DEFAULT_INBOUND_ROUTER_COLLECTION = InboundRouterCollection.class.getName();
116     public static final String DEFAULT_NESTED_ROUTER_COLLECTION = NestedRouterCollection.class.getName();
117     public static final String DEFAULT_RESPONSE_ROUTER_COLLECTION = ResponseRouterCollection.class.getName();
118     public static final String DEFAULT_NESTED_ROUTER = NestedRouter.class.getName();
119     public static final String DEFAULT_CATCH_ALL_STRATEGY = LoggingCatchAllStrategy.class.getName();
120     public static final String DEFAULT_POOL_FACTORY = CommonsPoolFactory.class.getName();
121     public static final String THREADING_PROFILE = ThreadingProfile.class.getName();
122     public static final String POOLING_PROFILE = PoolingProfile.class.getName();
123     public static final String QUEUE_PROFILE = QueueProfile.class.getName();
124 
125     public static final String PERSISTENCE_STRATEGY_INTERFACE = EventFilePersistenceStrategy.class.getName();
126     public static final String INBOUND_MESSAGE_ROUTER_INTERFACE = UMOInboundRouterCollection.class.getName();
127     public static final String NESTED_MESSAGE_ROUTER_INTERFACE = UMONestedRouterCollection.class.getName();
128     public static final String RESPONSE_MESSAGE_ROUTER_INTERFACE = UMOResponseRouterCollection.class.getName();
129     public static final String OUTBOUND_MESSAGE_ROUTER_INTERFACE = UMOOutboundRouterCollection.class.getName();
130     public static final String TRANSFORMER_INTERFACE = UMOTransformer.class.getName();
131     public static final String TRANSACTION_MANAGER_FACTORY_INTERFACE = UMOTransactionManagerFactory.class.getName();
132     public static final String SECURITY_PROVIDER_INTERFACE = UMOSecurityProvider.class.getName();
133     public static final String ENCRYPTION_STRATEGY_INTERFACE = UMOEncryptionStrategy.class.getName();
134     public static final String ENDPOINT_SECURITY_FILTER_INTERFACE = UMOEndpointSecurityFilter.class.getName();
135     public static final String AGENT_INTERFACE = UMOAgent.class.getName();
136     public static final String TRANSACTION_FACTORY_INTERFACE = UMOTransactionFactory.class.getName();
137     public static final String TRANSACTION_CONSTRAINT_INTERFACE = BatchConstraint.class.getName();
138     public static final String CONNECTOR_INTERFACE = UMOConnector.class.getName();
139     public static final String INTERCEPTOR_INTERFACE = UMOInterceptor.class.getName();
140     public static final String ROUTER_INTERFACE = UMOOutboundRouter.class.getName();
141     public static final String EXCEPTION_STRATEGY_INTERFACE = ExceptionListener.class.getName();
142     public static final String CONNECTION_STRATEGY_INTERFACE = ConnectionStrategy.class.getName();
143 
144     protected UMOManager manager;
145 
146     private final List transformerReferences = new ArrayList();
147     private final List endpointReferences = new ArrayList();
148 
149     public MuleXmlConfigurationBuilder() throws ConfigurationException
150     {
151         super(System.getProperty(MuleProperties.XML_VALIDATE_SYSTEM_PROPERTY, "true")
152             .equalsIgnoreCase("true"), System.getProperty(MuleProperties.XML_DTD_SYSTEM_PROPERTY,
153             MuleDtdResolver.DEFAULT_MULE_DTD));
154 
155         ConvertUtils.register(new EndpointConverter(), UMOEndpoint.class);
156         ConvertUtils.register(new TransformerConverter(), UMOTransformer.class);
157         ConvertUtils.register(new ConnectorConverter(), UMOConnector.class);
158         ConvertUtils.register(new TransactionFactoryConverter(), UMOTransactionFactory.class);
159         ConvertUtils.register(new EndpointURIConverter(), UMOEndpointURI.class);
160 
161         String path = getRootName();
162         addManagerRules(digester, path);
163         addServerPropertiesRules(path + "/environment-properties", "addProperties", 0);
164         addContainerContextRules(path + "/container-context", "setContainerContext", 0);
165 
166         addMuleConfigurationRules(digester, path);
167         addTransformerRules(digester, path);
168         addSecurityManagerRules(digester, path);
169         addTransactionManagerRules(digester, path);
170         addGlobalEndpointRules(digester, path);
171         addEndpointIdentifierRules(digester, path);
172         addInterceptorStackRules(digester, path);
173         addConnectorRules(digester, path);
174         addAgentRules(digester, path);
175 
176         addModelRules(digester, path);
177         // These rules allow for individual component configurations
178         //RM* this is no longer required since Mule supports Multiple models and can inherit existing models.
179         // This means that every mule-descriptor should be wrapped with a model element if its a stand alone
180         //component config
181         //addMuleDescriptorRules(digester, path);
182     }
183 
184     public String getRootName()
185     {
186         return "mule-configuration";
187     }
188 
189     public UMOManager configure(String configResources) throws ConfigurationException
190     {
191         return configure(configResources, null);
192     }
193 
194     public UMOManager configure(String configResources, String startupPropertiesFile)
195         throws ConfigurationException
196     {
197         try
198         {
199             String[] resources = StringUtils.splitAndTrim(configResources, ",");
200             if (logger.isDebugEnabled())
201             {
202                 logger.debug("There is/are " + resources.length + " configuration resource(s): " + ArrayUtils.toString(resources));
203             }
204             MuleManager.getConfiguration().setConfigResources(resources);
205             ReaderResource[] readers = new ReaderResource[resources.length];
206             String resource; 
207             for (int i = 0; i < resources.length; i++)
208             {
209                 resource = resources[i];
210                 readers[i] = new ReaderResource(resource, 
211                                             new InputStreamReader(loadResource(resource), configEncoding));
212             }
213 
214             // Load startup properties if any.
215             if (startupPropertiesFile != null)
216             {
217                 return configure(readers, PropertiesUtils.loadProperties(startupPropertiesFile, getClass()));
218             }
219             else
220             {
221                 return configure(readers, null);
222             }
223 
224         }
225         catch (Exception e)
226         {
227             throw new ConfigurationException(e);
228         }
229     }
230 
231     /**
232      * Override this method to provide alternative ways of loading a resource.
233      */
234     protected InputStream loadResource(String configResource) throws ConfigurationException
235     {
236         try
237         {
238             InputStream input = IOUtils.getResourceAsStream(configResource, getClass());
239             if (input == null)
240             {
241                 throw new ConfigurationException(CoreMessages.cannotLoadFromClasspath(configResource));
242             }
243             return input;
244         }
245         catch (IOException e)
246         {
247             throw new ConfigurationException(CoreMessages.cannotLoadFromClasspath(configResource), e);
248         }
249     }
250     
251     /**
252      * @deprecated Please use configure(ReaderResource[] configResources, Properties
253      *             startupProperties) instead.
254      */
255     public UMOManager configure(ReaderResource[] configResources) throws ConfigurationException
256     {
257         return configure(configResources, null);
258     }
259 
260     public UMOManager configure(ReaderResource[] configResources, Properties startupProperties)
261         throws ConfigurationException
262     {
263         if (startupProperties != null)
264         {
265             ((MuleManager)MuleManager.getInstance()).addProperties(startupProperties);
266         }
267         // Parse the config files with the Digester.
268         manager = (MuleManager)process(configResources);
269         if (manager == null)
270         {
271             throw new ConfigurationException(
272                 CoreMessages.failedToCreateManagerInstance("Are you using a correct configuration builder?"));
273         }
274         try
275         {
276             setContainerProperties();
277             setTransformers();
278             setGlobalEndpoints();
279             if (System.getProperty(MuleProperties.MULE_START_AFTER_CONFIG_SYSTEM_PROPERTY, "true")
280                 .equalsIgnoreCase("true"))
281             {
282                 manager.start();
283             }
284         }
285         catch (Exception e)
286         {
287             throw new ConfigurationException(CoreMessages.objectFailedToInitialise("MuleManager"), e);
288         }
289         return manager;
290     }
291 
292     /**
293      * Indicate whether this ConfigurationBulder has been configured yet
294      *
295      * @return <code>true</code> if this ConfigurationBulder has been configured
296      */
297     public boolean isConfigured()
298     {
299         return manager != null;
300     }
301 
302     protected void setContainerProperties() throws ContainerException
303     {
304         UMOContainerContext ctx = manager.getContainerContext();
305         try
306         {
307             for (Iterator iterator = containerReferences.iterator(); iterator.hasNext();)
308             {
309                 ContainerReference reference = (ContainerReference)iterator.next();
310                 reference.resolveReference(ctx);
311             }
312         }
313         finally
314         {
315             containerReferences.clear();
316         }
317     }
318 
319     protected void setTransformers() throws InitialisationException
320     {
321         try
322         {
323             for (Iterator iterator = transformerReferences.iterator(); iterator.hasNext();)
324             {
325                 TransformerReference reference = (TransformerReference)iterator.next();
326                 reference.resolveTransformer();
327             }
328         }
329         finally
330         {
331             transformerReferences.clear();
332         }
333     }
334 
335     protected void setGlobalEndpoints() throws InitialisationException
336     {
337         // because Mule Xml allows developers to overload global endpoints
338         // we need a way to initialise Global endpoints after the Xml has
339         // been processed but before the MuleManager is initialised. So we do
340         // it here.
341         UMOManager manager = MuleManager.getInstance();
342 
343         // we need to take a copy of the endpoints since we're going to modify them
344         // while iterating
345         Map endpoints = new HashMap(manager.getEndpoints());
346         for (Iterator iterator = endpoints.values().iterator(); iterator.hasNext();)
347         {
348             UMOEndpoint ep = (UMOEndpoint)iterator.next();
349             try
350             {
351                 if (ep.getConnector() == null)
352                 {
353                     UMOConnector connector = TransportFactory.getOrCreateConnectorByProtocol(ep);
354                     if (connector == null)
355                     {
356                         throw new InitialisationException(
357                                 CoreMessages.failedToCreateConnectorFromUri(ep.getEndpointURI()), this);
358 
359                     }
360                     ep.setConnector(connector);
361                 }
362             }
363             catch (TransportFactoryException e)
364             {
365                 throw new InitialisationException(
366                         CoreMessages.failedToCreateConnectorFromUri(ep.getEndpointURI()), e, this);
367             }
368 
369             manager.unregisterEndpoint(ep.getName());
370             manager.registerEndpoint(ep);
371         }
372 
373         try
374         {
375             for (Iterator iterator = endpointReferences.iterator(); iterator.hasNext();)
376             {
377                 EndpointReference reference = (EndpointReference)iterator.next();
378                 reference.resolveEndpoint();
379             }
380         }
381         finally
382         {
383             endpointReferences.clear();
384         }
385     }
386 
387     protected void addManagerRules(Digester digester, String path)
388     {
389         digester.addFactoryCreate(path, new AbstractObjectCreationFactory()
390         {
391             public Object createObject(Attributes attributes) throws Exception
392             {
393                 manager = MuleManager.getInstance();
394                 return manager;
395             }
396         });
397         digester.addSetProperties(path);
398     }
399 
400     protected void addMuleConfigurationRules(Digester digester, String path)
401     {
402         digester.addSetProperties(path);
403         // Create mule system properties and defaults
404         path += "/mule-environment-properties";
405         digester.addObjectCreate(path, MuleConfiguration.class);
406         addSetPropertiesRule(path, digester);
407 
408         // Add pooling profile rules
409         addPoolingProfileRules(digester, path);
410 
411         // Add Queue Profile rules
412         addQueueProfileRules(digester, path);
413 
414         // set threading profile
415         digester.addObjectCreate(path + "/threading-profile", THREADING_PROFILE);
416         SetPropertiesRule threadingRule = new SetPropertiesRule();
417         threadingRule.addAlias("poolExhaustedAction", "poolExhaustedActionString");
418         digester.addRule(path + "/threading-profile", threadingRule);
419         digester.addRule(path + "/threading-profile", new Rule()
420         {
421             private String id;
422 
423             public void begin(String s, String s1, Attributes attributes) throws Exception
424             {
425                 id = attributes.getValue("id");
426             }
427 
428             public void end(String s, String s1) throws Exception
429             {
430                 ThreadingProfile tp = (ThreadingProfile)digester.peek();
431                 MuleConfiguration cfg = (MuleConfiguration)digester.peek(1);
432 
433                 if ("default".equals(id))
434                 {
435                     cfg.setDefaultThreadingProfile(tp);
436                     cfg.setMessageDispatcherThreadingProfile(tp);
437                     cfg.setMessageReceiverThreadingProfile(tp);
438                     cfg.setComponentThreadingProfile(tp);
439                 }
440                 else if ("messageReceiver".equals(id) || "receiver".equals(id))
441                 {
442                     cfg.setMessageReceiverThreadingProfile(tp);
443                 }
444                 else if ("messageDispatcher".equals(id) || "dispatcher".equals(id))
445                 {
446                     cfg.setMessageDispatcherThreadingProfile(tp);
447                 }
448                 else if ("component".equals(id))
449                 {
450                     cfg.setComponentThreadingProfile(tp);
451                 }
452             }
453         });
454 
455         // add persistence strategy
456         digester.addObjectCreate(path + "/persistence-strategy", PERSISTENCE_STRATEGY_INTERFACE, "className");
457         addMulePropertiesRule(path + "/persistence-strategy", digester);
458         digester.addSetNext(path + "/persistence-strategy", "setPersistenceStrategy");
459 
460         // Connection strategy
461         digester.addObjectCreate(path + "/connection-strategy", CONNECTION_STRATEGY_INTERFACE, "className");
462         addMulePropertiesRule(path + "/connection-strategy", digester);
463         // digester.addSetNext(path + "/connection-strategy",
464         // "setConnectionStrategy");
465         digester.addRule(path + "/connection-strategy", new SetNextRule("setConnectionStrategy")
466         {
467             public void end(String s, String s1) throws Exception
468             {
469                 super.end(s, s1);
470             }
471         });
472 
473         digester.addRule(path, new Rule()
474         {
475             public void end(String s, String s1) throws Exception
476             {
477                 MuleManager.setConfiguration((MuleConfiguration)digester.peek());
478             }
479         });
480     }
481 
482     protected void addSecurityManagerRules(Digester digester, String path) throws ConfigurationException
483     {
484         // Create container Context
485         path += "/security-manager";
486         addObjectCreateOrGetFromContainer(path, DEFAULT_SECURITY_MANAGER, "className", "ref", false);
487 
488         // Add propviders
489         digester.addObjectCreate(path + "/security-provider", SECURITY_PROVIDER_INTERFACE, "className");
490         addSetPropertiesRule(path + "/security-provider", digester);
491         addMulePropertiesRule(path + "/security-provider", digester);
492         digester.addSetNext(path + "/security-provider", "addProvider");
493 
494         // Add encryption strategies
495         digester.addObjectCreate(path + "/encryption-strategy", ENCRYPTION_STRATEGY_INTERFACE, "className");
496         addSetPropertiesRule(path + "/encryption-strategy", digester);
497         addMulePropertiesRule(path + "/encryption-strategy", digester);
498         digester.addRule(path + "/encryption-strategy", new Rule()
499         {
500             private String name;
501 
502             public void begin(String endpointName, String endpointName1, Attributes attributes)
503                 throws Exception
504             {
505                 name = attributes.getValue("name");
506             }
507 
508             public void end(String endpointName, String endpointName1) throws Exception
509             {
510                 UMOEncryptionStrategy s = (UMOEncryptionStrategy)digester.peek();
511                 ((UMOSecurityManager)digester.peek(1)).addEncryptionStrategy(name, s);
512             }
513         });
514         digester.addSetNext(path, "setSecurityManager");
515 
516     }
517 
518     protected void addTransformerRules(Digester digester, String path) throws ConfigurationException
519     {
520         // Create Transformers
521         path += "/transformers/transformer";
522         addObjectCreateOrGetFromContainer(path, TRANSFORMER_INTERFACE, "className", "ref", true);
523 
524         addSetPropertiesRule(path, digester);
525 
526         addMulePropertiesRule(path, digester);
527         digester.addSetRoot(path, "registerTransformer");
528     }
529 
530     protected void addGlobalEndpointRules(Digester digester, String path) throws ConfigurationException
531     {
532         // Create global message endpoints
533         path += "/global-endpoints";
534         addEndpointRules(digester, path, "registerEndpoint");
535     }
536 
537     protected void addEndpointIdentifierRules(Digester digester, String path) throws ConfigurationException
538     {
539         // Create and reqister endpoints
540         path += "/endpoint-identifiers/endpoint-identifier";
541         digester.addRule(path, new Rule()
542         {
543             private PlaceholderProcessor processor = new PlaceholderProcessor();
544 
545             public void begin(String s, String s1, Attributes attributes) throws Exception
546             {
547                 attributes = processor.processAttributes(attributes, s1);
548                 String name = attributes.getValue("name");
549                 String value = attributes.getValue("value");
550                 ((UMOManager)digester.getRoot()).registerEndpointIdentifier(name, value);
551             }
552         });
553     }
554 
555     protected void addTransactionManagerRules(Digester digester, String path) throws ConfigurationException
556     {
557         // Create transactionManager
558         path += "/transaction-manager";
559         addObjectCreateOrGetFromContainer(path, TRANSACTION_MANAGER_FACTORY_INTERFACE, "factory", "ref", true);
560         addMulePropertiesRule(path, digester);
561 
562         digester.addSetRoot(path, "setTransactionManager");
563         digester.addRule(path, new Rule()
564         {
565             public void end(String s, String s1) throws Exception
566             {
567                 UMOTransactionManagerFactory txFactory = (UMOTransactionManagerFactory)digester.pop();
568                 digester.push(txFactory.create());
569             }
570         });
571     }
572 
573     protected void addAgentRules(Digester digester, String path) throws ConfigurationException
574     {
575         // Create Agents
576         path += "/agents/agent";
577         addObjectCreateOrGetFromContainer(path, AGENT_INTERFACE, "className", "ref", true);
578         addSetPropertiesRule(path, digester);
579 
580         addMulePropertiesRule(path, digester);
581 
582         digester.addSetRoot(path, "registerAgent");
583     }
584 
585     protected void addConnectorRules(Digester digester, String path) throws ConfigurationException
586     {
587         // Create connectors
588         path += "/connector";
589         addObjectCreateOrGetFromContainer(path, CONNECTOR_INTERFACE, "className", "ref", true);
590 
591         addSetPropertiesRule(path, digester);
592 
593         addMulePropertiesRule(path, digester);
594 
595         digester.addRule(path + "/threading-profile", new Rule()
596         {
597             private String id;
598 
599             public void begin(String s, String s1, Attributes attributes) throws Exception
600             {
601                 // use the global tp as a template
602                 MuleConfiguration cfg = MuleManager.getConfiguration();
603                 id = attributes.getValue("id");
604                 if ("default".equals(id))
605                 {
606                     digester.push(cfg.getDefaultThreadingProfile());
607                 }
608                 else if ("receiver".equals(id))
609                 {
610                     digester.push(cfg.getMessageReceiverThreadingProfile());
611                 }
612                 else if ("dispatcher".equals(id))
613                 {
614                     digester.push(cfg.getMessageDispatcherThreadingProfile());
615                 }
616 
617             }
618 
619             public void end(String s, String s1) throws Exception
620             {
621                 ThreadingProfile tp = (ThreadingProfile)digester.pop();
622                 AbstractConnector cnn = (AbstractConnector)digester.peek();
623 
624                 if ("default".equals(id))
625                 {
626                     cnn.setReceiverThreadingProfile(tp);
627                     cnn.setDispatcherThreadingProfile(tp);
628                 }
629                 else if ("receiver".equals(id))
630                 {
631                     cnn.setReceiverThreadingProfile(tp);
632                 }
633                 else if ("dispatcher".equals(id))
634                 {
635                     cnn.setDispatcherThreadingProfile(tp);
636                 }
637             }
638         });
639 
640         SetPropertiesRule threadingRule = new SetPropertiesRule();
641         threadingRule.addAlias("poolExhaustedAction", "poolExhaustedActionString");
642         digester.addRule(path + "/threading-profile", threadingRule);
643 
644         // Connection strategy
645         digester.addObjectCreate(path + "/connection-strategy", CONNECTION_STRATEGY_INTERFACE, "className");
646         addMulePropertiesRule(path + "/connection-strategy", digester);
647         digester.addSetNext(path + "/connection-strategy", "setConnectionStrategy");
648 
649         addExceptionStrategyRules(digester, path);
650 
651         // register conntector
652         digester.addSetRoot(path, "registerConnector");
653     }
654 
655     protected void addInterceptorStackRules(Digester digester, String path) throws ConfigurationException
656     {
657         // Create Inteceptor stacks
658         path += "/interceptor-stack";
659         digester.addRule(path + "/interceptor", new ObjectCreateRule(INTERCEPTOR_INTERFACE, "className")
660         {
661             public void end(String s, String s1) throws Exception
662             {
663                 /* do not pop the result */
664             }
665         });
666 
667         digester.addRule(path, new Rule()
668         {
669             public void begin(String s, String s1, Attributes attributes) throws Exception
670             {
671                 digester.push(attributes.getValue("name"));
672             }
673 
674             public void end(String s, String s1) throws Exception
675             {
676                 List list = new ArrayList();
677                 Object obj = digester.peek();
678                 while (obj instanceof UMOInterceptor)
679                 {
680                     list.add(0, digester.pop());
681                     obj = digester.peek();
682                 }
683                 InterceptorStack stack = new InterceptorStack();
684                 stack.setInterceptors(list);
685                 manager.registerInterceptorStack(digester.pop().toString(), stack);
686             }
687         });
688 
689         addMulePropertiesRule(path + "/interceptor", digester);
690     }
691 
692     protected void addModelRules(Digester digester, String path) throws ConfigurationException
693     {
694         // Create Model
695         path += "/model";
696 
697         digester.addRule(path, new Rule()
698         {
699             public void begin(String string, String string1, Attributes attributes) throws Exception
700             {
701                 UMOModel model;
702                 String modelType = attributes.getValue("type");
703                 String modelName = attributes.getValue("name");
704                 if (modelType == null)
705                 {
706                     modelType = MuleManager.getConfiguration().getModelType();
707                 }
708                 if (modelType.equalsIgnoreCase("custom"))
709                 {
710                     String className = attributes.getValue("className");
711                     if (className == null)
712                     {
713                         throw new IllegalArgumentException(
714                             "Cannot use 'custom' model type without setting the 'className' for the model");
715                     }
716                     else
717                     {
718                         model = (UMOModel)ClassUtils.instanciateClass(className, ClassUtils.NO_ARGS,
719                             getClass());
720                     }
721                 }
722                 else if (modelType.equalsIgnoreCase("inherited"))
723                 {
724                     Map models = MuleManager.getInstance().getModels();
725                     if(models.size()==0)
726                     {
727                         throw new IllegalArgumentException("When using model inheritance there must be one model registered with Mule");
728                     }
729                     model = (UMOModel)models.get(modelName);
730                     if(model == null)
731                     {
732                         throw new IllegalArgumentException("Cannot inherit from model '" + modelName + "'. No such model registered");
733                     }
734                 }
735                 else
736                 {
737                     model = ModelFactory.createModel(modelType);
738                 }
739 
740                 digester.push(model);
741             }
742         });
743 
744         addSetPropertiesRule(path, digester);
745 
746         digester.addSetRoot(path, "registerModel");
747 
748         // Create endpointUri resolver
749         digester.addObjectCreate(path + "/entry-point-resolver", DEFAULT_ENTRY_POINT_RESOLVER, "className");
750         addSetPropertiesRule(path + "/entry-point-resolver", digester);
751 
752         digester.addSetNext(path + "/entry-point-resolver", "setEntryPointResolver");
753 
754         // Create lifecycle adapter
755         digester.addObjectCreate(path + "/component-lifecycle-adapter-factory", DEFAULT_LIFECYCLE_ADAPTER,
756             "className");
757         addSetPropertiesRule(path, digester);
758         digester.addSetNext(path + "/component-lifecycle-adapter-factory", "setLifecycleAdapterFactory");
759 
760         // Pool factory
761         addPoolingProfileRules(digester, path);
762 
763         // Exception strategy
764         addExceptionStrategyRules(digester, path);
765 
766         // Add Components
767         addMuleDescriptorRules(digester, path);
768     }
769 
770     protected void addMuleDescriptorRules(Digester digester, String path) throws ConfigurationException
771     {
772         // Create Mule UMOs
773         path += "/mule-descriptor";
774         addObjectCreateOrGetFromContainer(path, DEFAULT_DESCRIPTOR, "className", "ref", "container", false);
775 
776         addSetPropertiesRule(path, digester);
777 
778         // Create Message Routers
779         addMessageRouterRules(digester, path, "inbound");
780         addMessageRouterRules(digester, path, "outbound");
781         addMessageRouterRules(digester, path, "nested");
782         addMessageRouterRules(digester, path, "response");
783 
784         // Add threading profile rules
785         addThreadingProfileRules(digester, path, "component");
786 
787         // Add pooling profile rules
788         addPoolingProfileRules(digester, path);
789 
790         // queue profile rules
791         addQueueProfileRules(digester, path);
792 
793         // Create interceptors
794         digester.addRule(path + "/interceptor", new Rule()
795         {
796             public void begin(String string, String string1, Attributes attributes) throws Exception
797             {
798                 String value = attributes.getValue("name");
799                 if (value == null)
800                 {
801                     value = attributes.getValue("className");
802                 }
803                 UMOManager man = (UMOManager)digester.getRoot();
804                 UMOInterceptorStack interceptorStack = man.lookupInterceptorStack(value);
805                 MuleDescriptor temp = (MuleDescriptor)digester.peek();
806                 if (interceptorStack != null)
807                 {
808                     temp.addInterceptor(interceptorStack);
809                 }
810                 else
811                 {
812                     // Instantiate the new object and push it on the context
813                     // stack
814                     Class clazz = digester.getClassLoader().loadClass(value);
815                     Object instance = clazz.newInstance();
816                     temp.addInterceptor((UMOInterceptor)instance);
817                     digester.push(instance);
818                 }
819             }
820 
821             public void end(String s, String s1) throws Exception
822             {
823                 if (digester.peek() instanceof UMOInterceptor)
824                 {
825                     digester.pop();
826                 }
827             }
828         });
829 
830         addMulePropertiesRule(path + "/interceptor", digester);
831 
832         // Set exception strategy
833         addExceptionStrategyRules(digester, path);
834 
835         addMulePropertiesRule(path, digester, "setProperties");
836         digester.addSetNext(path + "/properties", "setProperties");
837 
838         // register the component
839         digester.addRule(path, new Rule()
840         {
841             public void end(String s, String s1) throws Exception
842             {
843                 UMODescriptor descriptor = (UMODescriptor)digester.peek();
844                 Object obj = digester.peek(1);
845                 final UMOModel model = (UMOModel)obj;
846                 descriptor.setModelName(model.getName());
847                 model.registerComponent(descriptor);
848             }
849         });
850     }
851 
852     protected void addThreadingProfileRules(Digester digester, String path, final String type)
853     {
854         // set threading profile
855         digester.addRule(path + "/threading-profile", new Rule()
856         {
857             public void begin(String s, String s1, Attributes attributes) throws Exception
858             {
859                 // use the default as a template
860                 MuleConfiguration cfg = MuleManager.getConfiguration();
861                 if ("component".equals(type))
862                 {
863                     digester.push(cfg.getComponentThreadingProfile());
864                 }
865                 else if ("messageReceiver".equals(type))
866                 {
867                     digester.push(cfg.getComponentThreadingProfile());
868                 }
869                 else if ("messageDispatcher".equals(type))
870                 {
871                     digester.push(cfg.getComponentThreadingProfile());
872                 }
873                 else
874                 {
875                     digester.push(cfg.getDefaultThreadingProfile());
876                 }
877             }
878 
879             public void end(String s, String s1) throws Exception
880             {
881                 digester.pop();
882             }
883         });
884         // set threading profile
885         SetPropertiesRule threadingRule = new SetPropertiesRule();
886         threadingRule.addAlias("poolExhaustedAction", "poolExhaustedActionString");
887         digester.addRule(path + "/threading-profile", threadingRule);
888         digester.addSetNext(path + "/threading-profile", "setThreadingProfile");
889     }
890 
891     protected void addPoolingProfileRules(Digester digester, String path)
892     {
893         // set pooling profile
894         digester.addRule(path + "/pooling-profile", new Rule()
895         {
896             public void begin(String s, String s1, Attributes attributes) throws Exception
897             {
898                 // use the default as a template
899                 MuleConfiguration cfg = MuleManager.getConfiguration();
900                 digester.push(cfg.getPoolingProfile());
901             }
902 
903             public void end(String s, String s1) throws Exception
904             {
905                 digester.pop();
906             }
907         });
908 
909         SetPropertiesRule rule = new SetPropertiesRule();
910         rule.addAlias("exhaustedAction", "exhaustedActionString");
911         rule.addAlias("initialisationPolicy", "initialisationPolicyString");
912         digester.addRule(path + "/pooling-profile", rule);
913         digester.addSetNext(path + "/pooling-profile", "setPoolingProfile");
914     }
915 
916     protected void addQueueProfileRules(Digester digester, String path)
917     {
918         digester.addObjectCreate(path + "/queue-profile", QUEUE_PROFILE);
919         addSetPropertiesRule(path + "/queue-profile", digester);
920         digester.addSetNext(path + "/queue-profile", "setQueueProfile");
921     }
922 
923     protected void addMessageRouterRules(Digester digester, String path, String type)
924         throws ConfigurationException
925     {
926         String defaultRouter;
927         String setMethod;
928         if ("inbound".equals(type))
929         {
930             defaultRouter = DEFAULT_INBOUND_ROUTER_COLLECTION;
931             setMethod = "setInboundRouter";
932             path += "/inbound-router";
933             // Add endpoints for multiple inbound endpoints
934             addEndpointRules(digester, path, "addEndpoint");
935             addGlobalReferenceEndpointRules(digester, path, "addEndpoint");
936         }
937         else if ("response".equals(type))
938         {
939             defaultRouter = DEFAULT_RESPONSE_ROUTER_COLLECTION;
940             setMethod = "setResponseRouter";
941             path += "/response-router";
942             // Add endpoints for multiple response endpoints i.e. replyTo
943             // addresses
944             addEndpointRules(digester, path, "addEndpoint");
945             addGlobalReferenceEndpointRules(digester, path, "addEndpoint");
946         }
947         else if ("nested".equals(type)) {
948 			defaultRouter = DEFAULT_NESTED_ROUTER_COLLECTION;
949 			setMethod = "setNestedRouter";
950 			path += "/nested-router";
951 
952     	}
953         else
954         {
955             defaultRouter = DEFAULT_OUTBOUND_ROUTER_COLLECTION;
956             setMethod = "setOutboundRouter";
957             path += "/outbound-router";
958         }
959         digester.addObjectCreate(path, defaultRouter, "className");
960         addSetPropertiesRule(path, digester);
961 
962         // Add Catch All strategy
963         digester.addObjectCreate(path + "/catch-all-strategy", DEFAULT_CATCH_ALL_STRATEGY, "className");
964         addSetPropertiesRule(path + "/catch-all-strategy", digester);
965 
966         // Add endpointUri for catch-all strategy
967         addEndpointRules(digester, path + "/catch-all-strategy", "setEndpoint");
968         addGlobalReferenceEndpointRules(digester, path + "/catch-all-strategy", "setEndpoint");
969 
970         addMulePropertiesRule(path + "/catch-all-strategy", digester);
971         digester.addSetNext(path + "/catch-all-strategy", "setCatchAllStrategy");
972 
973         // Add router rules
974         addRouterRules(digester, path, type);
975 
976         // add the router to the descriptor
977         digester.addSetNext(path, setMethod);
978     }
979 
980     protected void addRouterRules(Digester digester, String path, final String type)
981         throws ConfigurationException
982     {
983         if("nested".equals(type))
984         {
985             path += "/binding";
986             digester.addObjectCreate(path, DEFAULT_NESTED_ROUTER);
987 
988 
989         } else if ("inbound".equals(type))
990         {
991             path += "/router";
992             digester.addObjectCreate(path, INBOUND_MESSAGE_ROUTER_INTERFACE, "className");
993         }
994         else if ("response".equals(type))
995         {
996             path += "/router";
997             digester.addObjectCreate(path, RESPONSE_MESSAGE_ROUTER_INTERFACE, "className");
998         }
999         else
1000         {
1001             path += "/router";
1002             digester.addObjectCreate(path, OUTBOUND_MESSAGE_ROUTER_INTERFACE, "className");
1003         }
1004 
1005         addSetPropertiesRule(path, digester, new String[]{"enableCorrelation", "propertyExtractor"},
1006             new String[]{"enableCorrelationAsString", "propertyExtractorAsString"});
1007         addMulePropertiesRule(path, digester);
1008         if ("outbound".equals(type))
1009         {
1010             addEndpointRules(digester, path, "addEndpoint");
1011             addReplyToRules(digester, path);
1012             addGlobalReferenceEndpointRules(digester, path, "addEndpoint");
1013             addTransactionConfigRules(path, digester);
1014         }
1015         else if("nested".equals(type))
1016         {
1017             //Right now only one endpoint can be set on a nested Router so call
1018             //setEndpoint not addEndpoint
1019             addEndpointRules(digester, path, "setEndpoint");
1020 			addGlobalReferenceEndpointRules(digester, path, "setEndpoint");
1021         }
1022         addFilterRules(digester, path);
1023 
1024         // Set the router on the to the message router
1025         digester.addSetNext(path, "addRouter");
1026     }
1027 
1028     protected void addReplyToRules(Digester digester, String path) throws ConfigurationException
1029     {
1030         // Set message endpoint
1031         path += "/reply-to";
1032         digester.addRule(path, new Rule()
1033         {
1034             public void begin(String s, String s1, Attributes attributes) throws Exception
1035             {
1036                 String replyTo = attributes.getValue("address");
1037                 ((UMOOutboundRouter)digester.peek()).setReplyTo(replyTo);
1038             }
1039         });
1040     }
1041 
1042     protected void addEndpointRules(Digester digester, String path, String method)
1043         throws ConfigurationException
1044     {
1045         // Set message endpoint
1046         path += "/endpoint";
1047         addObjectCreateOrGetFromContainer(path, DEFAULT_ENDPOINT, "className", "ref", false);
1048         addCommonEndpointRules(digester, path, method);
1049     }
1050 
1051     protected void addGlobalReferenceEndpointRules(Digester digester, String path, final String method)
1052         throws ConfigurationException
1053     {
1054         // Set message endpoint
1055         path += "/global-endpoint";
1056         digester.addRule(path, new Rule()
1057         {
1058             public void begin(String s, String s1, Attributes attributes) throws Exception
1059             {
1060                 String name = attributes.getValue("name");
1061                 String address = attributes.getValue("address");
1062                 String trans = attributes.getValue("transformers");
1063                 String responseTrans = attributes.getValue("responseTransformers");
1064                 String createConnector = attributes.getValue("createConnector");
1065                 EndpointReference ref = new EndpointReference(method, name, address, trans, responseTrans,
1066                     createConnector, digester.peek());
1067                 // TODO encoding
1068                 // String encoding = attributes.getValue("encoding");
1069                 digester.push(ref);
1070             }
1071 
1072             public void end(String endpointName, String endpointName1) throws Exception
1073             {
1074                 endpointReferences.add(digester.pop());
1075             }
1076         });
1077         addCommonEndpointRules(digester, path, null);
1078     }
1079 
1080     protected void addCommonEndpointRules(Digester digester, String path, String method)
1081         throws ConfigurationException
1082     {
1083         addSetPropertiesRule(path, digester, new String[]{"address", "transformers", "responseTransformers",
1084             "createConnector"}, new String[]{"endpointURI", "transformer", "responseTransformer",
1085             "createConnectorAsString"});
1086         // todo test
1087         addMulePropertiesRule(path, digester, "setProperties");
1088         addTransactionConfigRules(path, digester);
1089 
1090         addFilterRules(digester, path);
1091         if (method != null)
1092         {
1093             digester.addSetNext(path, method);
1094         }
1095 
1096         // Add security filter rules
1097         digester.addObjectCreate(path + "/security-filter", ENDPOINT_SECURITY_FILTER_INTERFACE, "className");
1098 
1099         addMulePropertiesRule(path + "/security-filter", digester);
1100         digester.addSetNext(path + "/security-filter", "setSecurityFilter");
1101     }
1102 
1103     protected void addTransactionConfigRules(String path, Digester digester)
1104     {
1105         digester.addObjectCreate(path + "/transaction", DEFAULT_TRANSACTION_CONFIG);
1106         addSetPropertiesRule(path + "/transaction", digester, new String[]{"action"},
1107             new String[]{"actionAsString"});
1108 
1109         digester.addObjectCreate(path + "/transaction/factory", TRANSACTION_FACTORY_INTERFACE, "className");
1110         addMulePropertiesRule(path + "/transaction/factory", digester);
1111         digester.addSetNext(path + "/transaction/factory", "setFactory");
1112 
1113         digester.addObjectCreate(path + "/transaction/constraint", TRANSACTION_CONSTRAINT_INTERFACE, "className");
1114         addSetPropertiesRule(path + "/transaction/constraint", digester);
1115 
1116         digester.addSetNext(path + "/transaction/constraint", "setConstraint");
1117         digester.addSetNext(path + "/transaction", "setTransactionConfig");
1118     }
1119 
1120     protected void addExceptionStrategyRules(Digester digester, String path) throws ConfigurationException
1121     {
1122         path += "/exception-strategy";
1123         digester.addObjectCreate(path, EXCEPTION_STRATEGY_INTERFACE, "className");
1124         addMulePropertiesRule(path, digester);
1125 
1126         // Add endpoint rules
1127         addEndpointRules(digester, path, "addEndpoint");
1128         addGlobalReferenceEndpointRules(digester, path, "addEndpoint");
1129         digester.addSetNext(path, "setExceptionListener");
1130     }
1131 
1132     protected void addSetPropertiesRule(String path, Digester digester, String[] s1, String[] s2)
1133     {
1134         digester.addRule(path, new ExtendedMuleSetPropertiesRule(s1, s2));
1135     }
1136 
1137     protected void addSetPropertiesRule(String path, Digester digester)
1138     {
1139         digester.addRule(path, new ExtendedMuleSetPropertiesRule());
1140     }
1141 
1142     private void addTransformerReference(String propName, String transName, Object object)
1143     {
1144         transformerReferences.add(new TransformerReference(propName, transName, object));
1145     }
1146 
1147     private void addEndpointReference(String propName, String endpointName, Object object)
1148     {
1149         endpointReferences.add(new EndpointReference(propName, endpointName, null, null, null, null, object));
1150     }
1151 
1152     /**
1153      * this rule serves 2 functions - 1. Allows for late binding of certain types of
1154      * object, namely Transformers and endpoints that need to be set on objects once
1155      * the Manager configuration has been processed 2. Allows for template parameters
1156      * to be parse on the configuration file in the form of ${param-name}. These will
1157      * get resolved against properties set in the mule-properites element
1158      */
1159     public class ExtendedMuleSetPropertiesRule extends MuleSetPropertiesRule
1160     {
1161         public ExtendedMuleSetPropertiesRule()
1162         {
1163             super();
1164         }
1165 
1166         public ExtendedMuleSetPropertiesRule(PlaceholderProcessor processor)
1167         {
1168             super(processor);
1169         }
1170 
1171         public ExtendedMuleSetPropertiesRule(String[] strings, String[] strings1)
1172         {
1173             super(strings, strings1);
1174         }
1175 
1176         public ExtendedMuleSetPropertiesRule(String[] strings,
1177                                              String[] strings1,
1178                                              PlaceholderProcessor processor)
1179         {
1180             super(strings, strings1, processor);
1181         }
1182 
1183         public void begin(String s1, String s2, Attributes attributes) throws Exception
1184         {
1185             attributes = processor.processAttributes(attributes, s2);
1186             // Add transformer references that will be bound to their objects
1187             // once all configuration has bean read
1188             String transformerNames = attributes.getValue("transformer");
1189             if (transformerNames != null)
1190             {
1191                 addTransformerReference("transformer", transformerNames, digester.peek());
1192             }
1193             transformerNames = attributes.getValue("transformers");
1194             if (transformerNames != null)
1195             {
1196                 addTransformerReference("transformer", transformerNames, digester.peek());
1197             }
1198 
1199             transformerNames = attributes.getValue("responseTransformers");
1200             if (transformerNames != null)
1201             {
1202                 addTransformerReference("responseTransformer", transformerNames, digester.peek());
1203             }
1204 
1205             // transformerNames = attributes.getValue("responseTransformer");
1206             // if (transformerNames != null) {
1207             // addTransformerReference("responseTransformer", transformerNames,
1208             // digester.peek());
1209             // }
1210 
1211             transformerNames = attributes.getValue("inboundTransformer");
1212             if (transformerNames != null)
1213             {
1214                 addTransformerReference("inboundTransformer", transformerNames, digester.peek());
1215             }
1216 
1217             transformerNames = attributes.getValue("outboundTransformer");
1218             if (transformerNames != null)
1219             {
1220                 addTransformerReference("outboundTransformer", transformerNames, digester.peek());
1221             }
1222 
1223             transformerNames = attributes.getValue("responseTransformer");
1224             if (transformerNames != null)
1225             {
1226                 addTransformerReference("responseTransformer", transformerNames, digester.peek());
1227             }
1228 
1229             // Special case handling of global endpoint refs on the
1230             // inboundEndpoint/
1231             // outboundendpoint attributes of the descriptor
1232             String endpoint = attributes.getValue("inboundEndpoint");
1233             if (endpoint != null)
1234             {
1235                 Object o = manager.getEndpoints().get(endpoint);
1236                 if (o != null)
1237                 {
1238                     addEndpointReference("setInboundEndpoint", endpoint, digester.peek());
1239                 }
1240             }
1241 
1242             endpoint = attributes.getValue("outboundEndpoint");
1243             if (endpoint != null)
1244             {
1245                 Object o = manager.getEndpoints().get(endpoint);
1246                 if (o != null)
1247                 {
1248                     addEndpointReference("setOutboundEndpoint", endpoint, digester.peek());
1249                 }
1250             }
1251             super.begin(attributes);
1252         }
1253     }
1254 
1255     protected void addObjectCreateOrGetFromContainer(final String path,
1256                                                      String defaultImpl,
1257                                                      final String classAttrib,
1258                                                      final String refAttrib,
1259                                                      final boolean classRefRequired)
1260     {
1261         digester.addRule(path, new ObjectGetOrCreateRule(defaultImpl, classAttrib, refAttrib, classAttrib,
1262             classRefRequired, "getContainerContext"));
1263     }
1264 
1265     protected void addObjectCreateOrGetFromContainer(final String path,
1266                                                      String defaultImpl,
1267                                                      final String classAttrib,
1268                                                      final String refAttrib,
1269                                                      final String containerAttrib,
1270                                                      final boolean classRefRequired)
1271     {
1272         digester.addRule(path, new ObjectGetOrCreateRule(defaultImpl, classAttrib, refAttrib,
1273             containerAttrib, classAttrib, classRefRequired, "getContainerContext"));
1274     }
1275 }