blob: 569e208e8b9febc77f517cba75a5c4b79fbe6593 [file] [log] [blame]
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* @author max
*/
package com.intellij.ide;
import com.intellij.ide.startup.StartupActionScriptManager;
import com.intellij.idea.Main;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.lang.UrlClassLoader;
import com.intellij.util.text.StringTokenizer;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
@SuppressWarnings({"HardCodedStringLiteral"})
public class BootstrapClassLoaderUtil extends ClassUtilCore {
private static final String PROPERTY_IGNORE_CLASSPATH = "ignore.classpath";
private static final String PROPERTY_ALLOW_BOOTSTRAP_RESOURCES = "idea.allow.bootstrap.resources";
private static final String PROPERTY_ADDITIONAL_CLASSPATH = "idea.additional.classpath";
private BootstrapClassLoaderUtil() { }
private static Logger getLogger() {
return Logger.getInstance(BootstrapClassLoaderUtil.class);
}
@NotNull
public static UrlClassLoader initClassLoader(boolean updatePlugins) throws Exception {
PathManager.loadProperties();
List<URL> classpath = new ArrayList<URL>();
addParentClasspath(classpath);
addIDEALibraries(classpath);
addAdditionalClassPath(classpath);
UrlClassLoader.Builder builder = UrlClassLoader.build()
.urls(filterClassPath(classpath))
.allowLock().useCache();
if (Boolean.valueOf(System.getProperty(PROPERTY_ALLOW_BOOTSTRAP_RESOURCES, "true"))) {
builder.allowBootstrapResources();
}
UrlClassLoader newClassLoader = builder.get();
// prepare plugins
if (updatePlugins && !isLoadingOfExternalPluginsDisabled()) {
try {
StartupActionScriptManager.executeActionScript();
}
catch (IOException e) {
Main.showMessage("Plugin Installation Error", e);
}
}
Thread.currentThread().setContextClassLoader(newClassLoader);
return newClassLoader;
}
private static List<URL> filterClassPath(List<URL> classpathElements) {
String ignoreProperty = System.getProperty(PROPERTY_IGNORE_CLASSPATH);
if (ignoreProperty != null) {
Pattern pattern = Pattern.compile(ignoreProperty);
for (Iterator<URL> i = classpathElements.iterator(); i.hasNext(); ) {
String url = i.next().toExternalForm();
if (pattern.matcher(url).matches()) {
i.remove();
}
}
}
return classpathElements;
}
private static void addParentClasspath(List<URL> aClasspathElements) throws MalformedURLException {
ClassLoader loader = BootstrapClassLoaderUtil.class.getClassLoader();
if (loader instanceof URLClassLoader) {
URLClassLoader urlClassLoader = (URLClassLoader)loader;
ContainerUtil.addAll(aClasspathElements, urlClassLoader.getURLs());
}
else {
String loaderName = loader.getClass().getName();
try {
Class<?> antClassLoaderClass = Class.forName("org.apache.tools.ant.AntClassLoader");
if (antClassLoaderClass.isInstance(loader) ||
"org.apache.tools.ant.AntClassLoader".equals(loaderName) || "org.apache.tools.ant.loader.AntClassLoader2".equals(loaderName)) {
String classpath = (String)antClassLoaderClass
.getDeclaredMethod("getClasspath", ArrayUtil.EMPTY_CLASS_ARRAY)
.invoke(loader, ArrayUtil.EMPTY_OBJECT_ARRAY);
StringTokenizer tokenizer = new StringTokenizer(classpath, File.separator, false);
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
aClasspathElements.add(new File(token).toURI().toURL());
}
}
else {
getLogger().warn("Unknown class loader: " + loaderName);
}
}
catch (ClassCastException e) {
logException(loaderName, e);
}
catch (ClassNotFoundException e) {
logException(loaderName, e);
}
catch (NoSuchMethodException e) {
logException(loaderName, e);
}
catch (IllegalAccessException e) {
logException(loaderName, e);
}
catch (InvocationTargetException e) {
logException(loaderName, e);
}
}
}
private static void logException(String loaderName, Exception e) {
getLogger().warn("Unknown class loader '" + loaderName + "'", e);
}
private static void addIDEALibraries(List<URL> classpathElements) {
final String ideaHomePath = PathManager.getHomePath();
addAllFromLibFolder(ideaHomePath, classpathElements);
}
private static void addAllFromLibFolder(String folderPath, List<URL> classPath) {
try {
Class<BootstrapClassLoaderUtil> aClass = BootstrapClassLoaderUtil.class;
String selfRoot = PathManager.getResourceRoot(aClass, "/" + aClass.getName().replace('.', '/') + ".class");
assert selfRoot != null;
URL selfRootUrl = new File(selfRoot).getAbsoluteFile().toURI().toURL();
classPath.add(selfRootUrl);
File libFolder = new File(folderPath + File.separator + "lib");
addLibraries(classPath, libFolder, selfRootUrl);
File extLib = new File(libFolder, "ext");
addLibraries(classPath, extLib, selfRootUrl);
File antLib = new File(new File(libFolder, "ant"), "lib");
addLibraries(classPath, antLib, selfRootUrl);
}
catch (MalformedURLException e) {
getLogger().error(e);
}
}
private static void addLibraries(List<URL> classPath, File fromDir, URL selfRootUrl) throws MalformedURLException {
File[] files = fromDir.listFiles();
if (files == null) return;
for (File file : files) {
if (FileUtil.isJarOrZip(file)) {
URL url = file.toURI().toURL();
if (!selfRootUrl.equals(url)) {
classPath.add(url);
}
}
}
}
private static void addAdditionalClassPath(List<URL> classPath) {
try {
StringTokenizer tokenizer = new StringTokenizer(System.getProperty(PROPERTY_ADDITIONAL_CLASSPATH, ""), File.pathSeparator, false);
while (tokenizer.hasMoreTokens()) {
String pathItem = tokenizer.nextToken();
classPath.add(new File(pathItem).toURI().toURL());
}
}
catch (MalformedURLException e) {
getLogger().error(e);
}
}
}