1
2
3
4
5
6
7 package org.mule.endpoint;
8
9 import org.mule.MessageExchangePattern;
10 import org.mule.api.MuleContext;
11 import org.mule.api.MuleException;
12 import org.mule.api.construct.FlowConstruct;
13 import org.mule.api.endpoint.EndpointMessageProcessorChainFactory;
14 import org.mule.api.endpoint.EndpointURI;
15 import org.mule.api.endpoint.ImmutableEndpoint;
16 import org.mule.api.lifecycle.Disposable;
17 import org.mule.api.processor.MessageProcessor;
18 import org.mule.api.processor.MessageProcessorChain;
19 import org.mule.api.retry.RetryPolicyTemplate;
20 import org.mule.api.routing.filter.Filter;
21 import org.mule.api.security.EndpointSecurityFilter;
22 import org.mule.api.security.SecurityFilter;
23 import org.mule.api.transaction.TransactionConfig;
24 import org.mule.api.transformer.Transformer;
25 import org.mule.api.transport.Connector;
26 import org.mule.processor.SecurityFilterMessageProcessor;
27 import org.mule.routing.MessageFilter;
28 import org.mule.util.ClassUtils;
29
30 import java.net.URI;
31 import java.util.HashMap;
32 import java.util.LinkedList;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.regex.Matcher;
36 import java.util.regex.Pattern;
37
38 import edu.emory.mathcs.backport.java.util.Collections;
39
40 import org.apache.commons.logging.Log;
41 import org.apache.commons.logging.LogFactory;
42
43
44
45
46
47 public abstract class AbstractEndpoint implements ImmutableEndpoint, Disposable
48 {
49
50 private static final long serialVersionUID = -1650380871293160973L;
51
52 public static final String PROPERTY_PROCESS_SYNCHRONOUSLY = "processSynchronously";
53
54
55
56
57 protected static final Log logger = LogFactory.getLog(AbstractEndpoint.class);
58
59
60
61
62 private final Connector connector;
63
64
65
66
67 private final EndpointURI endpointUri;
68
69 private final EndpointMessageProcessorChainFactory messageProcessorsFactory;
70
71 private final List <MessageProcessor> messageProcessors;
72
73 private final List <MessageProcessor> responseMessageProcessors;
74
75 private MessageProcessor messageProcessorChain;
76
77
78
79
80 private final String name;
81
82
83
84
85
86
87 private Map properties = new HashMap();
88
89
90
91
92 private final TransactionConfig transactionConfig;
93
94
95
96
97
98
99 private final boolean deleteUnacceptedMessages;
100
101 private final MessageExchangePattern messageExchangePattern;
102
103
104
105
106
107
108 private final int responseTimeout;
109
110
111
112
113 private final String initialState;
114
115 private final String endpointEncoding;
116
117 private MuleContext muleContext;
118
119 protected RetryPolicyTemplate retryPolicyTemplate;
120
121 private String endpointBuilderName;
122
123 private final String endpointMimeType;
124
125 private boolean disableTransportTransformer = false;
126
127 public AbstractEndpoint(Connector connector,
128 EndpointURI endpointUri,
129 String name,
130 Map properties,
131 TransactionConfig transactionConfig,
132 boolean deleteUnacceptedMessages,
133 MessageExchangePattern messageExchangePattern,
134 int responseTimeout,
135 String initialState,
136 String endpointEncoding,
137 String endpointBuilderName,
138 MuleContext muleContext,
139 RetryPolicyTemplate retryPolicyTemplate,
140 EndpointMessageProcessorChainFactory messageProcessorsFactory,
141 List <MessageProcessor> messageProcessors,
142 List <MessageProcessor> responseMessageProcessors,
143 boolean disableTransportTransformer,
144 String endpointMimeType)
145 {
146 this.connector = connector;
147 this.endpointUri = endpointUri;
148 this.name = name;
149
150
151 this.properties.putAll(properties);
152 this.transactionConfig = transactionConfig;
153 this.deleteUnacceptedMessages = deleteUnacceptedMessages;
154
155 this.responseTimeout = responseTimeout;
156 this.initialState = initialState;
157 this.endpointEncoding = endpointEncoding;
158 this.endpointBuilderName = endpointBuilderName;
159 this.muleContext = muleContext;
160 this.retryPolicyTemplate = retryPolicyTemplate;
161 this.endpointMimeType = endpointMimeType;
162 this.disableTransportTransformer = disableTransportTransformer;
163
164 if (transactionConfig != null && transactionConfig.getFactory() != null &&
165 transactionConfig.getAction() != TransactionConfig.ACTION_NONE &&
166 transactionConfig.getAction() != TransactionConfig.ACTION_NEVER)
167 {
168 if (logger.isDebugEnabled())
169 {
170 logger.debug("Endpoint has a transaction configuration. Defaulting to REQUEST_RESPONSE. Endpoint is: " + toString());
171 }
172 this.messageExchangePattern = MessageExchangePattern.REQUEST_RESPONSE;
173 }
174 else
175 {
176 this.messageExchangePattern = messageExchangePattern;
177 }
178
179 this.messageProcessorsFactory = messageProcessorsFactory;
180 if (messageProcessors == null)
181 {
182 this.messageProcessors = Collections.emptyList();
183 }
184 else
185 {
186 this.messageProcessors = messageProcessors;
187 }
188 if (responseMessageProcessors == null)
189 {
190 this.responseMessageProcessors = Collections.emptyList();
191 }
192 else
193 {
194 this.responseMessageProcessors = responseMessageProcessors;
195 }
196 }
197
198 public EndpointURI getEndpointURI()
199 {
200 return endpointUri;
201 }
202
203 public String getAddress()
204 {
205 EndpointURI uri = getEndpointURI();
206 if (uri != null)
207 {
208 return uri.getUri().toString();
209 }
210 else
211 {
212 return null;
213 }
214 }
215
216 public String getEncoding()
217 {
218 return endpointEncoding;
219 }
220
221 public String getMimeType()
222 {
223 return endpointMimeType;
224 }
225
226 public Connector getConnector()
227 {
228 return connector;
229 }
230
231 public String getName()
232 {
233 return name;
234 }
235
236 public EndpointMessageProcessorChainFactory getMessageProcessorsFactory()
237 {
238 return messageProcessorsFactory;
239 }
240
241 public List <MessageProcessor> getMessageProcessors()
242 {
243 return messageProcessors;
244 }
245
246 public List <MessageProcessor> getResponseMessageProcessors()
247 {
248 return responseMessageProcessors;
249 }
250
251
252 public List<Transformer> getTransformers()
253 {
254 return getTransformersFromProcessorList(messageProcessors);
255 }
256
257 public Map getProperties()
258 {
259 return properties;
260 }
261
262 public boolean isReadOnly()
263 {
264 return true;
265 }
266
267 @Override
268 public String toString()
269 {
270
271
272 String sanitizedEndPointUri = null;
273 URI uri = null;
274 if (endpointUri != null)
275 {
276 sanitizedEndPointUri = endpointUri.toString();
277 uri = endpointUri.getUri();
278 }
279
280
281
282 if (uri != null && (uri.getRawUserInfo() != null) && (uri.getScheme() != null) && (uri.getHost() != null)
283 && (uri.getRawPath() != null))
284 {
285
286 Pattern sanitizerPattern = Pattern.compile("(.*):.*");
287 Matcher sanitizerMatcher = sanitizerPattern.matcher(uri.getRawUserInfo());
288 if (sanitizerMatcher.matches())
289 {
290 sanitizedEndPointUri = new StringBuffer(uri.getScheme()).append("://")
291 .append(sanitizerMatcher.group(1))
292 .append(":<password>")
293 .append("@")
294 .append(uri.getHost())
295 .append(uri.getRawPath())
296 .toString();
297 }
298 if (uri.getRawQuery() != null)
299 {
300 sanitizedEndPointUri = sanitizedEndPointUri + "?" + uri.getRawQuery();
301 }
302
303 }
304
305 return ClassUtils.getClassName(getClass()) + "{endpointUri=" + sanitizedEndPointUri + ", connector="
306 + connector + ", name='" + name + "', mep=" + messageExchangePattern + ", properties=" + properties
307 + ", transactionConfig=" + transactionConfig + ", deleteUnacceptedMessages=" + deleteUnacceptedMessages
308 + ", initialState=" + initialState + ", responseTimeout="
309 + responseTimeout + ", endpointEncoding=" + endpointEncoding + ", disableTransportTransformer="
310 + disableTransportTransformer + "}";
311 }
312
313 public String getProtocol()
314 {
315 return connector.getProtocol();
316 }
317
318 public TransactionConfig getTransactionConfig()
319 {
320 return transactionConfig;
321 }
322
323 protected static boolean equal(Object a, Object b)
324 {
325 return ClassUtils.equal(a, b);
326 }
327
328 @Override
329 public boolean equals(Object obj)
330 {
331 if (this == obj)
332 {
333 return true;
334 }
335 if (obj == null || getClass() != obj.getClass())
336 {
337 return false;
338 }
339
340 final AbstractEndpoint other = (AbstractEndpoint) obj;
341 return equal(retryPolicyTemplate, other.retryPolicyTemplate)
342 && equal(connector, other.connector)
343 && deleteUnacceptedMessages == other.deleteUnacceptedMessages
344 && equal(endpointEncoding, other.endpointEncoding)
345 && equal(endpointUri, other.endpointUri)
346 && equal(initialState, other.initialState)
347
348
349 && equal(messageExchangePattern, other.messageExchangePattern)
350 && equal(name, other.name)
351 && equal(properties, other.properties)
352 && responseTimeout == other.responseTimeout
353 && equal(messageProcessors, other.messageProcessors)
354 && equal(responseMessageProcessors, other.responseMessageProcessors)
355 && equal(transactionConfig, other.transactionConfig)
356 && disableTransportTransformer == other.disableTransportTransformer;
357 }
358
359 @Override
360 public int hashCode()
361 {
362 return ClassUtils.hash(new Object[]{this.getClass(), retryPolicyTemplate, connector,
363 deleteUnacceptedMessages ? Boolean.TRUE : Boolean.FALSE,
364 endpointEncoding,
365 endpointUri,
366 initialState,
367
368
369 messageExchangePattern,
370 name,
371 properties,
372 Integer.valueOf(responseTimeout),
373 responseMessageProcessors,
374 transactionConfig,
375 messageProcessors,
376 disableTransportTransformer ? Boolean.TRUE : Boolean.FALSE});
377 }
378
379 public Filter getFilter()
380 {
381
382 for (MessageProcessor mp : messageProcessors)
383 {
384 if (mp instanceof MessageFilter)
385 {
386 return ((MessageFilter) mp).getFilter();
387 }
388 }
389 return null;
390 }
391
392 public boolean isDeleteUnacceptedMessages()
393 {
394 return deleteUnacceptedMessages;
395 }
396
397
398
399
400
401
402
403
404
405 public EndpointSecurityFilter getSecurityFilter()
406 {
407 for (MessageProcessor mp : messageProcessors)
408 {
409 if (mp instanceof SecurityFilterMessageProcessor)
410 {
411 SecurityFilter filter = ((SecurityFilterMessageProcessor)mp).getFilter();
412 if (filter instanceof EndpointSecurityFilter)
413 {
414 return (EndpointSecurityFilter) filter;
415 }
416 }
417 }
418
419 return null;
420 }
421
422 public MessageExchangePattern getExchangePattern()
423 {
424 return messageExchangePattern;
425 }
426
427
428
429
430
431
432 public int getResponseTimeout()
433 {
434 return responseTimeout;
435 }
436
437
438
439
440
441
442
443 public String getInitialState()
444 {
445 return initialState;
446 }
447
448
449 public List<Transformer> getResponseTransformers()
450 {
451 return getTransformersFromProcessorList(responseMessageProcessors);
452 }
453
454 private List<Transformer> getTransformersFromProcessorList(List<MessageProcessor> processors)
455 {
456 List<Transformer> transformers = new LinkedList<Transformer>();
457 for (MessageProcessor processor : processors)
458 {
459 if (processor instanceof Transformer)
460 {
461 transformers.add((Transformer) processor);
462 }
463 else if (processor instanceof MessageProcessorChain)
464 {
465 transformers.addAll(getTransformersFromProcessorList(((MessageProcessorChain) processor).getMessageProcessors()));
466 }
467 }
468 return transformers;
469 }
470
471 public Object getProperty(Object key)
472 {
473 return properties.get(key);
474 }
475
476 public MuleContext getMuleContext()
477 {
478 return muleContext;
479 }
480
481 public RetryPolicyTemplate getRetryPolicyTemplate()
482 {
483 return retryPolicyTemplate;
484 }
485
486 public String getEndpointBuilderName()
487 {
488 return endpointBuilderName;
489 }
490
491 public boolean isProtocolSupported(String protocol)
492 {
493 return connector.supportsProtocol(protocol);
494 }
495
496 public boolean isDisableTransportTransformer()
497 {
498 return disableTransportTransformer;
499 }
500
501 public void dispose()
502 {
503 this.muleContext = null;
504
505
506
507 this.messageProcessorChain = null;
508 }
509
510 public MessageProcessor getMessageProcessorChain(FlowConstruct flowContruct) throws MuleException
511 {
512 if (messageProcessorChain == null)
513 {
514 messageProcessorChain = createMessageProcessorChain(flowContruct);
515 }
516 return messageProcessorChain;
517 }
518
519 abstract protected MessageProcessor createMessageProcessorChain(FlowConstruct flowContruct) throws MuleException;
520 }