1.1 --- a/dew/src/main/java/org/apidesign/bck2brwsr/dew/ClassLoaderFileManager.java Sat Oct 12 09:05:08 2013 +0200
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,372 +0,0 @@
1.4 -/**
1.5 - * Back 2 Browser Bytecode Translator
1.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
1.7 - *
1.8 - * This program is free software: you can redistribute it and/or modify
1.9 - * it under the terms of the GNU General Public License as published by
1.10 - * the Free Software Foundation, version 2 of the License.
1.11 - *
1.12 - * This program is distributed in the hope that it will be useful,
1.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.15 - * GNU General Public License for more details.
1.16 - *
1.17 - * You should have received a copy of the GNU General Public License
1.18 - * along with this program. Look for COPYING file in the top folder.
1.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
1.20 - */
1.21 -
1.22 -package org.apidesign.bck2brwsr.dew;
1.23 -
1.24 -import java.io.File;
1.25 -import java.io.IOException;
1.26 -import java.io.InputStream;
1.27 -import java.net.URL;
1.28 -import java.util.ArrayList;
1.29 -import java.util.Collections;
1.30 -import java.util.EnumSet;
1.31 -import java.util.Enumeration;
1.32 -import java.util.HashMap;
1.33 -import java.util.Iterator;
1.34 -import java.util.List;
1.35 -import java.util.Map;
1.36 -import java.util.Set;
1.37 -import java.util.zip.ZipEntry;
1.38 -import java.util.zip.ZipFile;
1.39 -import javax.tools.FileObject;
1.40 -import javax.tools.JavaFileManager;
1.41 -import javax.tools.JavaFileObject;
1.42 -import javax.tools.StandardLocation;
1.43 -
1.44 -/**
1.45 - *
1.46 - * @author Tomas Zezula
1.47 - */
1.48 -public class ClassLoaderFileManager implements JavaFileManager {
1.49 -
1.50 - private static final Location[] READ_LOCATIONS = {
1.51 - StandardLocation.PLATFORM_CLASS_PATH,
1.52 - StandardLocation.CLASS_PATH,
1.53 - StandardLocation.SOURCE_PATH
1.54 - };
1.55 -
1.56 - private static final Location[] WRITE_LOCATIONS = {
1.57 - StandardLocation.CLASS_OUTPUT,
1.58 - StandardLocation.SOURCE_OUTPUT
1.59 - };
1.60 -
1.61 - private static final Location[] CLASS_LOADER_LOCATIONS = {
1.62 - StandardLocation.ANNOTATION_PROCESSOR_PATH
1.63 - };
1.64 -
1.65 - private Map<Location, Map<String,List<MemoryFileObject>>> generated;
1.66 -
1.67 -
1.68 - ClassLoaderFileManager() {
1.69 - generated = new HashMap<>();
1.70 - for (Location l : WRITE_LOCATIONS) {
1.71 - generated.put(l, new HashMap<String, List<MemoryFileObject>>());
1.72 - }
1.73 - }
1.74 -
1.75 -
1.76 - @Override
1.77 - public ClassLoader getClassLoader(Location location) {
1.78 - if (canClassLoad(location)) {
1.79 - return new SafeClassLoader(getClass().getClassLoader());
1.80 - } else {
1.81 - return null;
1.82 - }
1.83 - }
1.84 -
1.85 - @Override
1.86 - public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException {
1.87 - if (canRead(location)) {
1.88 - final List<JavaFileObject> res = new ArrayList<JavaFileObject>();
1.89 - for (String resource : getResources(convertFQNToResource(packageName))) {
1.90 - final JavaFileObject jfo = new ClassLoaderJavaFileObject(resource);
1.91 - if (kinds.contains(jfo.getKind())) {
1.92 - res.add(jfo);
1.93 - }
1.94 - }
1.95 - return res;
1.96 - } else if (canWrite(location)) {
1.97 - Map<String,List<MemoryFileObject>> folders = generated.get(location);
1.98 - List<MemoryFileObject> files = folders.get(convertFQNToResource(packageName));
1.99 - if (files != null) {
1.100 - final List<JavaFileObject> res = new ArrayList<JavaFileObject>();
1.101 - for (JavaFileObject file : files) {
1.102 - if (kinds.contains(file.getKind()) && file.getLastModified() >= 0) {
1.103 - res.add(file);
1.104 - }
1.105 - }
1.106 - return res;
1.107 - }
1.108 - }
1.109 - return Collections.<JavaFileObject>emptyList();
1.110 - }
1.111 -
1.112 - @Override
1.113 - public String inferBinaryName(Location location, JavaFileObject file) {
1.114 - return ((InferableJavaFileObject)file).infer();
1.115 - }
1.116 -
1.117 - @Override
1.118 - public boolean isSameFile(FileObject a, FileObject b) {
1.119 - return a.toUri().equals(b.toUri());
1.120 - }
1.121 -
1.122 - @Override
1.123 - public boolean handleOption(String current, Iterator<String> remaining) {
1.124 - return false;
1.125 - }
1.126 -
1.127 - @Override
1.128 - public boolean hasLocation(Location location) {
1.129 - for (Location l : StandardLocation.values()) {
1.130 - if (l.equals(location)) {
1.131 - return true;
1.132 - }
1.133 - }
1.134 - return false;
1.135 - }
1.136 -
1.137 - @Override
1.138 - public JavaFileObject getJavaFileForInput(Location location, String className, JavaFileObject.Kind kind) throws IOException {
1.139 - if (canRead(location)) {
1.140 - return new ClassLoaderJavaFileObject(convertFQNToResource(className) + kind.extension);
1.141 - } else {
1.142 - throw new UnsupportedOperationException("Unsupported location for reading: " + location); //NOI18N
1.143 - }
1.144 - }
1.145 -
1.146 - @Override
1.147 - public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
1.148 - if (canWrite(location)) {
1.149 - final String resource = convertFQNToResource(className) + kind.extension;
1.150 - final MemoryFileObject res = new MemoryFileObject(resource, null);
1.151 - register(location, resource, res);
1.152 - return res;
1.153 - } else {
1.154 - throw new UnsupportedOperationException("Unsupported location for reading: " + location); //NOI18N
1.155 - }
1.156 - }
1.157 -
1.158 - @Override
1.159 - public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
1.160 - if (canRead(location)) {
1.161 - return new ClassLoaderJavaFileObject(convertFQNToResource(packageName) + '/' + relativeName); //NOI18N
1.162 - } else {
1.163 - throw new UnsupportedOperationException("Unsupported location for reading: " + location); //NOI18N
1.164 - }
1.165 - }
1.166 -
1.167 - @Override
1.168 - public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException {
1.169 - if (canWrite(location)) {
1.170 - final String resource = convertFQNToResource(packageName) + '/' + relativeName; //NOI18N
1.171 - final MemoryFileObject res = new MemoryFileObject(resource, null);
1.172 - register(location, resource, res);
1.173 - return res;
1.174 - } else {
1.175 - throw new UnsupportedOperationException("Unsupported location for reading: " + location); //NOI18N
1.176 - }
1.177 - }
1.178 -
1.179 - @Override
1.180 - public void flush() throws IOException {
1.181 - }
1.182 -
1.183 - @Override
1.184 - public void close() throws IOException {
1.185 - }
1.186 -
1.187 - @Override
1.188 - public int isSupportedOption(String option) {
1.189 - return -1;
1.190 - }
1.191 -
1.192 -// private List<String> getResources(String folder) throws IOException {
1.193 -// final List<String> result = new ArrayList<String>();
1.194 -// final BufferedReader in = new BufferedReader(new InputStreamReader(
1.195 -// this.getClass().getClassLoader().getResourceAsStream(String.format("%s/pkg-list", folder.substring(0))), //NOI18N
1.196 -// "UTF-8")); //NOI18N
1.197 -// try {
1.198 -// String line;
1.199 -// while ((line = in.readLine()) != null) {
1.200 -// result.add(line);
1.201 -// }
1.202 -// } finally {
1.203 -// in.close();
1.204 -// }
1.205 -// return result;
1.206 -// }
1.207 -
1.208 - //MOCK IMPL
1.209 - private List<String> getResources(String folder) throws IOException {
1.210 - if (classPathContent == null) {
1.211 - classPathContent = new HashMap<>();
1.212 -// final String boot = System.getProperty("sun.boot.class.path"); //NOI18N
1.213 - final String cp = System.getProperty("java.class.path");
1.214 - for (String entry : cp.split(File.pathSeparator)) {
1.215 - File f = new File (entry);
1.216 - if (f.canRead()) {
1.217 - if (f.isFile()) {
1.218 - ZipFile zf = new ZipFile(f);
1.219 - try {
1.220 - Enumeration<? extends ZipEntry> entries = zf.entries();
1.221 - while (entries.hasMoreElements()) {
1.222 - ZipEntry e = entries.nextElement();
1.223 - if (e.isDirectory()) {
1.224 - continue;
1.225 - }
1.226 - final String name = String.format("/%s",e.getName());
1.227 - final String owner = getOwner(name);
1.228 - List<String> content = classPathContent.get(owner);
1.229 - if (content == null) {
1.230 - content = new ArrayList<>();
1.231 - classPathContent.put(owner, content);
1.232 - }
1.233 - content.add(name);
1.234 - }
1.235 - } finally {
1.236 - zf.close();
1.237 - }
1.238 - } else if (f.isDirectory()) {
1.239 - addFiles(f,"/", classPathContent);
1.240 - }
1.241 - }
1.242 - }
1.243 - }
1.244 - List<String> content = classPathContent.get(folder);
1.245 - return content == null ? Collections.<String>emptyList() : content;
1.246 - }
1.247 -
1.248 - private void addFiles(File folder, String path, Map<String,List<String>> into) {
1.249 - for (File f : folder.listFiles()) {
1.250 - String fname = path + (path.length() == 1 ? "" : "/") + f.getName();
1.251 - if (f.isDirectory()) {
1.252 - addFiles(f, fname, into);
1.253 - } else {
1.254 - List<String> content = into.get(path);
1.255 - if (content == null) {
1.256 - content = new ArrayList<>();
1.257 - classPathContent.put(path, content);
1.258 - }
1.259 - content.add(fname);
1.260 - }
1.261 - }
1.262 - }
1.263 -
1.264 - private Map<String,List<String>> classPathContent;
1.265 -
1.266 - private void register(Location loc, String resource, MemoryFileObject jfo) {
1.267 - Map<String,List<MemoryFileObject>> folders = generated.get(loc);
1.268 - final String folder = getOwner(resource);
1.269 - List<MemoryFileObject> content = folders.get(folder);
1.270 - if (content == null) {
1.271 - content = new ArrayList<>();
1.272 - folders.put(folder, content);
1.273 - }
1.274 - content.add(jfo);
1.275 - }
1.276 -
1.277 - private static String getOwner(String resource) {
1.278 - int lastSlash = resource.lastIndexOf('/');
1.279 - assert lastSlash >= 0;
1.280 - return resource.substring(0, lastSlash);
1.281 - }
1.282 -
1.283 - private static boolean canRead(Location loc) {
1.284 - for (Location rl : READ_LOCATIONS) {
1.285 - if (rl.equals(loc)) {
1.286 - return true;
1.287 - }
1.288 - }
1.289 - return false;
1.290 - }
1.291 -
1.292 - private static boolean canWrite(Location loc) {
1.293 - for (Location wl : WRITE_LOCATIONS) {
1.294 - if (wl.equals(loc)) {
1.295 - return true;
1.296 - }
1.297 - }
1.298 - return false;
1.299 - }
1.300 -
1.301 - private static boolean canClassLoad(Location loc) {
1.302 - for (Location cll : CLASS_LOADER_LOCATIONS) {
1.303 - if (cll.equals(loc)) {
1.304 - return true;
1.305 - }
1.306 - }
1.307 - return false;
1.308 - }
1.309 -
1.310 - static String convertFQNToResource(String fqn) {
1.311 - return '/' + fqn.replace('.', '/'); //NOI18N
1.312 - }
1.313 -
1.314 - static String convertResourceToFQN(String resource) {
1.315 - assert resource.startsWith("/"); //NOI18N
1.316 - int lastSlash = resource.lastIndexOf('/'); //NOI18N
1.317 - int lastDot = resource.lastIndexOf('.'); //NOI18N
1.318 - int stop = lastSlash < lastDot ?
1.319 - lastDot :
1.320 - resource.length();
1.321 - return resource.substring(1, stop).replace('/', '.'); //NOI18N
1.322 - }
1.323 -
1.324 -
1.325 - JavaFileObject createMemoryFileObject (String resourceName, JavaFileObject.Kind kind, byte[] content) {
1.326 - final InferableJavaFileObject jfo = new MemoryFileObject(resourceName, kind, content);
1.327 - return jfo;
1.328 - }
1.329 -
1.330 - Iterable<? extends MemoryFileObject> getGeneratedFiles(JavaFileObject.Kind... kinds) {
1.331 - final Set<JavaFileObject.Kind> ks = EnumSet.noneOf(JavaFileObject.Kind.class);
1.332 - Collections.addAll(ks, kinds);
1.333 - final List<MemoryFileObject> res = new ArrayList<>();
1.334 - for (Map<String,List<MemoryFileObject>> folders : generated.values()) {
1.335 - for (List<MemoryFileObject> content : folders.values()) {
1.336 - for (MemoryFileObject fo : content) {
1.337 - if (ks.contains(fo.getKind()) && fo.getLastModified() >= 0) {
1.338 - res.add(fo);
1.339 - }
1.340 - }
1.341 - }
1.342 - }
1.343 - return res;
1.344 - }
1.345 -
1.346 - private static final class SafeClassLoader extends ClassLoader {
1.347 - private final ClassLoader delegate;
1.348 -
1.349 - SafeClassLoader(final ClassLoader delegate) {
1.350 - this.delegate = delegate;
1.351 -
1.352 - }
1.353 -
1.354 - @Override
1.355 - public URL getResource(String name) {
1.356 - return delegate.getResource(name);
1.357 - }
1.358 -
1.359 - @Override
1.360 - public InputStream getResourceAsStream(String name) {
1.361 - return delegate.getResourceAsStream(name);
1.362 - }
1.363 -
1.364 - @Override
1.365 - public Enumeration<URL> getResources(String name) throws IOException {
1.366 - return delegate.getResources(name);
1.367 - }
1.368 -
1.369 - @Override
1.370 - public Class<?> loadClass(String name) throws ClassNotFoundException {
1.371 - return delegate.loadClass(name);
1.372 - }
1.373 - }
1.374 -
1.375 -}