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