001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.xbean.finder; 018 019import org.apache.xbean.finder.util.Files; 020 021import java.io.File; 022import java.io.IOException; 023import java.net.MalformedURLException; 024import java.net.URL; 025import java.net.URLClassLoader; 026import java.util.Arrays; 027import java.util.Collection; 028import java.util.Collections; 029import java.util.HashSet; 030import java.util.Set; 031 032public final class ClassLoaders { 033 private static final boolean DONT_USE_GET_URLS = Boolean.getBoolean("xbean.finder.use.get-resources"); 034 private static final ClassLoader SYSTEM = ClassLoader.getSystemClassLoader(); 035 036 private static final boolean UNIX = !System.getProperty("os.name").toLowerCase().contains("win"); 037 038 public static Set<URL> findUrls(final ClassLoader classLoader) throws IOException { 039 if (classLoader == null || (SYSTEM.getParent() != null && classLoader == SYSTEM.getParent())) { 040 return Collections.emptySet(); 041 } 042 043 final Set<URL> urls = new HashSet<URL>(); 044 045 if (URLClassLoader.class.isInstance(classLoader) && !DONT_USE_GET_URLS) { 046 if (!isSurefire(classLoader)) { 047 for (final Collection<URL> item : Arrays.asList( 048 Arrays.asList(URLClassLoader.class.cast(classLoader).getURLs()), findUrls(classLoader.getParent()))) { 049 for (final URL url : item) { 050 addIfNotSo(urls, url); 051 } 052 } 053 } else { // http://jira.codehaus.org/browse/SUREFIRE-928 - we could reuse findUrlFromResources but this seems faster 054 urls.addAll(fromClassPath()); 055 } 056 } 057 058 // DONT_USE_GET_URLS ||?java -jar xxx.jar and use MANIFEST.MF Class-Path? 059 // here perf is not an issue since we would either miss all the classpath or we have a single jar 060 if (urls.size() <= 1) { 061 urls.addAll(findUrlFromResources(classLoader)); 062 } 063 064 return urls; 065 } 066 067 private static void addIfNotSo(final Set<URL> urls, final URL url) { 068 if (UNIX && isNative(url)) { 069 return; 070 } 071 072 urls.add(url); 073 } 074 075 public static boolean isNative(final URL url) { 076 final File file = Files.toFile(url); 077 if (file != null) { 078 final String name = file.getName(); 079 if (!name.endsWith(".jar") && !file.isDirectory() 080 && name.contains(".so") && file.getAbsolutePath().startsWith("/usr/lib")) { 081 return true; 082 } 083 } 084 return false; 085 } 086 087 088 private static boolean isSurefire(ClassLoader classLoader) { 089 return System.getProperty("surefire.real.class.path") != null && classLoader == SYSTEM; 090 } 091 092 private static Collection<URL> fromClassPath() { 093 final String[] cp = System.getProperty("java.class.path").split(System.getProperty("path.separator", ":")); 094 final Set<URL> urls = new HashSet<URL>(); 095 for (final String path : cp) { 096 try { 097 urls.add(new File(path).toURI().toURL()); // don't build the url in plain String since it is not portable 098 } catch (final MalformedURLException e) { 099 // ignore 100 } 101 } 102 return urls; 103 } 104 105 public static Set<URL> findUrlFromResources(final ClassLoader classLoader) throws IOException { 106 final Set<URL> set = new HashSet<URL>(); 107 for (final URL url : Collections.list(classLoader.getResources("META-INF"))) { 108 final String externalForm = url.toExternalForm(); 109 set.add(new URL(externalForm.substring(0, externalForm.lastIndexOf("META-INF")))); 110 } 111 set.addAll(Collections.list(classLoader.getResources(""))); 112 return set; 113 } 114 115 private ClassLoaders() { 116 // no-op 117 } 118}