Skip to content

Commit

Permalink
fix merge
Browse files Browse the repository at this point in the history
  • Loading branch information
rpau committed Apr 17, 2018
2 parents 465cde0 + fb3d67d commit 4436022
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 120 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.walkmod.javalang.compiler.types;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.AllPermission;
Expand All @@ -10,11 +12,8 @@
import java.security.Permissions;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;
import java.util.Enumeration;
import java.util.List;

import sun.misc.Resource;


/**
* A custom ClassLoader that indexes the contents of classpath elements, for faster class locating.
Expand Down Expand Up @@ -44,11 +43,11 @@ public IndexedURLClassLoader(URL[] urls, ClassLoader parent) {
}

public List<String> getPackageClasses(String packageName) {
return ucp.listPackageContents(packageName,false);
return ucp.listPackageContents(packageName);
}

public List<String> getSDKContents(String packageName) {
return ucp.listSDKContents(packageName,false);
return ucp.listSDKContents(packageName);
}

private static URL[] getClassPathURLs() {
Expand All @@ -66,14 +65,14 @@ private static URL[] getClassPathURLs() {

@Override
public URL findResource(String name) {
return ucp.findResource(name, false);
return ucp.findResource(name);
}

@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
String path = name.replace('.', '/').concat(".class");
Resource res = ucp.getResource(path);
URL res = ucp.findResource(path);
if (res != null) {
int i = name.lastIndexOf('.');
if (i != -1) {
Expand All @@ -84,35 +83,34 @@ protected Class<?> findClass(String name) throws ClassNotFoundException {
definePackage(pkgname, null, null, null, null, null, null, null);
}
}
byte[] data = res.getBytes();
byte[] data = loadResource(res);
// Add a CodeSource via a ProtectionDomain, as code may use this to find its own jars.
CodeSource cs = new CodeSource(res.getCodeSourceURL(), (Certificate[])null);
CodeSource cs = new CodeSource(res, (Certificate[])null);
PermissionCollection pc = new Permissions();
pc.add(new AllPermission());
ProtectionDomain pd = new ProtectionDomain(cs, pc);
return defineClass(name, data, 0, data.length, pd);
} else {
throw new ClassNotFoundException(String.format("IndexedURLClassLoader can't find class %s", name));
throw new ClassNotFoundException(String.format("IndexedURLClassLoader failed to read class %s", name));
}
} catch (IOException e) {
throw new ClassNotFoundException(String.format("IndexedURLClassLoader failed to read class %s", name), e);
}
}

@Override
public Enumeration<URL> findResources(final String name) throws IOException {
final Enumeration e = ucp.findResources(name, true);

return new Enumeration<URL>() {
public URL nextElement() {
return (URL)e.nextElement();
}
private byte[] loadResource(URL toDownload) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

public boolean hasMoreElements() {
return e.hasMoreElements();
byte[] chunk = new byte[4096];
int bytesRead;
InputStream stream = toDownload.openStream();
try {
while ((bytesRead = stream.read(chunk)) > 0) {
outputStream.write(chunk, 0, bytesRead);
}
};
} finally {
stream.close();
}
return outputStream.toByteArray();
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,24 @@
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import sun.misc.Resource;
import sun.misc.URLClassPath;

/**
* A modified URLClassPath that indexes the contents of classpath elements, for faster resource locating.
*
* The standard URLClassPath does a linear scan of the classpath for each resource, which becomes
* prohibitively expensive for classpaths with many elements.
*/
public class IndexedURLClassPath extends URLClassPath {
public class IndexedURLClassPath {

private URL[] urls;
private final URL[] urls;
private int lastIndexed = 0;
private static final URL RT_JAR;

private static URL RT_JAR;
// Map from resource name to URLClassPath to delegate loading that resource to.
private final PathTree<URL> index = new PathTree<URL>();

static {

Expand All @@ -44,41 +43,30 @@ public class IndexedURLClassPath extends URLClassPath {
RT_JAR = foundJar;
}

public IndexedURLClassPath(URL[] urls) {
super(urls);
public IndexedURLClassPath(final URL[] urls) {
this.urls = urls;
}

@Override
public Resource getResource(final String name, boolean check) {
URLClassPath delegate = index.get(name);
if (delegate == null) {
if (lastIndexed < urls.length) {
indexURLs(urls[lastIndexed]);
lastIndexed ++;
return getResource(name, check);
}
return null;
}
return delegate.getResource(name, check);
}

@Override
public URL findResource(final String name, boolean check) {
URLClassPath delegate = index.get(name);
public URL findResource(final String name) {
URL delegate = index.get(name);
if (delegate == null) {
if (lastIndexed < urls.length) {
indexURLs(urls[lastIndexed]);
lastIndexed ++;
return findResource(name, check);
return findResource(name);
}
return null;
}
return delegate.findResource(name, check);
try {
return new URL(delegate, name);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}


public List<String> listPackageContents(final String packageName, boolean check) {
public List<String> listPackageContents(final String packageName) {

String packageFile = packageName.replaceAll("\\.", File.separator);
while (lastIndexed < urls.length) {
Expand All @@ -88,7 +76,7 @@ public List<String> listPackageContents(final String packageName, boolean check)
return index.list(packageFile);
}

public List<String> listSDKContents(final String packageName, boolean check) {
public List<String> listSDKContents(final String packageName) {
String packageFile = packageName.replaceAll("\\.", File.separator);
indexURLs(RT_JAR);
return index.list(packageFile);
Expand All @@ -101,23 +89,21 @@ private void indexURLs(URL url) {
throw new RuntimeException("Classpath element is not a file: " + url);
}
File root = new File(url.getPath());
URL[] args = {url};
URLClassPath delegate = new URLClassPath(args);

if (root.isDirectory()) {
String rootPath = root.getPath();
if (!rootPath.endsWith(File.separator)) {
rootPath = rootPath + File.separator;
}
addFilesToIndex(rootPath.length(), root, delegate);
addFilesToIndex(rootPath.length(), root, url);
} else if (root.isFile() && root.getName().endsWith(".jar")) {
JarFile jarFile = new JarFile(root);
try {
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String name = entry.getName();
maybeIndexResource(name, delegate);
maybeIndexResource(name, url);
}
} finally {
jarFile.close();
Expand All @@ -128,14 +114,17 @@ private void indexURLs(URL url) {
}
}

private void addFilesToIndex(int basePrefixLen, File f, URLClassPath delegate) throws IOException {
private void addFilesToIndex(int basePrefixLen, File f, URL delegate) throws IOException {
if (f.isDirectory()) {
if (f.getPath().length() > basePrefixLen) { // Don't index the root itself.
String relPath = f.getPath().substring(basePrefixLen);
maybeIndexResource(relPath, delegate);
}
File[] directoryEntries = f.listFiles();
assert(directoryEntries != null);

if (directoryEntries == null) {
throw new RuntimeException("The list of directories of " + f.getAbsolutePath() + " is null");
}
for (int i = 0; i < directoryEntries.length; ++i) {
addFilesToIndex(basePrefixLen, directoryEntries[i], delegate);
}
Expand All @@ -145,20 +134,24 @@ private void addFilesToIndex(int basePrefixLen, File f, URLClassPath delegate) t
}
}

private void maybeIndexResource(String relPath, URLClassPath delegate) {
public URL[] getURLs() {
return urls;
}

/**
* Callers may request the directory itself as a resource, and may
* do so with or without trailing slashes. We do this in a while-loop
* in case the classpath element has multiple superfluous trailing slashes.
* @param relPath relative path
* @param delegate value to insert
*/
private void maybeIndexResource(String relPath, URL delegate) {

if (!index.containsKey(relPath)) {
index.put(relPath, delegate);
// Callers may request the directory itself as a resource, and may
// do so with or without trailing slashes. We do this in a while-loop
// in case the classpath element has multiple superfluous trailing slashes.
if (relPath.endsWith(File.separator)) {
maybeIndexResource(relPath.substring(0, relPath.length() - File.separator.length()), delegate);
}
}
}


// Map from resource name to URLClassPath to delegate loading that resource to.
private final ClassPathTree index = new ClassPathTree("/", "/", new HashMap<String, ClassPathTree>(), null);
}
Loading

0 comments on commit 4436022

Please sign in to comment.