1
2
3
4
5
6
7 package org.mule.endpoint;
8
9 import org.mule.DefaultMuleEvent;
10 import org.mule.MessageExchangePattern;
11 import org.mule.api.MuleContext;
12 import org.mule.api.MuleEvent;
13 import org.mule.api.MuleException;
14 import org.mule.api.MuleMessage;
15 import org.mule.api.endpoint.EndpointBuilder;
16 import org.mule.api.endpoint.EndpointException;
17 import org.mule.api.endpoint.EndpointMessageProcessorChainFactory;
18 import org.mule.api.endpoint.EndpointURI;
19 import org.mule.api.endpoint.MalformedEndpointException;
20 import org.mule.api.endpoint.OutboundEndpoint;
21 import org.mule.api.expression.ExpressionManager;
22 import org.mule.api.expression.ExpressionRuntimeException;
23 import org.mule.api.lifecycle.InitialisationException;
24 import org.mule.api.processor.MessageProcessor;
25 import org.mule.api.retry.RetryPolicyTemplate;
26 import org.mule.api.routing.filter.Filter;
27 import org.mule.api.security.EndpointSecurityFilter;
28 import org.mule.api.transaction.TransactionConfig;
29 import org.mule.api.transformer.Transformer;
30 import org.mule.api.transport.Connector;
31 import org.mule.api.transport.DispatchException;
32 import org.mule.config.i18n.CoreMessages;
33 import org.mule.transport.AbstractConnector;
34 import org.mule.util.ObjectNameHelper;
35
36 import java.util.Collections;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Properties;
40
41 import org.apache.commons.collections.map.LRUMap;
42 import org.apache.commons.logging.Log;
43 import org.apache.commons.logging.LogFactory;
44
45
46
47
48
49
50
51
52
53
54 public class DynamicOutboundEndpoint implements OutboundEndpoint
55 {
56
57 public static final String DYNAMIC_URI_PLACEHOLDER = "dynamic://endpoint";
58
59 protected transient final Log logger = LogFactory.getLog(DynamicOutboundEndpoint.class);
60
61 private static final long serialVersionUID = 8861985949279708638L;
62
63
64
65
66 protected String uriTemplate;
67
68 private final EndpointBuilder builder;
69
70 private final OutboundEndpoint prototypeEndpoint;
71
72
73 private Map<String, OutboundEndpoint> staticEndpoints = Collections.synchronizedMap(new LRUMap(64));
74
75 public DynamicOutboundEndpoint(EndpointBuilder builder, String uriTemplate) throws MalformedEndpointException
76 {
77 validateUriTemplate(uriTemplate);
78
79 this.builder = builder;
80 this.uriTemplate = uriTemplate;
81
82 try
83 {
84 prototypeEndpoint = builder.buildOutboundEndpoint();
85 }
86 catch (Exception e)
87 {
88 throw new RuntimeException(e);
89 }
90 }
91
92 protected void validateUriTemplate(String uri) throws MalformedEndpointException
93 {
94 if (uri.indexOf(":") > uri.indexOf(ExpressionManager.DEFAULT_EXPRESSION_PREFIX))
95 {
96 throw new MalformedEndpointException(CoreMessages.dynamicEndpointsMustSpecifyAScheme(), uri);
97 }
98 }
99
100 protected EndpointURI getEndpointURIForMessage(MuleEvent event) throws DispatchException
101 {
102 if (logger.isDebugEnabled())
103 {
104 logger.debug("Uri before parsing is: " + uriTemplate);
105 }
106
107 String newUriString = uriTemplate;
108 try
109 {
110 newUriString = parseURIString(newUriString, event.getMessage());
111 }
112 catch (final ExpressionRuntimeException e)
113 {
114 throw new DispatchException(event, this, e);
115 }
116
117 if (logger.isDebugEnabled())
118 {
119 logger.debug("Uri after parsing is: " + newUriString);
120 }
121
122 try
123 {
124 final MuleEndpointURI resultUri = new MuleEndpointURI(newUriString, getMuleContext(), getServiceOverrides());
125 resultUri.initialise();
126
127 return resultUri;
128 }
129 catch (final Exception e)
130 {
131 throw new DispatchException(CoreMessages.templateCausedMalformedEndpoint(uriTemplate, newUriString), event, this, e);
132 }
133 }
134
135 private Properties getServiceOverrides() throws EndpointException
136 {
137 Properties properties = null;
138
139 if (builder instanceof AbstractEndpointBuilder)
140 {
141 Connector connector = ((AbstractEndpointBuilder) this.builder).getConnector();
142
143 if (connector instanceof AbstractConnector && ((AbstractConnector) connector).getServiceOverrides() != null)
144 {
145 properties = new Properties();
146 properties.putAll(((AbstractConnector) connector).getServiceOverrides());
147 }
148 }
149
150 return properties;
151 }
152
153 protected String parseURIString(String uri, MuleMessage message)
154 {
155 return this.getMuleContext().getExpressionManager().parse(uri, message, true);
156 }
157
158 public MuleEvent process(MuleEvent event) throws MuleException
159 {
160 EndpointURI endpointURIForMessage = getEndpointURIForMessage(event);
161 OutboundEndpoint outboundEndpoint = getStaticEndpointFor(endpointURIForMessage);
162
163 event = new DefaultMuleEvent(event.getMessage(), outboundEndpoint, event, event.getSession());
164
165 return outboundEndpoint.process(event);
166 }
167
168 private OutboundEndpoint getStaticEndpointFor(EndpointURI uri) throws EndpointException, InitialisationException
169 {
170 OutboundEndpoint outboundEndpoint = staticEndpoints.get(uri.getAddress());
171
172 if (outboundEndpoint == null)
173 {
174 outboundEndpoint = createStaticEndpoint(uri);
175 staticEndpoints.put(uri.getAddress(), outboundEndpoint);
176 }
177
178 return outboundEndpoint;
179 }
180
181 private OutboundEndpoint createStaticEndpoint(EndpointURI uri) throws EndpointException, InitialisationException
182 {
183 try
184 {
185 EndpointBuilder staticBuilder = (EndpointBuilder) builder.clone();
186 staticBuilder.setURIBuilder(new URIBuilder(uri));
187 String endpointName = ObjectNameHelper.getEndpointNameFor(uri);
188 staticBuilder.setName(endpointName);
189 return staticBuilder.buildOutboundEndpoint();
190 }
191 catch (CloneNotSupportedException e)
192 {
193
194 throw new IllegalStateException("Unable to clone endpoint builder");
195 }
196 }
197
198 @Override
199 public boolean equals(Object o)
200 {
201 return this == o;
202 }
203
204 @Override
205 public int hashCode()
206 {
207 return System.identityHashCode(this);
208 }
209
210 public Connector getConnector()
211 {
212 throw new UnsupportedOperationException("No connector available");
213 }
214
215 public EndpointURI getEndpointURI()
216 {
217 return null;
218 }
219
220 public String getAddress()
221 {
222 return uriTemplate;
223 }
224
225 public RetryPolicyTemplate getRetryPolicyTemplate()
226 {
227 return prototypeEndpoint.getRetryPolicyTemplate();
228 }
229
230 public String getEncoding()
231 {
232 return prototypeEndpoint.getEncoding();
233 }
234
235 public String getMimeType()
236 {
237 return prototypeEndpoint.getMimeType();
238 }
239
240 public Filter getFilter()
241 {
242 return prototypeEndpoint.getFilter();
243 }
244
245 public String getInitialState()
246 {
247 return prototypeEndpoint.getInitialState();
248 }
249
250 public MuleContext getMuleContext()
251 {
252 return prototypeEndpoint.getMuleContext();
253 }
254
255 public String getName()
256 {
257 return prototypeEndpoint.getName();
258 }
259
260 public Map getProperties()
261 {
262 return prototypeEndpoint.getProperties();
263 }
264
265 public Object getProperty(Object key)
266 {
267 return prototypeEndpoint.getProperty(key);
268 }
269
270 public String getProtocol()
271 {
272 return prototypeEndpoint.getProtocol();
273 }
274
275 public int getResponseTimeout()
276 {
277 return prototypeEndpoint.getResponseTimeout();
278 }
279
280 public List<Transformer> getResponseTransformers()
281 {
282 return prototypeEndpoint.getResponseTransformers();
283 }
284
285 public EndpointMessageProcessorChainFactory getMessageProcessorsFactory()
286 {
287 return prototypeEndpoint.getMessageProcessorsFactory();
288 }
289
290 public List<MessageProcessor> getMessageProcessors()
291 {
292 return prototypeEndpoint.getMessageProcessors();
293 }
294
295 public List<MessageProcessor> getResponseMessageProcessors()
296 {
297 return prototypeEndpoint.getResponseMessageProcessors();
298 }
299
300 public EndpointSecurityFilter getSecurityFilter()
301 {
302 return prototypeEndpoint.getSecurityFilter();
303 }
304
305 public TransactionConfig getTransactionConfig()
306 {
307 return prototypeEndpoint.getTransactionConfig();
308 }
309
310 public List<Transformer> getTransformers()
311 {
312 return prototypeEndpoint.getTransformers();
313 }
314
315 public boolean isDeleteUnacceptedMessages()
316 {
317 return prototypeEndpoint.isDeleteUnacceptedMessages();
318 }
319
320 public boolean isReadOnly()
321 {
322 return prototypeEndpoint.isReadOnly();
323 }
324
325 public MessageExchangePattern getExchangePattern()
326 {
327 return prototypeEndpoint.getExchangePattern();
328 }
329
330 public List<String> getResponseProperties()
331 {
332 return prototypeEndpoint.getResponseProperties();
333 }
334
335 public String getEndpointBuilderName()
336 {
337 return prototypeEndpoint.getEndpointBuilderName();
338 }
339
340 public boolean isProtocolSupported(String protocol)
341 {
342 return prototypeEndpoint.isProtocolSupported(protocol);
343 }
344
345 public boolean isDisableTransportTransformer()
346 {
347 return prototypeEndpoint.isDisableTransportTransformer();
348 }
349 }