View Javadoc

1   /*
2    * $Id: MuleUrlStreamHandlerFactory.java 7963 2007-08-21 08:53:15Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.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      private static final String HANDLER_PKGS_SYSTEM_PROPERTY = "java.protocol.handler.pkgs";
38      private static final Log log = LogFactory.getLog(MuleUrlStreamHandlerFactory.class);
39      
40      private static Map registry = Collections.synchronizedMap(new HashMap());
41  
42      /**
43       * Install an instance of this class as UrlStreamHandlerFactory. This may be done exactly
44       * once as {@link URL} will throw an {@link Error} on subsequent invocations. 
45       * <p>
46       * This method takes care that multiple invocations are possible, but the 
47       * UrlStreamHandlerFactory is installed only once.
48       */
49      public static synchronized void installUrlStreamHandlerFactory()
50      {
51          /*
52           * When running under surefire, this class will be loaded by different class loaders and
53           * will be running in multiple "main" thread objects. Thus, there is no way for this class
54           * to register a globally available variable to store the info whether our custom 
55           * UrlStreamHandlerFactory was already registered.
56           * 
57           * The only way to accomplish this is to catch the Error that is thrown by URL when
58           * trying to re-register the custom UrlStreamHandlerFactory.
59           */
60          try
61          {
62              URL.setURLStreamHandlerFactory(new MuleUrlStreamHandlerFactory());
63          }
64          catch (Error err)
65          {
66              if (log.isDebugEnabled())
67              {
68                  log.debug("Custom MuleUrlStreamHandlerFactory already registered", err);
69              }
70          }
71      }
72      
73      public static void registerHandler(String protocol, URLStreamHandler handler)
74      {
75          registry.put(protocol, handler);
76      }
77  
78      public URLStreamHandler createURLStreamHandler(String protocol)
79      {
80          URLStreamHandler handler = (URLStreamHandler) registry.get(protocol);
81          if (handler == null)
82          {
83              handler = this.defaultHandlerCreateStrategy(protocol);
84          }
85          return handler;
86      }
87  
88      private URLStreamHandler defaultHandlerCreateStrategy(String protocol)
89      {
90          String packagePrefixList = System.getProperty(HANDLER_PKGS_SYSTEM_PROPERTY, "");
91  
92          if (packagePrefixList.endsWith("|") == false)
93          {
94              packagePrefixList += "|sun.net.www.protocol";
95          }
96  
97          StringTokenizer tokenizer = new StringTokenizer(packagePrefixList, "|");
98  
99          URLStreamHandler handler = null;
100         while (handler == null && tokenizer.hasMoreTokens())
101         {
102             String packagePrefix = tokenizer.nextToken().trim();
103             String className = packagePrefix + "." + protocol + ".Handler";
104             try
105             {
106                 handler = (URLStreamHandler) ClassUtils.instanciateClass(className, null);
107             }
108             catch (Exception ex)
109             {
110                 // not much we can do here
111             }
112         }
113          
114         return handler;
115     }
116 }