View Javadoc

1   /*
2    * $Id: MuleEndpointURI.java 20112 2010-11-08 01:33:08Z mike.schilling $
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.api.MuleContext;
14  import org.mule.api.endpoint.EndpointException;
15  import org.mule.api.endpoint.EndpointURI;
16  import org.mule.api.endpoint.EndpointURIBuilder;
17  import org.mule.api.endpoint.MalformedEndpointException;
18  import org.mule.api.lifecycle.InitialisationException;
19  import org.mule.api.registry.ServiceException;
20  import org.mule.api.registry.ServiceType;
21  import org.mule.config.i18n.CoreMessages;
22  import org.mule.transport.service.TransportServiceDescriptor;
23  import org.mule.util.ClassUtils;
24  import org.mule.util.PropertiesUtils;
25  import org.mule.util.StringUtils;
26  
27  import java.net.URI;
28  import java.net.URISyntaxException;
29  import java.util.Properties;
30  
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  
34  /**
35   * <code>MuleEndpointURI</code> is used to determine how a message is sent or received. The url 
36   * defines the protocol, the endpointUri destination of the message and optionally the endpoint to 
37   * use when dispatching the event. Mule urls take the form of - 
38   * protocol://[host]:[port]/[provider]/endpointUri or
39   * protocol://[host]:[port]/endpointUri i.e. vm:///my.object 
40   * <br/>
41   * The protocol can be any of any connector registered with Mule. The endpoint name if specified 
42   * must be the name of a registered global endpoint. The endpointUri can be any endpointUri
43   * recognised by the endpoint type.
44   */
45  public class MuleEndpointURI implements EndpointURI
46  {
47      /**
48       * Serial version
49       */
50      private static final long serialVersionUID = 3906735768171252877L;
51  
52      /**
53       * logger used by this class
54       */
55      protected static final Log logger = LogFactory.getLog(MuleEndpointURI.class);
56  
57      public static boolean isMuleUri(String url)
58      {
59          return url.indexOf(":/") != -1;
60      }
61  
62      private String address;
63      private String filterAddress;
64      private String endpointName;
65      private String connectorName;
66      private String transformers;
67      private String responseTransformers;
68      private Properties params = new Properties();
69      private URI uri;
70      private String userInfo;
71      private String schemeMetaInfo;
72      private String resourceInfo;
73      private boolean dynamic;
74      private transient MuleContext muleContext;
75  
76      MuleEndpointURI(String address,
77                      String endpointName,
78                      String connectorName,
79                      String transformers,
80                      String responseTransformers,
81                      Properties properties,
82                      URI uri,
83                      String userInfo, MuleContext muleContext)
84      {
85          this(address, endpointName, connectorName, transformers, responseTransformers,
86                  properties, uri, muleContext);
87          if (userInfo != null)
88          {
89              this.userInfo = userInfo;
90          }
91      }
92  
93      public MuleEndpointURI(String address,
94                             String endpointName,
95                             String connectorName,
96                             String transformers,
97                             String responseTransformers,
98                             Properties properties,
99                             URI uri, MuleContext muleContext)
100     {
101         this.address = address;
102         this.endpointName = endpointName;
103         this.connectorName = connectorName;
104         this.transformers = transformers;
105         this.responseTransformers = responseTransformers;
106         this.params = properties;
107         this.uri = uri;
108         this.userInfo = uri.getUserInfo();
109         this.muleContext = muleContext;
110         if (properties != null)
111         {
112             resourceInfo = (String) properties.remove("resourceInfo");
113         }
114     }
115 
116     public MuleEndpointURI(EndpointURI endpointUri)
117     {
118         initialise(endpointUri);
119     }
120 
121     public MuleEndpointURI(EndpointURI endpointUri, String filterAddress)
122     {
123         initialise(endpointUri);
124         this.filterAddress = filterAddress;
125     }
126 
127     public MuleEndpointURI(String uri, MuleContext muleContext) throws EndpointException
128     {
129         this(uri, null, muleContext);       
130     }
131 
132     /**
133      * Creates but does not initialize the endpoint URI.  It is up to the caller
134      * to call initialise() at some point.
135      */
136     public MuleEndpointURI(String uri, String encodedUri, MuleContext muleContext) throws EndpointException
137     {
138         this.muleContext = muleContext;
139         uri = preprocessUri(uri);
140         String startUri = uri;
141         uri = convertExpressionDelimiters(uri, "#");
142         uri = convertExpressionDelimiters(uri, "$");
143 
144         if (uri.indexOf("#[") >= 0)
145         {
146             address = uri;
147             dynamic = true;
148         }
149         else
150         {
151             try
152             {
153                 this.uri = new URI((encodedUri != null && uri.equals(startUri)) ? preprocessUri(encodedUri) : uri);
154             }
155             catch (URISyntaxException e)
156             {
157                 throw new MalformedEndpointException(uri, e);
158             }
159             this.userInfo = this.uri.getRawUserInfo();
160         }
161     }
162 
163     private String convertExpressionDelimiters(String uri, String startChar)
164     {
165         //Allow Expressions to be embedded
166         int uriLength = uri.length();
167         for (int index = 0; index < uriLength; )
168         {
169             index = uri.indexOf(startChar + "{", index);
170             if (index < 0)
171             {
172                 break;
173             }
174             int braceCount = 1;
175             for (int seek = index + 2; seek < uriLength; seek++)
176             {
177                 char c = uri.charAt(seek);
178                 if (c == '{')
179                 {
180                     braceCount++;
181                 }
182                 else if (c == '}')
183                 {
184                     if (--braceCount == 0)
185                     {
186                         uri = uri.substring(0, index) + startChar + "[" + uri.substring(index + 2, seek) + "]" + uri.substring(seek+1);
187                         break;
188                     }
189                 }
190             }
191             index += 2;
192         }
193         return uri;
194     }
195 
196     protected String preprocessUri(String uri) throws MalformedEndpointException
197     {
198         uri = uri.trim().replaceAll(" ", "%20");
199         if (!validateUrl(uri))
200         {
201             throw new MalformedEndpointException(uri);
202         }
203         schemeMetaInfo = retrieveSchemeMetaInfo(uri);
204         if (schemeMetaInfo != null)
205         {
206             uri = uri.replaceFirst(schemeMetaInfo + ":", "");
207         }
208         return uri;
209     }
210 
211     public void initialise() throws InitialisationException
212     {
213         try
214         {
215             String scheme = getFullScheme();
216             TransportServiceDescriptor sd;
217             sd = (TransportServiceDescriptor) muleContext.getRegistry().lookupServiceDescriptor(ServiceType.TRANSPORT, scheme, null);
218             if (sd == null)
219             {
220                 throw new ServiceException(CoreMessages.noServiceTransportDescriptor(scheme));
221             }
222             EndpointURIBuilder builder = sd.createEndpointURIBuilder();
223             EndpointURI built = builder.build(this.uri, muleContext);
224             initialise(built);
225         }
226         catch (Exception e)
227         {
228             throw new InitialisationException(e, this);
229         }
230     }
231 
232     private String retrieveSchemeMetaInfo(String url)
233     {
234         int i = url.indexOf(':');
235         if (i == -1)
236         {
237             return null;
238         }
239         if (url.charAt(i + 1) == '/')
240         {
241             return null;
242         }
243         else
244         {
245             return url.substring(0, i);
246         }
247     }
248 
249     protected boolean validateUrl(String url)
250     {
251         return (url.indexOf(":/") > 0);
252     }
253 
254     private void initialise(EndpointURI endpointUri)
255     {
256         this.address = endpointUri.getAddress();
257         if (this.endpointName == null)
258         {
259             this.endpointName = endpointUri.getEndpointName();
260         }
261         this.connectorName = endpointUri.getConnectorName();
262         this.transformers = endpointUri.getTransformers();
263         this.responseTransformers = endpointUri.getResponseTransformers();
264         this.params = endpointUri.getParams();
265         this.uri = endpointUri.getUri();
266         this.resourceInfo = endpointUri.getResourceInfo();
267         this.userInfo = endpointUri.getUserInfo();
268     }
269 
270     public String getAddress()
271     {
272         return address;
273     }
274 
275     public String getEndpointName()
276     {
277         return (StringUtils.isEmpty(endpointName) ? null : endpointName);
278     }
279 
280     public Properties getParams()
281     {
282         // TODO fix this so that the query string properties are not lost.
283         // not sure whats causing this at the moment
284         if (params.size() == 0 && getQuery() != null)
285         {
286             params = PropertiesUtils.getPropertiesFromQueryString(getQuery());
287         }
288         return params;
289     }
290 
291     public Properties getUserParams()
292     {
293         Properties p = new Properties();
294         p.putAll(getParams());
295         p.remove(PROPERTY_ENDPOINT_NAME);
296         p.remove(PROPERTY_ENDPOINT_URI);
297         p.remove(PROPERTY_TRANSFORMERS);
298         return p;
299     }
300 
301     public URI parseServerAuthority() throws URISyntaxException
302     {
303         return uri.parseServerAuthority();
304     }
305 
306     public URI normalize()
307     {
308         return uri.normalize();
309     }
310 
311     public URI resolve(URI uri)
312     {
313         return uri.resolve(uri);
314     }
315 
316     public URI resolve(String str)
317     {
318         return uri.resolve(str);
319     }
320 
321     public URI relativize(URI uri)
322     {
323         return uri.relativize(uri);
324     }
325 
326     public String getScheme()
327     {
328         return uri.getScheme();
329     }
330 
331     public String getFullScheme()
332     {
333         String scheme;
334         if (dynamic)
335         {
336             int colon = address.indexOf(':');
337             scheme = address.substring(0, colon);
338         }
339         else
340         {
341             scheme = uri.getScheme();
342         }
343         return (schemeMetaInfo == null ? scheme : schemeMetaInfo + ':' + scheme);
344     }
345 
346     public boolean isAbsolute()
347     {
348         return uri.isAbsolute();
349     }
350 
351     public boolean isOpaque()
352     {
353         return uri.isOpaque();
354     }
355 
356     public String getRawSchemeSpecificPart()
357     {
358         return uri.getRawSchemeSpecificPart();
359     }
360 
361     public String getSchemeSpecificPart()
362     {
363         return uri.getSchemeSpecificPart();
364     }
365 
366     public String getRawAuthority()
367     {
368         return uri.getRawAuthority();
369     }
370 
371     public String getAuthority()
372     {
373         return uri.getAuthority();
374     }
375 
376     public String getRawUserInfo()
377     {
378         return uri.getRawUserInfo();
379     }
380 
381     public String getUserInfo()
382     {
383         return userInfo;
384     }
385 
386     public String getHost()
387     {
388         return uri.getHost();
389     }
390 
391     public int getPort()
392     {
393         return uri.getPort();
394     }
395 
396     public String getRawPath()
397     {
398         return uri.getRawPath();
399     }
400 
401     public String getPath()
402     {
403         return uri.getPath();
404     }
405 
406     public String getRawQuery()
407     {
408         return uri.getRawQuery();
409     }
410 
411     public String getQuery()
412     {
413         return uri.getQuery();
414     }
415 
416     public String getRawFragment()
417     {
418         return uri.getRawFragment();
419     }
420 
421     public String getFragment()
422     {
423         return uri.getFragment();
424     }
425 
426     @Override
427     public String toString()
428     {
429         if (StringUtils.isNotEmpty(userInfo) && (userInfo.indexOf(":") > 0))
430         {
431             // Mask passwords in the logs
432             String maskinfo = userInfo.substring(0, userInfo.indexOf(":")) + ":****";
433             return uri.toASCIIString().replace(userInfo, maskinfo);
434         }
435         return uri.toASCIIString();
436     }
437 
438     public String getTransformers()
439     {
440         return transformers;
441     }
442 
443     public URI getUri()
444     {
445         return uri;
446     }
447 
448     public String getConnectorName()
449     {
450         return connectorName;
451     }
452 
453     public String getSchemeMetaInfo()
454     {
455         return (schemeMetaInfo == null ? uri.getScheme() : schemeMetaInfo);
456     }
457 
458     public String getResourceInfo()
459     {
460         return resourceInfo;
461     }
462 
463     public String getFilterAddress()
464     {
465         return filterAddress;
466     }
467 
468     public String getUser()
469     {
470         if (StringUtils.isNotBlank(userInfo))
471         {
472             int i = userInfo.indexOf(':');
473             if (i == -1)
474             {
475                 return userInfo;
476             }
477             else
478             {
479                 return userInfo.substring(0, i);
480             }
481         }
482         return null;
483     }
484 
485     public String getResponseTransformers()
486     {
487         return responseTransformers;
488     }
489 
490     public String getPassword()
491     {
492         if (StringUtils.isNotBlank(userInfo))
493         {
494             int i = userInfo.indexOf(':');
495             if (i > -1)
496             {
497                 return userInfo.substring(i + 1);
498             }
499         }
500         return null;
501     }
502 
503     public MuleContext getMuleContext()
504     {
505         return muleContext;
506     }
507 
508     public boolean isDynamic()
509     {
510         return dynamic;
511     }
512 
513     @Override
514     public boolean equals(Object o)
515     {
516         if (this == o)
517         {
518             return true;
519         }
520         if (!(o instanceof MuleEndpointURI))
521         {
522             return false;
523         }
524         MuleEndpointURI muleEndpointURI = (MuleEndpointURI) o;
525         return ClassUtils.equal(address, muleEndpointURI.address) &&
526                 ClassUtils.equal(connectorName, muleEndpointURI.connectorName) &&
527                 ClassUtils.equal(endpointName, muleEndpointURI.endpointName) &&
528                 ClassUtils.equal(filterAddress, muleEndpointURI.filterAddress) &&
529                 ClassUtils.equal(params, muleEndpointURI.params) &&
530                 ClassUtils.equal(resourceInfo, muleEndpointURI.resourceInfo) &&
531                 ClassUtils.equal(schemeMetaInfo, muleEndpointURI.schemeMetaInfo) &&
532                 ClassUtils.equal(transformers, muleEndpointURI.transformers) &&
533                 ClassUtils.equal(responseTransformers, muleEndpointURI.responseTransformers) &&
534                 ClassUtils.equal(uri, muleEndpointURI.uri);
535     }
536 
537     @Override
538     public int hashCode()
539     {
540         return ClassUtils.hash(new Object[]{
541                 address,
542                 filterAddress,
543                 endpointName,
544                 connectorName,
545                 transformers,
546                 responseTransformers,
547                 params,
548                 uri,
549                 schemeMetaInfo,
550                 resourceInfo
551         });
552     }
553 }