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.endpoint;
8   
9   import org.mule.MessageExchangePattern;
10  import org.mule.api.DefaultMuleException;
11  import org.mule.api.MuleContext;
12  import org.mule.api.MuleRuntimeException;
13  import org.mule.api.config.MuleProperties;
14  import org.mule.api.endpoint.EndpointBuilder;
15  import org.mule.api.endpoint.EndpointException;
16  import org.mule.api.endpoint.EndpointMessageProcessorChainFactory;
17  import org.mule.api.endpoint.EndpointURI;
18  import org.mule.api.endpoint.ImmutableEndpoint;
19  import org.mule.api.endpoint.InboundEndpoint;
20  import org.mule.api.endpoint.MalformedEndpointException;
21  import org.mule.api.endpoint.OutboundEndpoint;
22  import org.mule.api.lifecycle.InitialisationException;
23  import org.mule.api.processor.MessageProcessor;
24  import org.mule.api.registry.ServiceException;
25  import org.mule.api.registry.ServiceType;
26  import org.mule.api.retry.RetryPolicyTemplate;
27  import org.mule.api.security.EndpointSecurityFilter;
28  import org.mule.api.security.SecurityFilter;
29  import org.mule.api.transaction.TransactionConfig;
30  import org.mule.api.transformer.Transformer;
31  import org.mule.api.transport.Connector;
32  import org.mule.config.i18n.CoreMessages;
33  import org.mule.config.i18n.Message;
34  import org.mule.processor.SecurityFilterMessageProcessor;
35  import org.mule.routing.MessageFilter;
36  import org.mule.routing.requestreply.ReplyToParameterProcessor;
37  import org.mule.transaction.MuleTransactionConfig;
38  import org.mule.transformer.TransformerUtils;
39  import org.mule.transport.AbstractConnector;
40  import org.mule.transport.service.TransportFactory;
41  import org.mule.transport.service.TransportFactoryException;
42  import org.mule.transport.service.TransportServiceDescriptor;
43  import org.mule.transport.service.TransportServiceException;
44  import org.mule.util.ClassUtils;
45  import org.mule.util.CollectionUtils;
46  import org.mule.util.MapCombiner;
47  import org.mule.util.ObjectNameHelper;
48  import org.mule.util.StringUtils;
49  
50  import java.util.Collections;
51  import java.util.HashMap;
52  import java.util.LinkedList;
53  import java.util.List;
54  import java.util.Map;
55  import java.util.Properties;
56  
57  import javax.activation.MimeType;
58  import javax.activation.MimeTypeParseException;
59  
60  import org.apache.commons.logging.Log;
61  import org.apache.commons.logging.LogFactory;
62  
63  /**
64   * Abstract endpoint builder used for externalizing the complex creation logic of
65   * endpoints out of the endpoint instance itself. <br/>
66   * The use of a builder allows i) Endpoints to be configured once and created in a
67   * repeatable fashion (global endpoints), ii) Allow for much more extensibility in
68   * endpoint creation for transport specific endpoints, streaming endpoints etc.<br/>
69   */
70  public abstract class AbstractEndpointBuilder implements EndpointBuilder
71  {
72  
73      public static final String PROPERTY_RESPONSE_TIMEOUT = "responseTimeout";
74      public static final String PROPERTY_RESPONSE_PROPERTIES = "responseProperties";
75  
76      protected URIBuilder uriBuilder;
77      protected Connector connector;
78      protected String name;
79      protected Map<Object, Object> properties = new HashMap<Object, Object>();
80      protected TransactionConfig transactionConfig;
81      protected Boolean deleteUnacceptedMessages;
82      protected Boolean synchronous;
83      protected MessageExchangePattern messageExchangePattern;
84      protected Integer responseTimeout;
85      protected String initialState = ImmutableEndpoint.INITIAL_STATE_STARTED;
86      protected String encoding;
87      protected Integer createConnector;
88      protected RetryPolicyTemplate retryPolicyTemplate;
89      protected String responsePropertiesList;
90      protected EndpointMessageProcessorChainFactory messageProcessorsFactory;
91      protected List<MessageProcessor> messageProcessors = new LinkedList<MessageProcessor>();
92      protected List<MessageProcessor> responseMessageProcessors = new LinkedList<MessageProcessor>();
93      protected List<Transformer> transformers = new LinkedList<Transformer>();
94      protected List<Transformer> responseTransformers = new LinkedList<Transformer>();
95      protected Boolean disableTransportTransformer;
96      protected String mimeType;
97  
98      // not included in equality/hash
99      protected String registryId = null;
100     protected MuleContext muleContext;
101 
102     protected transient Log logger = LogFactory.getLog(getClass());
103 
104     public InboundEndpoint buildInboundEndpoint() throws EndpointException, InitialisationException
105     {
106         return doBuildInboundEndpoint();
107     }
108 
109     public OutboundEndpoint buildOutboundEndpoint() throws EndpointException, InitialisationException
110     {
111         return doBuildOutboundEndpoint();
112     }
113 
114     protected void setPropertiesFromProperties(Map<Object, Object> properties)
115     {
116         final Boolean tempSync = getBooleanProperty(properties, MuleProperties.SYNCHRONOUS_PROPERTY,
117             synchronous);
118         if (tempSync != null)
119         {
120             if (uriBuilder != null)
121             {
122                 logger.warn(String.format(
123                     "Deprecated 'synchronous' flag found on endpoint '%s', please replace with "
124                                     + "e.g. 'exchangePattern=request-response", uriBuilder.getEndpoint()));
125             }
126             else
127             {
128                 logger.warn("Deprecated 'synchronous' flag found on endpoint)");
129             }
130         }
131 
132         String mepString = (String) properties.get(MuleProperties.EXCHANGE_PATTERN_CAMEL_CASE);
133         if (StringUtils.isNotEmpty(mepString))
134         {
135             setExchangePattern(MessageExchangePattern.fromString(mepString));
136         }
137 
138         responseTimeout = getIntegerProperty(properties, PROPERTY_RESPONSE_TIMEOUT, responseTimeout);
139         responsePropertiesList = (String)properties.get(PROPERTY_RESPONSE_PROPERTIES);
140     }
141 
142     private static Boolean getBooleanProperty(Map<Object, Object> properties, String name, Boolean dflt)
143     {
144         if (properties.containsKey(name))
145         {
146             return Boolean.valueOf((String)properties.get(name));
147         }
148         else
149         {
150             return dflt;
151         }
152     }
153 
154     private static Integer getIntegerProperty(Map<Object, Object> properties, String name, Integer dflt)
155     {
156         if (properties.containsKey(name))
157         {
158             return Integer.decode((String)properties.get(name));
159         }
160         else
161         {
162             return dflt;
163         }
164     }
165 
166     protected InboundEndpoint doBuildInboundEndpoint() throws InitialisationException, EndpointException
167     {
168         //It does not make sense to allow inbound dynamic endpoints
169         String uri = uriBuilder.getConstructor();
170         if(muleContext.getExpressionManager().isExpression(uri))
171         {
172             throw new MalformedEndpointException(CoreMessages.dynamicEndpointURIsCannotBeUsedOnInbound(), uri);
173         }
174 
175         prepareToBuildEndpoint();
176 
177         EndpointURI endpointURI = uriBuilder.getEndpoint();
178         endpointURI.initialise();
179         
180         List<MessageProcessor> mergedProcessors = addReplyToProcessors(addTransformerProcessors(endpointURI));
181         List<MessageProcessor> mergedResponseProcessors = addResponseTransformerProcessors(endpointURI);
182 
183         Connector connector = getConnector();
184         if (connector != null && !connector.supportsProtocol(endpointURI.getFullScheme()))
185         {
186             throw new IllegalArgumentException(CoreMessages.connectorSchemeIncompatibleWithEndpointScheme(
187                 connector.getProtocol(), endpointURI).getMessage());
188         }
189 
190         checkInboundExchangePattern();
191 
192         // Filters on inbound endpoints need to throw exceptions in case the reciever needs to reject the message 
193         for (MessageProcessor mp :messageProcessors)
194         {
195             if (mp instanceof MessageFilter)
196             {
197                 ((MessageFilter) mp).setThrowOnUnaccepted(true);
198             }
199         }
200         
201         return new DefaultInboundEndpoint(connector, endpointURI,
202                 getName(endpointURI), getProperties(), getTransactionConfig(),
203                 getDefaultDeleteUnacceptedMessages(connector),
204                 messageExchangePattern, getResponseTimeout(connector), getInitialState(connector),
205                 getEndpointEncoding(connector), name, muleContext, getRetryPolicyTemplate(connector),
206                 getMessageProcessorsFactory(), mergedProcessors, mergedResponseProcessors,
207                 isDisableTransportTransformer(), mimeType);
208     }
209 
210     protected OutboundEndpoint doBuildOutboundEndpoint() throws InitialisationException, EndpointException
211     {
212 
213         String uri = uriBuilder.getConstructor();
214         if(muleContext.getExpressionManager().isExpression(uri))
215         {
216             if(muleContext.getExpressionManager().isValidExpression(uriBuilder.getConstructor()))
217             {
218                 String dynamicAddress = getDynamicUriFrom(uri);
219                 uriBuilder = new URIBuilder(dynamicAddress, muleContext);
220 
221                 return new DynamicOutboundEndpoint(this, uri);
222             }
223             else
224             {
225                 throw new MalformedEndpointException(uri);
226             }
227         }
228 
229         prepareToBuildEndpoint();
230 
231         EndpointURI endpointURI = uriBuilder.getEndpoint();
232         endpointURI.initialise();
233 
234         List<MessageProcessor> mergedProcessors = addTransformerProcessors(endpointURI);
235         List<MessageProcessor> mergedResponseProcessors = addResponseTransformerProcessors(endpointURI);
236 
237         Connector connector = getConnector();
238         if (connector != null && !connector.supportsProtocol(getScheme()))
239         {
240             throw new IllegalArgumentException(CoreMessages.connectorSchemeIncompatibleWithEndpointScheme(
241                 connector.getProtocol(), endpointURI).getMessage());
242         }
243 
244         checkOutboundExchangePattern();
245 
246         return new DefaultOutboundEndpoint(connector, endpointURI,
247                 getName(endpointURI), getProperties(), getTransactionConfig(),
248                 getDefaultDeleteUnacceptedMessages(connector), 
249                 messageExchangePattern, getResponseTimeout(connector), getInitialState(connector),
250                 getEndpointEncoding(connector), name, muleContext, getRetryPolicyTemplate(connector),
251                 responsePropertiesList,  getMessageProcessorsFactory(), mergedProcessors,
252                 mergedResponseProcessors, isDisableTransportTransformer(), mimeType);
253     }
254 
255     private String getDynamicUriFrom(String uri)
256     {
257         int index = uri.indexOf(":");
258         if (index == -1)
259         {
260             throw new IllegalArgumentException("Cannot obtain protocol from uri:" + uri);
261         }
262         String dynamicProtocol = uri.substring(0, index);
263         return dynamicProtocol + "://dynamic";
264     }
265 
266     
267     protected List<MessageProcessor> addTransformerProcessors(EndpointURI endpointURI)
268         throws TransportFactoryException
269     {
270         List<MessageProcessor> tempProcessors = new LinkedList<MessageProcessor>(messageProcessors);
271         tempProcessors.addAll(getTransformersFromUri(endpointURI));
272         tempProcessors.addAll(transformers);
273         return tempProcessors;
274     }
275 
276     protected List<MessageProcessor> addReplyToProcessors(List<MessageProcessor>  processors)
277     {
278         processors.add(new ReplyToParameterProcessor());
279         return processors;
280     }
281 
282     protected List<MessageProcessor> addResponseTransformerProcessors(EndpointURI endpointURI)
283         throws TransportFactoryException
284     {
285         List<MessageProcessor> tempResponseProcessors = new LinkedList<MessageProcessor>(
286             responseMessageProcessors);
287         tempResponseProcessors.addAll(getResponseTransformersFromUri(endpointURI));
288         tempResponseProcessors.addAll(responseTransformers);
289         return tempResponseProcessors;
290     }
291 
292     protected void prepareToBuildEndpoint()
293     {
294         // use an explicit value here to avoid caching
295         Map<Object, Object> props = getProperties();
296         // this sets values used below, if they appear as properties
297         setPropertiesFromProperties(props);
298 
299         if (uriBuilder == null)
300         {
301             throw new MuleRuntimeException(CoreMessages.objectIsNull("uriBuilder"));
302         }
303         uriBuilder.setMuleContext(muleContext);
304     }
305 
306     protected void checkInboundExchangePattern() throws EndpointException
307     {
308         TransportServiceDescriptor serviceDescriptor = getConnectorServiceDescriptor();
309         initExchangePatternFromConnectorDefault(serviceDescriptor);
310 
311         if (!serviceDescriptor.getInboundExchangePatterns().contains(messageExchangePattern))
312         {
313             throw new EndpointException(CoreMessages.exchangePatternForEndpointNotSupported(
314                 messageExchangePattern, "inbound", uriBuilder.getEndpoint()));
315         }
316     }
317 
318     private void checkOutboundExchangePattern() throws EndpointException
319     {
320         TransportServiceDescriptor serviceDescriptor = getConnectorServiceDescriptor();
321         initExchangePatternFromConnectorDefault(serviceDescriptor);
322 
323         if (!serviceDescriptor.getOutboundExchangePatterns().contains(messageExchangePattern))
324         {
325             throw new EndpointException(CoreMessages.exchangePatternForEndpointNotSupported(
326                 messageExchangePattern, "outbound", uriBuilder.getEndpoint()));
327         }
328     }
329 
330     private TransportServiceDescriptor getConnectorServiceDescriptor() throws EndpointException
331     {
332         try
333         {
334             Connector conn = getConnector();
335             return getNonNullServiceDescriptor(conn);
336         }
337         catch (ServiceException e)
338         {
339             throw new EndpointException(e);
340         }
341     }
342 
343     protected void initExchangePatternFromConnectorDefault(TransportServiceDescriptor serviceDescriptor)
344         throws EndpointException
345     {
346         if (messageExchangePattern == null)
347         {
348             try
349             {
350                 messageExchangePattern = serviceDescriptor.getDefaultExchangePattern();
351             }
352             catch (TransportServiceException e)
353             {
354                 throw new EndpointException(e);
355             }
356         }
357     }
358 
359     private Properties getOverrides(Connector connector)
360     {
361         // Get connector specific overrides to set on the descriptor
362         Properties overrides = new Properties();
363         if (connector instanceof AbstractConnector)
364         {
365             Map so = ((AbstractConnector)connector).getServiceOverrides();
366             if (so != null)
367             {
368                 overrides.putAll(so);
369             }
370         }
371         return overrides;
372     }
373 
374     private TransportServiceDescriptor getNonNullServiceDescriptor(Connector conn) throws ServiceException
375     {
376         String scheme = uriBuilder.getEndpoint().getSchemeMetaInfo();
377         Properties overrides = getOverrides(conn);
378         TransportServiceDescriptor sd = (TransportServiceDescriptor) muleContext.getRegistry()
379             .lookupServiceDescriptor(ServiceType.TRANSPORT, scheme, overrides);
380         if (null != sd)
381         {
382             return sd;
383         }
384         else
385         {
386             throw new ServiceException(CoreMessages.noServiceTransportDescriptor(scheme));
387         }
388     }
389 
390     protected RetryPolicyTemplate getRetryPolicyTemplate(Connector conn)
391     {
392         return retryPolicyTemplate != null ? retryPolicyTemplate : conn.getRetryPolicyTemplate();
393     }
394 
395     protected TransactionConfig getTransactionConfig()
396     {
397         return transactionConfig != null ? transactionConfig : getDefaultTransactionConfig();
398     }
399 
400     protected TransactionConfig getDefaultTransactionConfig()
401     {
402         return new MuleTransactionConfig();
403     }
404 
405     protected SecurityFilter getSecurityFilter()
406     {
407         for (MessageProcessor mp : messageProcessors)
408         {
409             if (mp instanceof SecurityFilterMessageProcessor)
410             {
411                 return ((SecurityFilterMessageProcessor) mp).getFilter();
412             }
413         }
414 
415         return null;
416     }
417 
418     protected EndpointSecurityFilter getDefaultSecurityFilter()
419     {
420         return null;
421     }
422 
423     protected Connector getConnector() throws EndpointException
424     {
425         return connector != null ? connector : getDefaultConnector();
426     }
427 
428     protected Connector getDefaultConnector() throws EndpointException
429     {
430         return getConnector(uriBuilder.getEndpoint());
431     }
432 
433     protected String getName(EndpointURI endpointURI)
434     {
435         return name != null ? name : new ObjectNameHelper(muleContext).getEndpointName(endpointURI);
436     }
437 
438     protected Map<Object, Object> getProperties()
439     {
440         // Add properties from builder, endpointURI and then seal (make unmodifiable)
441         LinkedList<Object> maps = new LinkedList<Object>();
442         // properties from url come first
443         if (null != uriBuilder)
444         {
445             uriBuilder.setMuleContext(muleContext);
446             // properties from the URI itself
447             maps.addLast(uriBuilder.getEndpoint().getParams());
448         }
449         // properties on builder may override url
450         if (properties != null)
451         {
452             maps.addLast(properties);
453         }
454         MapCombiner combiner = new MapCombiner();
455         combiner.setList(maps);
456         return Collections.unmodifiableMap(combiner);
457     }
458 
459     protected boolean getDeleteUnacceptedMessages(Connector connector)
460     {
461         return deleteUnacceptedMessages != null
462                                                ? deleteUnacceptedMessages.booleanValue()
463                                                : getDefaultDeleteUnacceptedMessages(connector);
464     }
465 
466     protected boolean getDefaultDeleteUnacceptedMessages(Connector connector)
467     {
468         return false;
469     }
470 
471     protected String getEndpointEncoding(Connector connector)
472     {
473         return encoding != null ? encoding : getDefaultEndpointEncoding(connector);
474     }
475 
476     protected String getDefaultEndpointEncoding(Connector connector)
477     {
478         return muleContext.getConfiguration().getDefaultEncoding();
479     }
480 
481     protected String getInitialState(Connector connector)
482     {
483         return initialState != null ? initialState : getDefaultInitialState(connector);
484     }
485 
486     protected String getDefaultInitialState(Connector connector)
487     {
488         return ImmutableEndpoint.INITIAL_STATE_STARTED;
489     }
490 
491     protected int getResponseTimeout(Connector connector)
492     {
493         return responseTimeout != null ? responseTimeout.intValue() : getDefaultResponseTimeout(connector);
494 
495     }
496 
497     protected int getDefaultResponseTimeout(Connector connector)
498     {
499         return muleContext.getConfiguration().getDefaultResponseTimeout();
500     }
501 
502     protected List<Transformer> getTransformersFromUri(EndpointURI endpointURI)
503         throws TransportFactoryException
504     {
505         if (endpointURI.getTransformers() != null)
506         {
507             if (!CollectionUtils.containsType(messageProcessors, Transformer.class))
508             {
509                 return getTransformersFromString(endpointURI.getTransformers());
510             }
511             else
512             {
513                 logger.info("Endpoint with uri '"
514                             + endpointURI.toString()
515                             + "' has transformer(s) configured, transformers configured as uri paramaters will be ignored.");
516             }
517         }
518         return Collections.emptyList();
519     }
520 
521     protected List<Transformer> getResponseTransformersFromUri(EndpointURI endpointURI)
522         throws TransportFactoryException
523     {
524         if (endpointURI.getResponseTransformers() != null)
525         {
526             if (!CollectionUtils.containsType(responseMessageProcessors, Transformer.class))
527             {
528                 return getTransformersFromString(endpointURI.getResponseTransformers());
529             }
530             else
531             {
532                 logger.info("Endpoint with uri '"
533                             + endpointURI.toString()
534                             + "' has response transformer(s) configured, response transformers configured as uri paramaters will be ignored.");
535             }
536         }
537         return Collections.emptyList();
538     }
539     
540     protected String getMimeType()
541     {
542         return mimeType;
543     }
544 
545     public void setMimeType(String mimeType)
546     {
547         if (mimeType == null)
548         {
549             this.mimeType = null;
550         }
551         else
552         {
553             MimeType mt;
554             try
555             {
556                 mt = new MimeType(mimeType);
557             }
558             catch (MimeTypeParseException e)
559             {
560                 throw new IllegalArgumentException(e.getMessage(), e);
561             }
562             this.mimeType = mt.getPrimaryType() + "/" + mt.getSubType();
563         }
564     }
565 
566     private List<Transformer> getTransformersFromString(String transformerString) throws TransportFactoryException
567     {
568         try
569         {
570             return TransformerUtils.getTransformers(transformerString, muleContext);
571         }
572         catch (DefaultMuleException e)
573         {
574             throw new TransportFactoryException(e);
575         }
576     }
577 
578     private Connector getConnector(EndpointURI endpointURI) throws EndpointException
579     {
580         String scheme = getScheme();
581         TransportFactory factory = new TransportFactory(muleContext);
582 
583         Connector connector;
584         try
585         {
586             if (uriBuilder.getEndpoint().getConnectorName() != null)
587             {
588                 connector = muleContext.getRegistry().lookupConnector(
589                     uriBuilder.getEndpoint().getConnectorName());
590                 if (connector == null)
591                 {
592                     throw new TransportFactoryException(CoreMessages.objectNotRegistered("Connector",
593                         uriBuilder.getEndpoint().getConnectorName()));
594                 }
595             }
596             else if (isAlwaysCreateConnector())
597             {
598                 connector = factory.createConnector(endpointURI);
599                 muleContext.getRegistry().registerConnector(connector);
600             }
601             else
602             {
603                 connector = factory.getConnectorByProtocol(scheme);
604                 if (connector == null)
605                 {
606                     connector = factory.createConnector(endpointURI);
607                     muleContext.getRegistry().registerConnector(connector);
608                 }
609             }
610         }
611         catch (Exception e)
612         {
613             throw new TransportFactoryException(e);
614         }
615 
616         if (connector == null)
617         {
618             Message m = CoreMessages.failedToCreateObjectWith("Endpoint", "endpointURI: " + endpointURI);
619             m.setNextMessage(CoreMessages.objectIsNull("connector"));
620             throw new TransportFactoryException(m);
621 
622         }
623         return connector;
624     }
625 
626     protected String getScheme()
627     {
628         return uriBuilder.getEndpoint().getFullScheme();
629     }
630 
631     /**
632      * Some endpoint may always require a new connector to be created for every
633      * endpoint
634      *
635      * @return the default if false but cusotm endpoints can override
636      * @since 3.0.0
637      */
638     protected boolean isAlwaysCreateConnector()
639     {
640         return false;
641     }
642 
643     // Builder setters
644 
645     public void setConnector(Connector connector)
646     {
647         this.connector = connector;
648     }
649 
650     /** @deprecated Use addMessageProcessor() */
651     @Deprecated
652     public void addTransformer(Transformer transformer)
653     {
654         this.transformers.add(transformer);
655     }
656 
657     /** @deprecated Use setMessageProcessors() */
658     @Deprecated
659     public void setTransformers(List<Transformer> newTransformers)
660     {
661         if (newTransformers == null)
662         {
663             newTransformers = new LinkedList<Transformer>();
664         }
665         this.transformers = newTransformers;
666     }
667 
668     protected EndpointMessageProcessorChainFactory getMessageProcessorsFactory()
669     {
670         return messageProcessorsFactory != null
671                                                ? messageProcessorsFactory
672                                                : getDefaultMessageProcessorsFactory();
673     }
674 
675     protected EndpointMessageProcessorChainFactory getDefaultMessageProcessorsFactory()
676     {
677         return new DefaultEndpointMessageProcessorChainFactory();
678     }
679 
680     /** @deprecated Use addResponseMessageProcessor() */
681     @Deprecated
682     public void addResponseTransformer(Transformer transformer)
683     {
684         this.responseTransformers.add(transformer);
685     }
686 
687     /** @deprecated Use setResponseMessageProcessors() */
688     @Deprecated
689     public void setResponseTransformers(List<Transformer> newResponseTransformers)
690     {
691         if (newResponseTransformers == null)
692         {
693             newResponseTransformers = new LinkedList<Transformer>();
694         }
695         this.responseTransformers = newResponseTransformers;
696     }
697 
698     public void addMessageProcessor(MessageProcessor messageProcessor)
699     {
700         messageProcessors.add(messageProcessor);
701     }
702 
703     public void setMessageProcessors(List<MessageProcessor> newMessageProcessors)
704     {
705         if (newMessageProcessors == null)
706         {
707             newMessageProcessors = new LinkedList<MessageProcessor>();
708         }
709         this.messageProcessors = newMessageProcessors;
710     }
711 
712     public List<MessageProcessor> getMessageProcessors()
713     {
714         return messageProcessors;
715     }
716 
717     public void addResponseMessageProcessor(MessageProcessor messageProcessor)
718     {
719         responseMessageProcessors.add(messageProcessor);
720     }
721 
722     public void setResponseMessageProcessors(List<MessageProcessor> newResponseMessageProcessors)
723     {
724         if (newResponseMessageProcessors == null)
725         {
726             newResponseMessageProcessors = new LinkedList<MessageProcessor>();
727         }
728         this.responseMessageProcessors = newResponseMessageProcessors;
729     }
730 
731     public List<MessageProcessor> getResponseMessageProcessors()
732     {
733         return responseMessageProcessors;
734     }
735 
736     protected boolean isDisableTransportTransformer()
737     {
738         return disableTransportTransformer != null
739                 ? disableTransportTransformer.booleanValue()
740                 : getDefaultDisableTransportTransformer();
741     }
742 
743     protected boolean getDefaultDisableTransportTransformer()
744     {
745         return false;
746     }
747 
748     public void setName(String name)
749     {
750         this.name = name;
751     }
752 
753     /**
754      * NOTE - this appends properties.
755      */
756     public void setProperties(Map<Object, Object> properties)
757     {
758         if (null == this.properties)
759         {
760             this.properties = new HashMap<Object, Object>();
761         }
762         this.properties.putAll(properties);
763     }
764 
765     /**
766      * Sets a property on the endpoint
767      *
768      * @param key the property key
769      * @param value the value of the property
770      */
771     public void setProperty(Object key, Object value)
772     {
773         properties.put(key, value);
774     }
775 
776     public void setTransactionConfig(TransactionConfig transactionConfig)
777     {
778         this.transactionConfig = transactionConfig;
779     }
780 
781     public void setDeleteUnacceptedMessages(boolean deleteUnacceptedMessages)
782     {
783         this.deleteUnacceptedMessages = Boolean.valueOf(deleteUnacceptedMessages);
784     }
785 
786     public void setExchangePattern(MessageExchangePattern mep)
787     {
788         messageExchangePattern = mep;
789     }
790 
791     public void setResponseTimeout(int responseTimeout)
792     {
793         this.responseTimeout = new Integer(responseTimeout);
794     }
795 
796     public void setInitialState(String initialState)
797     {
798         this.initialState = initialState;
799     }
800 
801     public void setEncoding(String encoding)
802     {
803         this.encoding = encoding;
804     }
805 
806     public void setCreateConnector(int createConnector)
807     {
808         this.createConnector = new Integer(createConnector);
809     }
810 
811     public void setRegistryId(String registryId)
812     {
813         this.registryId = registryId;
814     }
815 
816     public void setMuleContext(MuleContext muleContext)
817     {
818         this.muleContext = muleContext;
819     }
820 
821     public void setRetryPolicyTemplate(RetryPolicyTemplate retryPolicyTemplate)
822     {
823         this.retryPolicyTemplate = retryPolicyTemplate;
824     }
825 
826     public void setDisableTransportTransformer(boolean disableTransportTransformer)
827     {
828         this.disableTransportTransformer = Boolean.valueOf(disableTransportTransformer);
829     }
830 
831     public URIBuilder getEndpointBuilder()
832     {
833         return uriBuilder;
834     }
835 
836     public void setURIBuilder(URIBuilder URIBuilder)
837     {
838         this.uriBuilder = URIBuilder;
839     }
840 
841     @Override
842     public int hashCode()
843     {
844         return ClassUtils.hash(new Object[]{retryPolicyTemplate, connector, createConnector, 
845             deleteUnacceptedMessages, encoding, uriBuilder, initialState, name, properties,
846             responseTimeout, responseMessageProcessors, synchronous,
847             messageExchangePattern, transactionConfig, messageProcessors, disableTransportTransformer, mimeType});
848     }
849 
850     @Override
851     public boolean equals(Object obj)
852     {
853         if (this == obj)
854         {
855             return true;
856         }
857         if (obj == null || getClass() != obj.getClass())
858         {
859             return false;
860         }
861 
862         final AbstractEndpointBuilder other = (AbstractEndpointBuilder)obj;
863         return equal(retryPolicyTemplate, other.retryPolicyTemplate) && equal(connector, other.connector)
864                 && equal(createConnector, other.createConnector)
865                 && equal(deleteUnacceptedMessages, other.deleteUnacceptedMessages) && equal(encoding, other.encoding)
866                 && equal(uriBuilder, other.uriBuilder)
867                 && equal(initialState, other.initialState) && equal(name, other.name)
868                 && equal(properties, other.properties)
869                 && equal(responseTimeout, other.responseTimeout)
870                 && equal(messageProcessors, other.messageProcessors)
871                 && equal(synchronous, other.synchronous)
872                 && equal(messageExchangePattern, other.messageExchangePattern)
873                 && equal(transactionConfig, other.transactionConfig)
874                 && equal(responseMessageProcessors, other.responseMessageProcessors)
875                 && equal(disableTransportTransformer, other.disableTransportTransformer)
876                 && equal(mimeType, other.mimeType);
877     }
878 
879     protected static boolean equal(Object a, Object b)
880     {
881         return ClassUtils.equal(a, b);
882     }
883 
884     @Override
885     public Object clone() throws CloneNotSupportedException
886     {
887         EndpointBuilder builder = (EndpointBuilder)super.clone();
888         builder.setConnector(connector);
889         builder.setURIBuilder(uriBuilder);
890         builder.setMessageProcessors(messageProcessors);
891         builder.setResponseMessageProcessors(responseMessageProcessors);
892         builder.setName(name);
893         builder.setProperties(properties);
894         builder.setTransactionConfig(transactionConfig);
895         builder.setInitialState(initialState);
896         builder.setEncoding(encoding);
897         builder.setRegistryId(registryId);
898         builder.setMuleContext(muleContext);
899         builder.setRetryPolicyTemplate(retryPolicyTemplate);
900         builder.setTransformers(transformers);
901         builder.setResponseTransformers(responseTransformers);
902 
903         if (deleteUnacceptedMessages != null)
904         {
905             builder.setDeleteUnacceptedMessages(deleteUnacceptedMessages.booleanValue());
906         }
907         if (messageExchangePattern != null)
908         {
909             builder.setExchangePattern(messageExchangePattern);
910         }
911 
912         if (responseTimeout != null)
913         {
914             builder.setResponseTimeout(responseTimeout.intValue());
915         }
916         if (disableTransportTransformer != null)
917         {
918             builder.setDisableTransportTransformer(disableTransportTransformer.booleanValue());
919         }
920 
921         return builder;
922     }
923 
924 }