View Javadoc

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