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