blob: 987e1d916ecea8616e56f5f20e7cafe81f434ba4 [file] [log] [blame]
/*
* Copyright 2011 Google Inc.
*
* 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.
*/
package com.google.gwt.dev.cfg;
import static com.google.gwt.thirdparty.guava.common.base.StandardSystemProperty.JAVA_CLASS_PATH;
import com.google.gwt.thirdparty.guava.common.base.Splitter;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
/**
* Creates instances of {@link ResourceLoader}.
*/
public class ResourceLoaders {
private static class ClassLoaderAdapter implements ResourceLoader {
private final ClassLoader wrapped;
public ClassLoaderAdapter(ClassLoader wrapped) {
// TODO(rluble): Maybe stop wrapping arbitrary class loaders here and always use the
// system ClassLoader.
this.wrapped = wrapped;
}
@Override
public boolean equals(Object other) {
if (!(other instanceof ClassLoaderAdapter)) {
return false;
}
ClassLoaderAdapter otherAdapter = (ClassLoaderAdapter) other;
return wrapped.equals(otherAdapter.wrapped);
}
/**
* Returns the URLs for the system class path.
*/
@Override
public List<URL> getClassPath() {
List<URL> result = new ArrayList<URL>();
for (String entry : Splitter.on(File.pathSeparatorChar).split(JAVA_CLASS_PATH.value())) {
try {
result.add(Paths.get(entry).toUri().toURL());
} catch (MalformedURLException e) {
}
}
return result;
}
@Override
public URL getResource(String resourceName) {
return wrapped.getResource(resourceName);
}
@Override
public int hashCode() {
return wrapped.hashCode();
}
}
/**
* A ResourceLoader that prefixes some directories to another ResourceLoader.
*/
private static class PrefixLoader implements ResourceLoader {
private final List<File> path;
private final List<URL> pathAsUrls = new ArrayList<URL>();
private final ResourceLoader fallback;
public PrefixLoader(List<File> path, ResourceLoader fallback) {
assert path != null;
this.path = path;
this.fallback = fallback;
for (File file : path) {
try {
pathAsUrls.add(file.toURI().toURL());
} catch (MalformedURLException e) {
throw new RuntimeException("can't create URL for file: " + file);
}
}
}
@Override
public boolean equals(Object other) {
if (!(other instanceof PrefixLoader)) {
return false;
}
PrefixLoader otherLoader = (PrefixLoader) other;
return path.equals(otherLoader.path) && fallback.equals(otherLoader.fallback);
}
@Override
public List<URL> getClassPath() {
List<URL> result = new ArrayList<URL>();
result.addAll(pathAsUrls);
result.addAll(fallback.getClassPath());
return result;
}
@Override
public URL getResource(String resourceName) {
for (File prefix : path) {
File candidate = new File(prefix, resourceName);
if (candidate.exists()) {
try {
return candidate.toURI().toURL();
} catch (MalformedURLException e) {
return null;
}
}
}
return fallback.getResource(resourceName);
}
@Override
public int hashCode() {
return path.hashCode() ^ fallback.hashCode();
}
}
/**
* Creates a ResourceLoader that loads from the given thread's class loader.
*/
public static ResourceLoader forClassLoader(Thread thread) {
return wrap(thread.getContextClassLoader());
}
/**
* Creates a ResourceLoader that loads from a list of directories and falls back
* to another ResourceLoader.
*/
public static ResourceLoader forPathAndFallback(List<File> path, ResourceLoader fallback) {
return new PrefixLoader(path, fallback);
}
/**
* Adapts a ClassLoader to work as a ResourceLoader.
* (Caveat: any ClassLoader in the chain that isn't a URLClassLoader won't contribute to the
* results of {@link ResourceLoader#getClassPath}.)
*/
public static ResourceLoader wrap(ClassLoader loader) {
return new ClassLoaderAdapter(loader);
}
private ResourceLoaders() {
}
}