package jetbrains.mps.core.tool.environment.classloading; /*Generated by MPS */ import org.jetbrains.annotations.NonNls; import java.io.PrintStream; import java.util.Stack; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import org.jetbrains.annotations.Nullable; import java.util.List; import java.io.IOException; import java.util.Enumeration; import java.net.URISyntaxException; import java.io.File; import java.util.NoSuchElementException; public class ClassPath { @NonNls private static final String FILE_PROTOCOL = "file"; private static final boolean myDebugTime = false; private static final long NS_THRESHOLD = 10000000L; private static PrintStream ourOrder; private final Stack<URL> myUrls = new Stack<URL>(); private final ArrayList<Loader> myLoaders = new ArrayList<Loader>(); private final HashMap<URL, Loader> myLoadersMap = new HashMap<URL, Loader>(); private final ClasspathCache myCache = new ClasspathCache(); private final boolean myCanLockJars; private final boolean myCanUseCache; private final boolean myAcceptUnescapedUrls; public ClassPath(URL[] urls, boolean canLockJars, boolean canUseCache) { this(urls, canLockJars, canUseCache, false); } public ClassPath(URL[] urls, boolean canLockJars, boolean canUseCache, boolean acceptUnescapedUrls) { this.myCanLockJars = canLockJars; this.myCanUseCache = canUseCache; this.myAcceptUnescapedUrls = acceptUnescapedUrls; push(urls); } public void addURL(URL url) { synchronized (myUrls) { myUrls.push(url); } } private void push(URL[] urls) { synchronized (myUrls) { for (int i = urls.length - 1; i >= 0; i--) { myUrls.push(urls[i]); } } } @Nullable public Resource getResource(String s, boolean flag) { final long started = (ClassPath.myDebugTime ? System.nanoTime() : 0); try { int i; if (myCanUseCache) { final List<Loader> loaders = myCache.getLoaders(s); for (Loader loader : loaders) { final Resource resource = loader.getResource(s, flag); if (resource != null) { // printOrder(loader, s); return resource; } } synchronized (myUrls) { if (myUrls.isEmpty()) { return null; } } i = myLoaders.size(); } else { i = 0; } for (Loader loader; (loader = getLoader(i)) != null; i++) { Resource resource = loader.getResource(s, flag); if (resource != null) { return resource; } } return null; } finally { long doneFor = (ClassPath.myDebugTime ? System.nanoTime() - started : 0); if (doneFor > ClassPath.NS_THRESHOLD) { System.out.println((doneFor / 1000000) + " ms for getResource:" + s + ", flag:" + flag); } } } @Nullable private Loader getLoader(int i) { while (myLoaders.size() < i + 1) { URL url; synchronized (myUrls) { if (myUrls.empty()) { return null; } url = myUrls.pop(); } if (myLoadersMap.containsKey(url)) { continue; } Loader loader; try { loader = getLoader(url); if (loader == null) { continue; } } catch (IOException ioexception) { continue; } myLoaders.add(loader); myLoadersMap.put(url, loader); } return myLoaders.get(i); } public Enumeration<URL> getResources(final String name, final boolean check) { return new ClassPath.MyEnumeration(name, check); } @Nullable private Loader getLoader(final URL url) throws IOException { String s; if (myAcceptUnescapedUrls) { s = url.getFile(); } else { try { s = url.toURI().getSchemeSpecificPart(); } catch (URISyntaxException thisShouldNotHappen) { thisShouldNotHappen.printStackTrace(); s = url.getFile(); } } Loader loader = null; if (s != null && new File(s).isDirectory()) { if (ClassPath.FILE_PROTOCOL.equals(url.getProtocol())) { loader = new FileLoader(url); } } else { loader = new JarLoader(url, myCanLockJars); } if (loader != null && myCanUseCache) { try { loader.buildCache(myCache); } catch (Throwable e) { // TODO: log can't create loader } } return loader; } private class MyEnumeration implements Enumeration<URL> { private int myIndex = 0; private Resource myRes = null; private final String myName; private final boolean myCheck; public MyEnumeration(String name, boolean check) { myName = name; myCheck = check; } private boolean next() { if (myRes != null) { return true; } Loader loader; while ((loader = getLoader(myIndex++)) != null) { myRes = loader.getResource(myName, myCheck); if (myRes != null) { return true; } } return false; } @Override public boolean hasMoreElements() { return next(); } @Override public URL nextElement() { if (!(next())) { throw new NoSuchElementException(); } else { Resource resource = myRes; myRes = null; return resource.getURL(); } } } }