package jetbrains.mps.core.tool.environment.classloading; /*Generated by MPS */ import org.jetbrains.annotations.NonNls; import java.lang.reflect.Field; import java.util.HashMap; import org.apache.log4j.Logger; import org.apache.log4j.LogManager; import java.util.List; import java.net.URL; import jetbrains.mps.core.tool.environment.util.PathManager; import java.net.MalformedURLException; import java.util.regex.Pattern; import java.util.Iterator; import java.net.URLClassLoader; import java.util.StringTokenizer; import java.io.File; import java.lang.reflect.InvocationTargetException; import jetbrains.mps.core.tool.environment.common.StringUtil; public class ClassloaderUtil { @NonNls /*package*/ static final String FILE_CACHE = "fileCache"; @NonNls /*package*/ static final String URL_CACHE = "urlCache"; @NonNls public static final String PROPERTY_IGNORE_CLASSPATH = "ignore.classpath"; @SuppressWarnings(value = {"HardCodedStringLiteral"}) private static final String ERROR = "Error"; private static Class[] EMPTY_CLASS_ARRAY = new Class[0]; private ClassloaderUtil() { } public static void clearJarURLCache() { try { // new URLConnection(null) { // public void connect() throws IOException { // throw new UnsupportedOperationException(); // } // }.setDefaultUseCaches(false); Class jarFileFactory = Class.forName("sun.net.www.protocol.jar.JarFileFactory"); Field fileCache = jarFileFactory.getDeclaredField(ClassloaderUtil.FILE_CACHE); Field urlCache = jarFileFactory.getDeclaredField(ClassloaderUtil.URL_CACHE); fileCache.setAccessible(true); fileCache.set(null, new HashMap()); urlCache.setAccessible(true); urlCache.set(null, new HashMap()); } catch (Exception e) { System.err.println("Failed to clear URL cache"); // Do nothing. } } public static Logger getLogger() { return LogManager.getLogger("ClassloaderUtil"); } public static UrlClassLoader initClassloader(final List<URL> classpathElements) { PathManager.loadProperties(); try { ClassloaderUtil.addParentClasspath(classpathElements); ClassloaderUtil.addIDEALibraries(classpathElements); ClassloaderUtil.addAdditionalClassPath(classpathElements); } catch (IllegalArgumentException e) { ClassloaderUtil.getLogger().error(null, e); System.exit(1); } catch (MalformedURLException e) { ClassloaderUtil.getLogger().error(e.getMessage()); System.exit(1); } ClassloaderUtil.filterClassPath(classpathElements); UrlClassLoader newClassLoader = null; try { newClassLoader = new UrlClassLoader(classpathElements, null, true, true); // prepare plugins Thread.currentThread().setContextClassLoader(newClassLoader); } catch (Exception e) { Logger logger = ClassloaderUtil.getLogger(); if (logger == null) { e.printStackTrace(System.err); } else { logger.error(null, e); } } return newClassLoader; } public static void filterClassPath(final List<URL> classpathElements) { final String ignoreProperty = System.getProperty(ClassloaderUtil.PROPERTY_IGNORE_CLASSPATH); if (ignoreProperty == null) { return; } final Pattern pattern = Pattern.compile(ignoreProperty); for (Iterator<URL> i = classpathElements.iterator(); i.hasNext();) { URL url = i.next(); final String u = url.toExternalForm(); if (pattern.matcher(u).matches()) { i.remove(); } } } public static void addParentClasspath(List<URL> aClasspathElements) throws MalformedURLException { final ClassLoader loader = ClassloaderUtil.class.getClassLoader(); if (loader instanceof URLClassLoader) { URLClassLoader urlClassLoader = (URLClassLoader) loader; ContainerUtil.addAll(aClasspathElements, urlClassLoader.getURLs()); } else { try { Class antClassLoaderClass = Class.forName("org.apache.tools.ant.AntClassLoader"); if (antClassLoaderClass.isInstance(loader) || loader.getClass().getName().equals("org.apache.tools.ant.AntClassLoader") || loader.getClass().getName().equals("org.apache.tools.ant.loader.AntClassLoader2")) { // noinspection HardCodedStringLiteral final String classpath = (String) antClassLoaderClass.getDeclaredMethod("getClasspath", ClassloaderUtil.EMPTY_CLASS_ARRAY).invoke(loader, ClassloaderUtil.EMPTY_CLASS_ARRAY); final StringTokenizer tokenizer = new StringTokenizer(classpath, File.separator, false); while (tokenizer.hasMoreTokens()) { final String token = tokenizer.nextToken(); aClasspathElements.add(new File(token).toURI().toURL()); } } else { ClassloaderUtil.getLogger().warn("Unknown classloader: " + loader.getClass().getName()); } } catch (ClassCastException e) { ClassloaderUtil.getLogger().warn("Unknown classloader [CCE]: " + e.getMessage()); } catch (ClassNotFoundException e) { ClassloaderUtil.getLogger().warn("Unknown classloader [CNFE]: " + loader.getClass().getName()); } catch (NoSuchMethodException e) { ClassloaderUtil.getLogger().warn("Unknown classloader [NSME]: " + e.getMessage()); } catch (IllegalAccessException e) { ClassloaderUtil.getLogger().warn("Unknown classloader [IAE]: " + e.getMessage()); } catch (InvocationTargetException e) { ClassloaderUtil.getLogger().warn("Unknown classloader [ITE]: " + e.getMessage()); } } } public static void addIDEALibraries(List<URL> classpathElements) { final String ideaHomePath = PathManager.getHomePath(); ClassloaderUtil.addAllFromLibFolder(ideaHomePath, classpathElements); } @SuppressWarnings(value = {"HardCodedStringLiteral"}) public static void addAllFromLibFolder(final String aFolderPath, List<URL> classPath) { try { final Class<ClassloaderUtil> aClass = ClassloaderUtil.class; final String selfRoot = PathManager.getResourceRoot(aClass, "/" + aClass.getName().replace('.', '/') + ".class"); final URL selfRootUrl = new File(selfRoot).getAbsoluteFile().toURI().toURL(); classPath.add(selfRootUrl); final File libFolder = new File(aFolderPath + File.separator + "lib"); ClassloaderUtil.addLibraries(classPath, libFolder, selfRootUrl); final File extLib = new File(libFolder, "ext"); ClassloaderUtil.addLibraries(classPath, extLib, selfRootUrl); final File antLib = new File(new File(libFolder, "ant"), "lib"); ClassloaderUtil.addLibraries(classPath, antLib, selfRootUrl); } catch (MalformedURLException e) { ClassloaderUtil.getLogger().error(null, e); } } public static void addLibraries(List<URL> classPath, File fromDir, final URL selfRootUrl) throws MalformedURLException { final File[] files = fromDir.listFiles(); if (files != null) { for (final File file : files) { if (!(ClassloaderUtil.isJarOrZip(file))) { continue; } final URL url = file.toURI().toURL(); if (selfRootUrl.equals(url)) { continue; } classPath.add(url); } } } @SuppressWarnings(value = {"HardCodedStringLiteral"}) public static boolean isJarOrZip(File file) { if (file.isDirectory()) { return false; } final String name = file.getName(); return StringUtil.endsWithIgnoreCase(name, ".jar") || StringUtil.endsWithIgnoreCase(name, ".zip"); } public static void addAdditionalClassPath(List<URL> classPath) { try { // noinspection HardCodedStringLiteral final StringTokenizer tokenizer = new StringTokenizer(System.getProperty("idea.additional.classpath", ""), File.pathSeparator, false); while (tokenizer.hasMoreTokens()) { String pathItem = tokenizer.nextToken(); classPath.add(new File(pathItem).toURI().toURL()); } } catch (MalformedURLException e) { ClassloaderUtil.getLogger().error(null, e); } } @SuppressWarnings(value = {"HardCodedStringLiteral"}) public static boolean isLoadingOfExternalPluginsDisabled() { return !("true".equalsIgnoreCase(System.getProperty("idea.plugins.load", "true"))); } }