1 22 package org.jboss.virtual.spi; 23 24 import java.io.BufferedReader ; 25 import java.io.IOException ; 26 import java.io.InputStream ; 27 import java.io.InputStreamReader ; 28 import java.net.URI ; 29 import java.net.URL ; 30 import java.security.AccessController ; 31 import java.security.PrivilegedAction ; 32 import java.util.ArrayList ; 33 import java.util.Arrays ; 34 import java.util.Enumeration ; 35 import java.util.Map ; 36 import java.util.StringTokenizer ; 37 import java.util.concurrent.ConcurrentHashMap ; 38 39 import org.jboss.logging.Logger; 40 import org.jboss.virtual.plugins.context.file.FileSystemContextFactory; 41 import org.jboss.virtual.plugins.context.jar.JarContextFactory; 42 43 50 public class VFSContextFactoryLocator 51 { 52 53 private static final Logger log = Logger.getLogger(VFSContextFactoryLocator.class); 54 55 56 private static final Map <String , VFSContextFactory> factoryByProtocol = new ConcurrentHashMap <String , VFSContextFactory>(); 57 58 59 public static final String DEFAULT_FACTORY_PROPERTY = VFSContextFactory.class.getName(); 60 61 62 public static final String SERVICES_PATH = "META-INF/services/" + VFSContextFactory.class.getName(); 63 64 65 private static boolean initialized; 66 67 75 public synchronized static void registerFactory(VFSContextFactory factory) 76 { 77 if (factory == null) 78 throw new IllegalArgumentException ("Null VFSContextFactory"); 79 80 String [] protocols = factory.getProtocols(); 81 if (protocols == null || protocols.length == 0) 82 throw new IllegalArgumentException ("VFSContextFactory trying to register null or no protocols: " + factory); 83 84 for (String protocol : protocols) 85 { 86 if (protocol == null) 87 throw new IllegalArgumentException ("VFSContextFactory try to register a null protocol: " + factory + " protocols=" + Arrays.asList(protocols)); 88 VFSContextFactory other = factoryByProtocol.get(protocol); 89 if (other != null) 90 throw new IllegalStateException ("VFSContextFactory: " + other + " already registered for protocol: " + protocol); 91 } 92 93 boolean trace = log.isTraceEnabled(); 94 for (String protocol : protocols) 95 { 96 factoryByProtocol.put(protocol, factory); 97 if (trace) 98 log.trace("Registered " + factory + " for protocol: " + protocol); 99 } 100 } 101 102 109 public synchronized static boolean unregisterFactory(VFSContextFactory factory) 110 { 111 if (factory == null) 112 throw new IllegalArgumentException ("Null VFSContextFactory"); 113 114 ArrayList <String > protocols = new ArrayList <String >(); 115 for (Map.Entry <String , VFSContextFactory> entry : factoryByProtocol.entrySet()) 116 { 117 if (factory == entry.getValue()) 118 protocols.add(entry.getKey()); 119 } 120 121 boolean trace = log.isTraceEnabled(); 122 for (String protocol : protocols) 123 { 124 factoryByProtocol.remove(protocol); 125 if (trace) 126 log.trace("Unregistered " + factory + " for protocol: " + protocol); 127 } 128 129 return protocols.isEmpty() == false; 130 } 131 132 140 public static VFSContextFactory getFactory(URL rootURL) 141 { 142 if (rootURL == null) 143 throw new IllegalArgumentException ("Null rootURL"); 144 145 init(); 146 String protocol = rootURL.getProtocol(); 147 return factoryByProtocol.get(protocol); 148 } 149 157 public static VFSContextFactory getFactory(URI rootURI) 158 { 159 if (rootURI == null) 160 throw new IllegalArgumentException ("Null rootURI"); 161 162 init(); 163 String scheme = rootURI.getScheme(); 164 return factoryByProtocol.get(scheme); 165 } 166 167 177 private static synchronized void init() 178 { 179 if (initialized) 181 return; 182 183 ClassLoader loader = AccessController.doPrivileged(new GetContextClassLoader()); 185 Enumeration <URL > urls = AccessController.doPrivileged(new EnumerateServices()); 186 if (urls != null) 187 { 188 while (urls.hasMoreElements()) 189 { 190 URL url = urls.nextElement(); 191 192 VFSContextFactory[] factories = loadFactories(url, loader); 193 for (VFSContextFactory factory : factories) 194 { 195 try 196 { 197 registerFactory(factory); 198 } 199 catch (Exception e) 200 { 201 log.warn("Error registering factory from " + url, e); 202 } 203 } 204 } 205 } 206 207 String defaultFactoryNames = AccessController.doPrivileged(new GetDefaultFactories()); 208 if (defaultFactoryNames != null) 209 { 210 StringTokenizer tokenizer = new StringTokenizer (defaultFactoryNames, ","); 211 while (tokenizer.hasMoreTokens()) 212 { 213 String factoryName = tokenizer.nextToken(); 214 VFSContextFactory factory = createVFSContextFactory(loader, factoryName, " from system property."); 215 if (factory != null) 216 registerFactory(factory); 217 } 218 } 219 220 if (factoryByProtocol.containsKey("file") == false) 222 registerFactory(new FileSystemContextFactory()); 223 224 if (factoryByProtocol.containsKey("jar") == false) 226 registerFactory(new JarContextFactory()); 227 228 initialized = true; 229 } 230 231 239 private static VFSContextFactory[] loadFactories(URL serviceURL, ClassLoader loader) 240 { 241 ArrayList <VFSContextFactory> temp = new ArrayList <VFSContextFactory>(); 242 try 243 { 244 InputStream is = serviceURL.openStream(); 245 try 246 { 247 BufferedReader br = new BufferedReader (new InputStreamReader (is)); 248 String line; 249 while ( (line = br.readLine()) != null ) 250 { 251 if (line.startsWith("#") == true) 252 continue; 253 String [] classes = line.split("\\s+|#.*"); 254 for (int n = 0; n < classes.length; n ++) 255 { 256 String name = classes[n]; 257 if (name.length() == 0) 258 continue; 259 VFSContextFactory factory = createVFSContextFactory(loader, name, " defined in " + serviceURL); 260 if (factory != null) 261 temp.add(factory); 262 } 263 } 264 } 265 finally 266 { 267 is.close(); 268 } 269 } 270 catch(Exception e) 271 { 272 log.warn("Error parsing " + serviceURL, e); 273 } 274 275 VFSContextFactory[] factories = new VFSContextFactory[temp.size()]; 276 return temp.toArray(factories); 277 } 278 279 286 private static VFSContextFactory createVFSContextFactory(ClassLoader cl, String className, String context) 287 { 288 try 289 { 290 Class factoryClass = cl.loadClass(className); 291 return (VFSContextFactory) factoryClass.newInstance(); 292 } 293 catch (Exception e) 294 { 295 log.warn("Error creating VFSContextFactory " + className + " " + context, e); 296 return null; 297 } 298 } 299 300 303 private static class GetContextClassLoader implements PrivilegedAction <ClassLoader > 304 { 305 public ClassLoader run() 306 { 307 return Thread.currentThread().getContextClassLoader(); 308 } 309 } 310 311 314 private static class GetDefaultFactories implements PrivilegedAction <String > 315 { 316 public String run() 317 { 318 return System.getProperty(DEFAULT_FACTORY_PROPERTY); 319 } 320 } 321 322 325 private static class EnumerateServices implements PrivilegedAction <Enumeration <URL >> 326 { 327 public Enumeration <URL > run() 328 { 329 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 330 try 331 { 332 return cl.getResources(SERVICES_PATH); 333 } 334 catch (IOException e) 335 { 336 log.warn("Error retrieving " + SERVICES_PATH, e); 337 return null; 338 } 339 } 340 } 341 } 342 | Popular Tags |