View Javadoc

1   /*
2    * $Id: MuleUrlStreamHandlerFactory.java 19191 2010-08-25 21:05:23Z tcarlson $
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.util;
12  
13  import java.net.URL;
14  import java.net.URLStreamHandler;
15  import java.net.URLStreamHandlerFactory;
16  import java.util.Collections;
17  import java.util.HashMap;
18  import java.util.Map;
19  import java.util.StringTokenizer;
20  
21  import org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  
24  /**
25   * A factory for loading URL protocol handlers. This factory is necessary to make
26   * Mule work in cases where the standard approach using system properties does not
27   * work, e.g. in application servers or with maven's surefire tests.
28   * <p>
29   * Client classes can register a subclass of {@link URLStreamHandler} for a given
30   * protocol. This implementation first checks its registered handlers before
31   * resorting to the default mechanism.
32   * <p>
33   * @see java.net.URL#URL(String, String, int, String)
34   */
35  public class MuleUrlStreamHandlerFactory extends Object implements URLStreamHandlerFactory
36  {
37      
38      private static final String HANDLER_PKGS_SYSTEM_PROPERTY = "java.protocol.handler.pkgs";
39      private static final Log log = LogFactory.getLog(MuleUrlStreamHandlerFactory.class);
40      
41      private static Map registry = Collections.synchronizedMap(new HashMap());
42  
43      /**
44       * Install an instance of this class as UrlStreamHandlerFactory. This may be done exactly
45       * once as {@link URL} will throw an {@link Error} on subsequent invocations. 
46       * <p>
47       * This method takes care that multiple invocations are possible, but the 
48       * UrlStreamHandlerFactory is installed only once.
49       */
50      public static synchronized void installUrlStreamHandlerFactory()
51      {
52          /*
53           * When running under surefire, this class will be loaded by different class loaders and
54           * will be running in multiple "main" thread objects. Thus, there is no way for this class
55           * to register a globally available variable to store the info whether our custom 
56           * UrlStreamHandlerFactory was already registered.
57           * 
58           * The only way to accomplish this is to catch the Error that is thrown by URL when
59           * trying to re-register the custom UrlStreamHandlerFactory.
60           */
61          try
62          {
63              URL.setURLStreamHandlerFactory(new MuleUrlStreamHandlerFactory());
64          }
65          catch (Error err)
66          {
67              if (log.isDebugEnabled())
68              {
69                  log.debug("Custom MuleUrlStreamHandlerFactory already registered", err);
70              }
71          }
72      }
73      
74      public static void registerHandler(String protocol, URLStreamHandler handler)
75      {
76          registry.put(protocol, handler);
77      }
78  
79      public URLStreamHandler createURLStreamHandler(String protocol)
80      {
81          URLStreamHandler handler = (URLStreamHandler) registry.get(protocol);
82          if (handler == null)
83          {
84              handler = this.defaultHandlerCreateStrategy(protocol);
85          }
86          return handler;
87      }
88  
89      private URLStreamHandler defaultHandlerCreateStrategy(String protocol)
90      {
91          String packagePrefixList = System.getProperty(HANDLER_PKGS_SYSTEM_PROPERTY, "");
92  
93          if (packagePrefixList.endsWith("|") == false)
94          {
95              packagePrefixList += "|sun.net.www.protocol";
96          }
97  
98          StringTokenizer tokenizer = new StringTokenizer(packagePrefixList, "|");
99  
100         URLStreamHandler handler = null;
101         while (handler == null && tokenizer.hasMoreTokens())
102         {
103             String packagePrefix = tokenizer.nextToken().trim();
104             String className = packagePrefix + "." + protocol + ".Handler";
105             try
106             {
107                 handler = (URLStreamHandler) ClassUtils.instanciateClass(className);
108             }
109             catch (Exception ex)
110             {
111                 // not much we can do here
112             }
113         }
114          
115         return handler;
116     }
117 }