View Javadoc

1   /*
2    * $Id: DefaultTransportServiceDescriptor.java 19195 2010-08-25 21:41:35Z aperepel $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.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.transport.service;
12  
13  import org.mule.MessageExchangePattern;
14  import org.mule.api.MuleContext;
15  import org.mule.api.MuleException;
16  import org.mule.api.config.MuleProperties;
17  import org.mule.api.construct.FlowConstruct;
18  import org.mule.api.endpoint.EndpointBuilder;
19  import org.mule.api.endpoint.EndpointException;
20  import org.mule.api.endpoint.EndpointURIBuilder;
21  import org.mule.api.endpoint.ImmutableEndpoint;
22  import org.mule.api.endpoint.InboundEndpoint;
23  import org.mule.api.registry.AbstractServiceDescriptor;
24  import org.mule.api.transaction.TransactionFactory;
25  import org.mule.api.transformer.Transformer;
26  import org.mule.api.transport.Connector;
27  import org.mule.api.transport.MessageDispatcherFactory;
28  import org.mule.api.transport.MessageReceiver;
29  import org.mule.api.transport.MessageRequesterFactory;
30  import org.mule.api.transport.MuleMessageFactory;
31  import org.mule.api.transport.SessionHandler;
32  import org.mule.config.i18n.CoreMessages;
33  import org.mule.endpoint.EndpointURIEndpointBuilder;
34  import org.mule.endpoint.UrlEndpointURIBuilder;
35  import org.mule.session.SerializeAndEncodeSessionHandler;
36  import org.mule.transaction.XaTransactionFactory;
37  import org.mule.util.ClassUtils;
38  import org.mule.util.CollectionUtils;
39  import org.mule.util.StringUtils;
40  
41  import java.util.ArrayList;
42  import java.util.Collections;
43  import java.util.List;
44  import java.util.Properties;
45  
46  /** @inheritDocs */
47  public class DefaultTransportServiceDescriptor extends AbstractServiceDescriptor implements TransportServiceDescriptor
48  {
49      private String connector;
50      private String dispatcherFactory;
51      private String requesterFactory;
52      private String transactionFactory;
53      private String messageFactory;
54      private String messageReceiver;
55      private String transactedMessageReceiver;
56      private String xaTransactedMessageReceiver;
57      private String endpointUriBuilder;
58      private String sessionHandler;
59      private String defaultInboundTransformer;
60      private String defaultOutboundTransformer;
61      private String defaultResponseTransformer;
62      private String endpointBuilder;
63  
64      private Properties exceptionMappings = new Properties();
65      private MuleContext muleContext;
66      private List<MessageExchangePattern> inboundExchangePatterns;
67      private List<MessageExchangePattern> outboundExchangePatterns;
68      private String defaultExchangePattern;
69  
70      private ClassLoader classLoader;
71  
72      public DefaultTransportServiceDescriptor(String service, Properties props, ClassLoader classLoader)
73      {
74          super(service);
75          this.classLoader = classLoader;
76          init(props);
77      }
78  
79      protected void init(Properties props)
80      {
81          connector = removeProperty(MuleProperties.CONNECTOR_CLASS, props);
82          dispatcherFactory = removeProperty(MuleProperties.CONNECTOR_DISPATCHER_FACTORY, props);
83          requesterFactory = removeProperty(MuleProperties.CONNECTOR_REQUESTER_FACTORY, props);
84          transactionFactory = removeProperty(MuleProperties.CONNECTOR_DISPATCHER_FACTORY, props);
85          messageReceiver = removeProperty(MuleProperties.CONNECTOR_MESSAGE_RECEIVER_CLASS, props);
86          transactedMessageReceiver = removeProperty(MuleProperties.CONNECTOR_TRANSACTED_MESSAGE_RECEIVER_CLASS, props);
87          xaTransactedMessageReceiver = removeProperty(MuleProperties.CONNECTOR_XA_TRANSACTED_MESSAGE_RECEIVER_CLASS, props);
88          messageFactory = removeProperty(MuleProperties.CONNECTOR_MESSAGE_FACTORY, props);
89          defaultInboundTransformer = removeProperty(MuleProperties.CONNECTOR_INBOUND_TRANSFORMER, props);
90          defaultOutboundTransformer = removeProperty(MuleProperties.CONNECTOR_OUTBOUND_TRANSFORMER, props);
91          defaultResponseTransformer = removeProperty(MuleProperties.CONNECTOR_RESPONSE_TRANSFORMER, props);
92          endpointBuilder = removeProperty(MuleProperties.CONNECTOR_META_ENDPOINT_BUILDER, props);
93          endpointUriBuilder = removeProperty(MuleProperties.CONNECTOR_ENDPOINT_BUILDER, props);
94          sessionHandler = removeProperty(MuleProperties.CONNECTOR_SESSION_HANDLER, props);
95          
96          initInboundExchangePatterns(props);        
97          initOutboundExchangePatterns(props);
98          defaultExchangePattern = removeProperty(MuleProperties.CONNECTOR_DEFAULT_EXCHANGE_PATTERN, props);
99      }
100 
101     public void setOverrides(Properties props)
102     {
103         if (props == null || props.size() == 0)
104         {
105             return;
106         }
107 
108         connector = props.getProperty(MuleProperties.CONNECTOR_CLASS, connector);
109         dispatcherFactory = props.getProperty(MuleProperties.CONNECTOR_DISPATCHER_FACTORY, dispatcherFactory);
110         requesterFactory = props.getProperty(MuleProperties.CONNECTOR_REQUESTER_FACTORY, requesterFactory);
111         messageReceiver = props.getProperty(MuleProperties.CONNECTOR_MESSAGE_RECEIVER_CLASS, messageReceiver);
112         transactedMessageReceiver = props.getProperty(
113                 MuleProperties.CONNECTOR_TRANSACTED_MESSAGE_RECEIVER_CLASS, transactedMessageReceiver);
114         xaTransactedMessageReceiver = props.getProperty(
115                 MuleProperties.CONNECTOR_XA_TRANSACTED_MESSAGE_RECEIVER_CLASS, xaTransactedMessageReceiver);
116         messageFactory = props.getProperty(MuleProperties.CONNECTOR_MESSAGE_FACTORY, messageFactory);
117         endpointBuilder = props.getProperty(MuleProperties.CONNECTOR_META_ENDPOINT_BUILDER, endpointBuilder);
118 
119         String temp = props.getProperty(MuleProperties.CONNECTOR_INBOUND_TRANSFORMER);
120         if (temp != null)
121         {
122             defaultInboundTransformer = temp;
123         }
124 
125         temp = props.getProperty(MuleProperties.CONNECTOR_OUTBOUND_TRANSFORMER);
126         if (temp != null)
127         {
128             defaultOutboundTransformer = temp;
129         }
130 
131         temp = props.getProperty(MuleProperties.CONNECTOR_RESPONSE_TRANSFORMER);
132         if (temp != null)
133         {
134             defaultResponseTransformer = temp;
135         }
136 
137         temp = props.getProperty(MuleProperties.CONNECTOR_ENDPOINT_BUILDER);
138         if (temp != null)
139         {
140             endpointUriBuilder = temp;
141         }
142         
143         initInboundExchangePatterns(props);
144         initOutboundExchangePatterns(props);
145         defaultExchangePattern = props.getProperty(MuleProperties.CONNECTOR_DEFAULT_EXCHANGE_PATTERN, null);
146     }
147 
148     public void setMuleContext(MuleContext context)
149     {
150         this.muleContext = context;
151     }
152 
153     public MuleMessageFactory createMuleMessageFactory() throws TransportServiceException
154     {
155         if (messageFactory == null)
156         {
157             throw new TransportServiceException(CoreMessages.objectNotSetInService("Message Factory",
158                 getService()));
159         }
160 
161         try
162         {
163             return (MuleMessageFactory) ClassUtils.instanciateClass(messageFactory, muleContext);
164         }
165         catch (Exception e)
166         {
167             throw new TransportServiceException(CoreMessages.failedToCreate("Message Factory"));
168         }
169     }
170 
171     public SessionHandler createSessionHandler() throws TransportServiceException
172     {
173         if (sessionHandler == null)
174         {
175             sessionHandler = SerializeAndEncodeSessionHandler.class.getName();
176             if (logger.isDebugEnabled())
177             {
178                 logger.debug("No session.handler set in service description, defaulting to: "
179                         + sessionHandler);
180             }
181         }
182         try
183         {
184             return (SessionHandler) ClassUtils.instanciateClass(sessionHandler, ClassUtils.NO_ARGS, classLoader);
185         }
186         catch (Throwable e)
187         {
188             throw new TransportServiceException(CoreMessages.failedToCreateObjectWith("SessionHandler", sessionHandler), e);
189         }
190     }
191 
192     public MessageReceiver createMessageReceiver(Connector connector,
193                                                  FlowConstruct flowConstruct,
194                                                  InboundEndpoint endpoint) throws MuleException
195     {
196 
197         MessageReceiver mr = createMessageReceiver(connector, flowConstruct, endpoint, null);
198         return mr;
199     }
200 
201     public MessageReceiver createMessageReceiver(Connector connector,
202                                                  FlowConstruct flowConstruct,
203                                                  InboundEndpoint endpoint,
204                                                  Object... args) throws MuleException
205     {
206         String receiverClass = messageReceiver;
207 
208         if (endpoint.getTransactionConfig().isTransacted())
209         {
210             boolean xaTx = endpoint.getTransactionConfig().getFactory() instanceof XaTransactionFactory;
211             if (transactedMessageReceiver != null && !xaTx)
212             {
213                 receiverClass = transactedMessageReceiver;
214             }
215             else if (xaTransactedMessageReceiver != null && xaTx)
216             {
217                 receiverClass = xaTransactedMessageReceiver;
218             }
219 
220         }
221 
222         if (receiverClass != null)
223         {
224             Object[] newArgs;
225 
226             if (args != null && args.length != 0)
227             {
228                 newArgs = new Object[3 + args.length];
229             }
230             else
231             {
232                 newArgs = new Object[3];
233             }
234 
235             newArgs[0] = connector;
236             newArgs[1] = flowConstruct;
237             newArgs[2] = endpoint;
238 
239             if (args != null && args.length != 0)
240             {
241                 System.arraycopy(args, 0, newArgs, 3, newArgs.length - 3);
242             }
243 
244             try
245             {
246                 MessageReceiver mr = (MessageReceiver) ClassUtils.instanciateClass(receiverClass, newArgs, classLoader);
247                 return mr;
248             }
249             catch (Exception e)
250             {
251                 throw new TransportServiceException(CoreMessages.failedToCreateObjectWith("Message Receiver", getService()), e);
252             }
253 
254         }
255         else
256         {
257             throw new TransportServiceException(CoreMessages.objectNotSetInService("Message Receiver", getService()));
258         }
259     }
260 
261     public MessageDispatcherFactory createDispatcherFactory() throws TransportServiceException
262     {
263         if (dispatcherFactory != null)
264         {
265             try
266             {
267                 return (MessageDispatcherFactory) ClassUtils.instanciateClass(dispatcherFactory,
268                         ClassUtils.NO_ARGS, classLoader);
269             }
270             catch (Exception e)
271             {
272                 throw new TransportServiceException(CoreMessages.failedToCreateObjectWith("Message Dispatcher Factory", dispatcherFactory), e);
273             }
274         }
275         else
276         {
277             //Its valid not to have a Dispatcher factory on the transport
278             return null;
279         }
280     }
281 
282     public MessageRequesterFactory createRequesterFactory() throws TransportServiceException
283     {
284         if (requesterFactory != null)
285         {
286             try
287             {
288                 return (MessageRequesterFactory) ClassUtils.instanciateClass(requesterFactory,
289                         ClassUtils.NO_ARGS, classLoader);
290             }
291             catch (Exception e)
292             {
293                 throw new TransportServiceException(
294                         CoreMessages.failedToCreateObjectWith("Message Requester Factory", requesterFactory), e);
295             }
296         }
297         else
298         {
299             //Its valid not to have a Requester factory on the transport
300             return null;
301         }
302     }
303 
304     public TransactionFactory createTransactionFactory() throws TransportServiceException
305     {
306         if (transactionFactory != null)
307         {
308             try
309             {
310                 return (TransactionFactory) ClassUtils.instanciateClass(transactionFactory,
311                         ClassUtils.NO_ARGS, classLoader);
312             }
313             catch (Exception e)
314             {
315                 throw new TransportServiceException(CoreMessages.failedToCreateObjectWith("Transaction Factory", transactionFactory), e);
316             }
317         }
318         else
319         {
320             return null;
321         }
322     }
323 
324     @SuppressWarnings("unchecked")
325     public Connector createConnector() throws TransportServiceException
326     {
327         Connector newConnector;
328         // if there is a factory, use it
329         try
330         {
331             if (connector != null)
332             {
333                 Class<Connector> connectorClass;
334                 if (classLoader != null)
335                 {
336                     connectorClass = ClassUtils.loadClass(connector, classLoader);
337                 }
338                 else
339                 {
340                     connectorClass = ClassUtils.loadClass(connector, getClass());
341                 }
342                 newConnector = connectorClass.getConstructor(MuleContext.class).newInstance(muleContext);
343             }
344             else
345             {
346                 throw new TransportServiceException(CoreMessages.objectNotSetInService("Connector", getService()));
347             }
348         }
349         catch (TransportServiceException e)
350         {
351             throw e;
352         }
353         catch (Exception e)
354         {
355             throw new TransportServiceException(CoreMessages.failedToCreateObjectWith("Connector", connector), e);
356         }
357 
358         if (newConnector.getName() == null)
359         {
360             newConnector.setName("_" + newConnector.getProtocol() + "Connector#" + connector.hashCode());
361         }
362         return newConnector;
363     }
364 
365     @SuppressWarnings("unchecked")
366     public List<Transformer> createInboundTransformers(ImmutableEndpoint endpoint) throws TransportFactoryException
367     {
368         if (defaultInboundTransformer != null)
369         {
370             logger.info("Loading default inbound transformer: " + defaultInboundTransformer);
371             try
372             {
373                 Transformer newTransformer = createTransformer(defaultInboundTransformer, endpoint);
374                 return CollectionUtils.singletonList(newTransformer);
375             }
376             catch (Exception e)
377             {
378                 throw new TransportFactoryException(CoreMessages.failedToLoadTransformer("inbound",
379                     defaultInboundTransformer), e);
380             }
381         }
382         return Collections.emptyList();
383     }
384     
385     @SuppressWarnings("unchecked")
386     public List<Transformer> createOutboundTransformers(ImmutableEndpoint endpoint) throws TransportFactoryException
387     {
388         if (defaultOutboundTransformer != null)
389         {
390             logger.info("Loading default outbound transformer: " + defaultOutboundTransformer);
391             try
392             {
393                 Transformer newTransformer = createTransformer(defaultOutboundTransformer, endpoint);
394                 return CollectionUtils.singletonList(newTransformer);
395             }
396             catch (Exception e)
397             {
398                 throw new TransportFactoryException(CoreMessages.failedToLoadTransformer("outbound",
399                     defaultOutboundTransformer), e);
400             }
401         }
402         return Collections.emptyList();
403     }
404 
405     @SuppressWarnings("unchecked")
406     public List<Transformer> createResponseTransformers(ImmutableEndpoint endpoint) throws TransportFactoryException
407     {
408         if (defaultResponseTransformer != null)
409         {
410             logger.info("Loading default response transformer: " + defaultResponseTransformer);
411             try
412             {
413                 Transformer newTransformer = createTransformer(defaultResponseTransformer, endpoint);
414                 return CollectionUtils.singletonList(newTransformer);
415             }
416             catch (Exception e)
417             {
418                 throw new TransportFactoryException(CoreMessages.failedToLoadTransformer("response",
419                     defaultResponseTransformer), e);
420             }
421         }
422         return Collections.emptyList();
423     }
424 
425     protected Transformer createTransformer(String className, ImmutableEndpoint endpoint) throws Exception
426     {
427         Transformer newTransformer = (Transformer) ClassUtils.instanciateClass(className, 
428             ClassUtils.NO_ARGS, classLoader);
429         newTransformer.setMuleContext(muleContext);
430         newTransformer.setName(newTransformer.getName() + "#" + newTransformer.hashCode());
431         newTransformer.setEndpoint(endpoint);
432         return newTransformer;
433     }
434 
435     public EndpointURIBuilder createEndpointURIBuilder() throws TransportFactoryException
436     {
437         if (endpointUriBuilder == null)
438         {
439             logger.debug("Endpoint resolver not set, Loading default resolver: "
440                     + UrlEndpointURIBuilder.class.getName());
441             return new UrlEndpointURIBuilder();
442         }
443         else
444         {
445             logger.debug("Loading endpointUri resolver: " + endpointUriBuilder);
446             try
447             {
448                 return (EndpointURIBuilder) ClassUtils.instanciateClass(endpointUriBuilder, ClassUtils.NO_ARGS, classLoader);
449             }
450             catch (Exception e)
451             {
452                 throw new TransportFactoryException(CoreMessages.failedToLoad("EndpointURI Builder: " + endpointUriBuilder), e);
453             }
454         }
455     }
456 
457     public EndpointBuilder createEndpointBuilder(String uri) throws TransportFactoryException
458     {
459         if (endpointBuilder == null)
460         {
461             logger.debug("Endpoint builder not set, Loading default builder: "
462                     + EndpointURIEndpointBuilder.class.getName());
463             return new EndpointURIEndpointBuilder(uri, muleContext);
464         }
465         else
466         {
467             return createEndpointBuilder(new Object[] { uri, muleContext });
468         }
469     }
470 
471     public EndpointBuilder createEndpointBuilder(EndpointURIEndpointBuilder builder) throws TransportFactoryException
472     {
473         EndpointBuilder wrappingBuilder;
474         if (endpointBuilder == null)
475         {
476             logger.debug("Endpoint builder not set, Loading default builder: "
477                     + EndpointURIEndpointBuilder.class.getName());
478             try
479             {
480                 wrappingBuilder = new EndpointURIEndpointBuilder(builder);
481             }
482             catch (EndpointException e)
483             {
484                 throw new TransportFactoryException(CoreMessages.failedToLoad("Endpoint Builder: " + endpointBuilder), e);
485             }
486         }
487         else
488         {
489             wrappingBuilder = createEndpointBuilder(new Object[] { builder });
490         }
491 
492         wrappingBuilder.setMuleContext(muleContext);
493         return wrappingBuilder;
494     }
495     
496     protected EndpointBuilder createEndpointBuilder(Object[] constructorParams) throws TransportFactoryException
497     {
498         logger.debug("Loading endpoint builder: " + endpointBuilder);
499         try
500         {
501             return (EndpointBuilder) ClassUtils.instanciateClass(endpointBuilder, constructorParams, classLoader);
502         }
503         catch (Exception e)
504         {
505             throw new TransportFactoryException(CoreMessages.failedToLoad("Endpoint Builder: " + endpointBuilder), e);
506         }
507     }
508     
509     public void setExceptionMappings(Properties props)
510     {
511         this.exceptionMappings = props;
512     }
513 
514     public Properties getExceptionMappings()
515     {
516         return this.exceptionMappings;
517     }
518 
519     protected void initInboundExchangePatterns(Properties properties)
520     {
521         // it's valid to configure no inbound exchange patterns but it's invalid to have
522         // no key for inbound exchange patterns
523         if (!properties.keySet().contains(MuleProperties.CONNECTOR_INBOUND_EXCHANGE_PATTERNS))
524         {
525             inboundExchangePatterns = null;
526         }
527         else
528         {
529             String mepsString = 
530                 removeProperty(MuleProperties.CONNECTOR_INBOUND_EXCHANGE_PATTERNS, properties);
531             inboundExchangePatterns = parseExchangePatterns(mepsString);
532         }
533     }
534 
535     protected void initOutboundExchangePatterns(Properties properties)
536     {
537         // it's valid to configure no outbound exchange patterns but it's invalid to have
538         // no key for outbound exchange patterns
539         if (!properties.keySet().contains(MuleProperties.CONNECTOR_OUTBOUND_EXCHANGE_PATTERNS))
540         {
541             outboundExchangePatterns = null;
542         }
543         else
544         {
545             String mepsString = 
546                 removeProperty(MuleProperties.CONNECTOR_OUTBOUND_EXCHANGE_PATTERNS, properties);
547             outboundExchangePatterns = parseExchangePatterns(mepsString);
548         }
549     }
550 
551     protected List<MessageExchangePattern> parseExchangePatterns(String mepsString)
552     {
553         if (StringUtils.isEmpty(mepsString))
554         {
555             return Collections.emptyList();
556         }
557         
558         List<MessageExchangePattern> mepList = new ArrayList<MessageExchangePattern>();
559         
560         String[] meps = StringUtils.splitAndTrim(mepsString, ",");
561         for (String exchangePattern : meps)
562         {
563             mepList.add(MessageExchangePattern.fromString(exchangePattern));
564         }
565         
566         return mepList;
567     }
568     
569     public List<MessageExchangePattern> getInboundExchangePatterns() throws TransportServiceException
570     {
571         if (inboundExchangePatterns == null)
572         {
573             throw new TransportServiceException(CoreMessages.objectNotSetInService(
574                 MuleProperties.CONNECTOR_INBOUND_EXCHANGE_PATTERNS, getService()));
575         }
576         return inboundExchangePatterns;
577     }
578 
579     public List<MessageExchangePattern> getOutboundExchangePatterns() throws TransportServiceException
580     {
581         if (outboundExchangePatterns == null)
582         {
583             throw new TransportServiceException(CoreMessages.objectNotSetInService(
584                 MuleProperties.CONNECTOR_OUTBOUND_EXCHANGE_PATTERNS, getService()));
585         }
586         return outboundExchangePatterns;
587     }
588 
589     public MessageExchangePattern getDefaultExchangePattern() throws TransportServiceException
590     {
591         if (defaultExchangePattern == null)
592         {
593             throw new TransportServiceException(CoreMessages.objectNotSetInService(
594                 MuleProperties.CONNECTOR_DEFAULT_EXCHANGE_PATTERN, getService()));
595         }
596         
597         return MessageExchangePattern.fromString(defaultExchangePattern);
598     }
599 }