View Javadoc

1   /*
2    * $Id: MuleEndpointURI.java 21109 2011-01-26 07:39:00Z dirk.olmes $
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   * recognized 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 uriString, String startChar)
164     {
165         //Allow Expressions to be embedded
166         int uriLength = uriString.length();
167         for (int index = 0; index < uriLength; )
168         {
169             index = uriString.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 = uriString.charAt(seek);
178                 if (c == '{')
179                 {
180                     braceCount++;
181                 }
182                 else if (c == '}')
183                 {
184                     if (--braceCount == 0)
185                     {
186                         uriString = uriString.substring(0, index) + startChar + "[" + uriString.substring(index + 2, seek) + "]" + uriString.substring(seek+1);
187                         break;
188                     }
189                 }
190             }
191             index += 2;
192         }
193         return uriString;
194     }
195 
196     protected String preprocessUri(String uriString) throws MalformedEndpointException
197     {
198         uriString = uriString.trim().replaceAll(" ", "%20");
199         if (!validateUrl(uriString))
200         {
201             throw new MalformedEndpointException(uriString);
202         }
203         schemeMetaInfo = retrieveSchemeMetaInfo(uriString);
204         if (schemeMetaInfo != null)
205         {
206             uriString = uriString.replaceFirst(schemeMetaInfo + ":", "");
207         }
208         return uriString;
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             return createUriStringWithPasswordMasked();
432         }
433         return uri.toASCIIString();
434     }
435 
436     protected String createUriStringWithPasswordMasked()
437     {
438         String rawUserInfo =  uri.getRawUserInfo();
439         // uri.getRawUserInfo() returns null for JMS endpoints with passwords, so use the userInfo
440         // from this instance instead
441         if (StringUtils.isBlank(rawUserInfo))
442         {
443             rawUserInfo = userInfo;
444         }
445 
446         String maskedUserInfo = null;
447         int index = rawUserInfo.indexOf(":");
448         if (index > -1)
449         {
450             maskedUserInfo = rawUserInfo.substring(0, index);
451         }
452 
453         maskedUserInfo = maskedUserInfo + ":****";
454         return uri.toASCIIString().replace(rawUserInfo, maskedUserInfo);
455     }
456 
457     public String getTransformers()
458     {
459         return transformers;
460     }
461 
462     public URI getUri()
463     {
464         return uri;
465     }
466 
467     public String getConnectorName()
468     {
469         return connectorName;
470     }
471 
472     public String getSchemeMetaInfo()
473     {
474         return (schemeMetaInfo == null ? uri.getScheme() : schemeMetaInfo);
475     }
476 
477     public String getResourceInfo()
478     {
479         return resourceInfo;
480     }
481 
482     public String getFilterAddress()
483     {
484         return filterAddress;
485     }
486 
487     public String getUser()
488     {
489         if (StringUtils.isNotBlank(userInfo))
490         {
491             int i = userInfo.indexOf(':');
492             if (i == -1)
493             {
494                 return userInfo;
495             }
496             else
497             {
498                 return userInfo.substring(0, i);
499             }
500         }
501         return null;
502     }
503 
504     public String getResponseTransformers()
505     {
506         return responseTransformers;
507     }
508 
509     public String getPassword()
510     {
511         if (StringUtils.isNotBlank(userInfo))
512         {
513             int i = userInfo.indexOf(':');
514             if (i > -1)
515             {
516                 return userInfo.substring(i + 1);
517             }
518         }
519         return null;
520     }
521 
522     public MuleContext getMuleContext()
523     {
524         return muleContext;
525     }
526 
527     public boolean isDynamic()
528     {
529         return dynamic;
530     }
531 
532     @Override
533     public boolean equals(Object o)
534     {
535         if (this == o)
536         {
537             return true;
538         }
539         if (!(o instanceof MuleEndpointURI))
540         {
541             return false;
542         }
543         MuleEndpointURI muleEndpointURI = (MuleEndpointURI) o;
544         return ClassUtils.equal(address, muleEndpointURI.address) &&
545                 ClassUtils.equal(connectorName, muleEndpointURI.connectorName) &&
546                 ClassUtils.equal(endpointName, muleEndpointURI.endpointName) &&
547                 ClassUtils.equal(filterAddress, muleEndpointURI.filterAddress) &&
548                 ClassUtils.equal(params, muleEndpointURI.params) &&
549                 ClassUtils.equal(resourceInfo, muleEndpointURI.resourceInfo) &&
550                 ClassUtils.equal(schemeMetaInfo, muleEndpointURI.schemeMetaInfo) &&
551                 ClassUtils.equal(transformers, muleEndpointURI.transformers) &&
552                 ClassUtils.equal(responseTransformers, muleEndpointURI.responseTransformers) &&
553                 ClassUtils.equal(uri, muleEndpointURI.uri);
554     }
555 
556     @Override
557     public int hashCode()
558     {
559         return ClassUtils.hash(new Object[]{
560                 address,
561                 filterAddress,
562                 endpointName,
563                 connectorName,
564                 transformers,
565                 responseTransformers,
566                 params,
567                 uri,
568                 schemeMetaInfo,
569                 resourceInfo
570         });
571     }
572 }