Merging two heads javac
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 03 Oct 2013 10:07:18 +0200
branchjavac
changeset 1329c1893bd50f35
parent 1328 1d1d70f6828b
parent 1327 217ca48c5b80
child 1336 804f6f982f4e
Merging two heads
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dew/src/main/java/org/apidesign/bck2brwsr/dew/BaseFileObject.java	Thu Oct 03 10:07:18 2013 +0200
     1.3 @@ -0,0 +1,110 @@
     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.net.URI;
    1.25 +import javax.lang.model.element.Modifier;
    1.26 +import javax.lang.model.element.NestingKind;
    1.27 +
    1.28 +/**
    1.29 + *
    1.30 + * @author Tomas Zezula
    1.31 + */
    1.32 +public abstract class BaseFileObject implements InferableJavaFileObject {
    1.33 +
    1.34 +    protected final String path;
    1.35 +    protected final Kind kind;
    1.36 +
    1.37 +    BaseFileObject(
    1.38 +        String path,
    1.39 +        Kind kind) {
    1.40 +        if (!path.startsWith("/")) {    //NOI18N
    1.41 +            throw new IllegalArgumentException();
    1.42 +        }
    1.43 +        this.path = path;
    1.44 +        this.kind = kind;
    1.45 +    }
    1.46 +
    1.47 +
    1.48 +    @Override
    1.49 +    public String infer() {
    1.50 +        return ClassLoaderFileManager.convertResourceToFQN(path);
    1.51 +    }
    1.52 +
    1.53 +    @Override
    1.54 +    public Kind getKind() {
    1.55 +        return kind;
    1.56 +    }
    1.57 +
    1.58 +    @Override
    1.59 +    public boolean isNameCompatible(String simpleName, Kind kind) {
    1.60 +        return this.kind == kind &&
    1.61 +        getSimpleName(path).equals(simpleName);
    1.62 +    }
    1.63 +
    1.64 +    @Override
    1.65 +    public NestingKind getNestingKind() {
    1.66 +        return null;
    1.67 +    }
    1.68 +
    1.69 +    @Override
    1.70 +    public Modifier getAccessLevel() {
    1.71 +        return null;
    1.72 +    }
    1.73 +
    1.74 +    @Override
    1.75 +    public URI toUri() {
    1.76 +        return URI.create(escape(path));
    1.77 +    }
    1.78 +
    1.79 +    @Override
    1.80 +    public String getName() {
    1.81 +        return path;
    1.82 +    }
    1.83 +
    1.84 +
    1.85 +
    1.86 +    protected static String getSimpleName(String path) {
    1.87 +        int slashIndex = path.lastIndexOf('/');
    1.88 +        assert slashIndex >= 0;
    1.89 +        return (slashIndex + 1 < path.length()) ?
    1.90 +            path.substring(slashIndex + 1) :
    1.91 +            ""; //NOI18N
    1.92 +    }
    1.93 +
    1.94 +    protected static Kind getKind(final String path) {
    1.95 +        final String simpleName = getSimpleName(path);
    1.96 +        final int dotIndex = simpleName.lastIndexOf('.'); //NOI18N
    1.97 +        final String ext = dotIndex > 0 ?
    1.98 +            simpleName.substring(dotIndex) :
    1.99 +            "";
   1.100 +        for (Kind k : Kind.values()) {
   1.101 +            if (k.extension.equals(ext)) {
   1.102 +                return k;
   1.103 +            }
   1.104 +        }
   1.105 +        return Kind.OTHER;
   1.106 +    }
   1.107 +
   1.108 +    private String escape(String path) {
   1.109 +        return path;
   1.110 +    }
   1.111 +
   1.112 +
   1.113 +}
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/dew/src/main/java/org/apidesign/bck2brwsr/dew/ClassLoaderFileManager.java	Thu Oct 03 10:07:18 2013 +0200
     2.3 @@ -0,0 +1,372 @@
     2.4 +/**
     2.5 + * Back 2 Browser Bytecode Translator
     2.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     2.7 + *
     2.8 + * This program is free software: you can redistribute it and/or modify
     2.9 + * it under the terms of the GNU General Public License as published by
    2.10 + * the Free Software Foundation, version 2 of the License.
    2.11 + *
    2.12 + * This program is distributed in the hope that it will be useful,
    2.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.15 + * GNU General Public License for more details.
    2.16 + *
    2.17 + * You should have received a copy of the GNU General Public License
    2.18 + * along with this program. Look for COPYING file in the top folder.
    2.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    2.20 + */
    2.21 +
    2.22 +package org.apidesign.bck2brwsr.dew;
    2.23 +
    2.24 +import java.io.File;
    2.25 +import java.io.IOException;
    2.26 +import java.io.InputStream;
    2.27 +import java.net.URL;
    2.28 +import java.util.ArrayList;
    2.29 +import java.util.Collections;
    2.30 +import java.util.EnumSet;
    2.31 +import java.util.Enumeration;
    2.32 +import java.util.HashMap;
    2.33 +import java.util.Iterator;
    2.34 +import java.util.List;
    2.35 +import java.util.Map;
    2.36 +import java.util.Set;
    2.37 +import java.util.zip.ZipEntry;
    2.38 +import java.util.zip.ZipFile;
    2.39 +import javax.tools.FileObject;
    2.40 +import javax.tools.JavaFileManager;
    2.41 +import javax.tools.JavaFileObject;
    2.42 +import javax.tools.StandardLocation;
    2.43 +
    2.44 +/**
    2.45 + *
    2.46 + * @author Tomas Zezula
    2.47 + */
    2.48 +public class ClassLoaderFileManager implements JavaFileManager {
    2.49 +
    2.50 +    private static final Location[] READ_LOCATIONS = {
    2.51 +        StandardLocation.PLATFORM_CLASS_PATH,
    2.52 +        StandardLocation.CLASS_PATH,
    2.53 +        StandardLocation.SOURCE_PATH
    2.54 +    };
    2.55 +
    2.56 +    private static final Location[] WRITE_LOCATIONS = {
    2.57 +        StandardLocation.CLASS_OUTPUT,
    2.58 +        StandardLocation.SOURCE_OUTPUT
    2.59 +    };
    2.60 +
    2.61 +    private static final Location[] CLASS_LOADER_LOCATIONS = {
    2.62 +        StandardLocation.ANNOTATION_PROCESSOR_PATH
    2.63 +    };
    2.64 +
    2.65 +    private Map<Location, Map<String,List<MemoryFileObject>>> generated;
    2.66 +
    2.67 +
    2.68 +    ClassLoaderFileManager() {
    2.69 +        generated = new HashMap<>();
    2.70 +        for (Location l : WRITE_LOCATIONS) {
    2.71 +            generated.put(l, new HashMap<String, List<MemoryFileObject>>());
    2.72 +        }
    2.73 +    }
    2.74 +
    2.75 +
    2.76 +    @Override
    2.77 +    public ClassLoader getClassLoader(Location location) {
    2.78 +        if (canClassLoad(location)) {
    2.79 +            return new SafeClassLoader(getClass().getClassLoader());
    2.80 +        } else {
    2.81 +            return null;
    2.82 +        }
    2.83 +    }
    2.84 +
    2.85 +    @Override
    2.86 +    public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException {
    2.87 +        if (canRead(location)) {
    2.88 +            final List<JavaFileObject> res = new ArrayList<JavaFileObject>();
    2.89 +            for (String resource : getResources(convertFQNToResource(packageName))) {
    2.90 +                final JavaFileObject jfo = new ClassLoaderJavaFileObject(resource);
    2.91 +                if (kinds.contains(jfo.getKind())) {
    2.92 +                    res.add(jfo);
    2.93 +                }
    2.94 +            }
    2.95 +            return res;
    2.96 +        } else if (canWrite(location)) {
    2.97 +            Map<String,List<MemoryFileObject>> folders = generated.get(location);
    2.98 +            List<MemoryFileObject> files = folders.get(convertFQNToResource(packageName));
    2.99 +            if (files != null) {
   2.100 +                final List<JavaFileObject> res = new ArrayList<JavaFileObject>();
   2.101 +                for (JavaFileObject file : files) {
   2.102 +                    if (kinds.contains(file.getKind()) && file.getLastModified() >= 0) {
   2.103 +                        res.add(file);
   2.104 +                    }
   2.105 +                }
   2.106 +                return res;
   2.107 +            }
   2.108 +        }
   2.109 +        return Collections.<JavaFileObject>emptyList();
   2.110 +    }
   2.111 +
   2.112 +    @Override
   2.113 +    public String inferBinaryName(Location location, JavaFileObject file) {
   2.114 +        return ((InferableJavaFileObject)file).infer();
   2.115 +    }
   2.116 +
   2.117 +    @Override
   2.118 +    public boolean isSameFile(FileObject a, FileObject b) {
   2.119 +        return a.toUri().equals(b.toUri());
   2.120 +    }
   2.121 +
   2.122 +    @Override
   2.123 +    public boolean handleOption(String current, Iterator<String> remaining) {
   2.124 +        return false;
   2.125 +    }
   2.126 +
   2.127 +    @Override
   2.128 +    public boolean hasLocation(Location location) {
   2.129 +        for (Location l : StandardLocation.values()) {
   2.130 +            if (l.equals(location)) {
   2.131 +                return true;
   2.132 +            }
   2.133 +        }
   2.134 +        return false;
   2.135 +    }
   2.136 +
   2.137 +    @Override
   2.138 +    public JavaFileObject getJavaFileForInput(Location location, String className, JavaFileObject.Kind kind) throws IOException {
   2.139 +        if (canRead(location)) {
   2.140 +            return new ClassLoaderJavaFileObject(convertFQNToResource(className) + kind.extension);
   2.141 +        } else {
   2.142 +            throw new UnsupportedOperationException("Unsupported location for reading: " + location);   //NOI18N
   2.143 +        }
   2.144 +    }
   2.145 +
   2.146 +    @Override
   2.147 +    public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
   2.148 +        if (canWrite(location)) {
   2.149 +            final String resource = convertFQNToResource(className) + kind.extension;
   2.150 +            final MemoryFileObject res = new MemoryFileObject(resource, null);
   2.151 +            register(location, resource, res);
   2.152 +            return res;
   2.153 +        } else {
   2.154 +            throw new UnsupportedOperationException("Unsupported location for reading: " + location);   //NOI18N
   2.155 +        }
   2.156 +    }
   2.157 +
   2.158 +    @Override
   2.159 +    public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
   2.160 +        if (canRead(location)) {
   2.161 +            return new ClassLoaderJavaFileObject(convertFQNToResource(packageName) + '/' + relativeName); //NOI18N
   2.162 +        } else {
   2.163 +            throw new UnsupportedOperationException("Unsupported location for reading: " + location);   //NOI18N
   2.164 +        }
   2.165 +    }
   2.166 +
   2.167 +    @Override
   2.168 +    public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException {
   2.169 +        if (canWrite(location)) {
   2.170 +            final String resource = convertFQNToResource(packageName) + '/' + relativeName; //NOI18N
   2.171 +            final MemoryFileObject res = new MemoryFileObject(resource, null);
   2.172 +            register(location, resource, res);
   2.173 +            return res;
   2.174 +        } else {
   2.175 +            throw new UnsupportedOperationException("Unsupported location for reading: " + location);   //NOI18N
   2.176 +        }
   2.177 +    }
   2.178 +
   2.179 +    @Override
   2.180 +    public void flush() throws IOException {
   2.181 +    }
   2.182 +
   2.183 +    @Override
   2.184 +    public void close() throws IOException {        
   2.185 +    }
   2.186 +
   2.187 +    @Override
   2.188 +    public int isSupportedOption(String option) {
   2.189 +        return -1;
   2.190 +    }
   2.191 +
   2.192 +//    private List<String> getResources(String folder) throws IOException {
   2.193 +//        final List<String> result = new ArrayList<String>();
   2.194 +//        final BufferedReader in = new BufferedReader(new InputStreamReader(
   2.195 +//                this.getClass().getClassLoader().getResourceAsStream(String.format("%s/pkg-list", folder.substring(0))),    //NOI18N
   2.196 +//                "UTF-8"));  //NOI18N
   2.197 +//        try {
   2.198 +//            String line;
   2.199 +//            while ((line = in.readLine()) != null) {
   2.200 +//                result.add(line);
   2.201 +//            }
   2.202 +//        } finally {
   2.203 +//            in.close();
   2.204 +//        }
   2.205 +//        return result;
   2.206 +//    }
   2.207 +
   2.208 +    //MOCK IMPL
   2.209 +    private List<String> getResources(String folder) throws IOException {
   2.210 +        if (classPathContent == null) {
   2.211 +            classPathContent = new HashMap<>();
   2.212 +//            final String boot = System.getProperty("sun.boot.class.path");  //NOI18N
   2.213 +            final String cp = System.getProperty("java.class.path");
   2.214 +            for (String entry : cp.split(File.pathSeparator)) {
   2.215 +                File f = new File (entry);
   2.216 +                if (f.canRead()) {
   2.217 +                    if (f.isFile()) {
   2.218 +                        ZipFile zf = new ZipFile(f);
   2.219 +                        try {
   2.220 +                            Enumeration<? extends ZipEntry> entries = zf.entries();
   2.221 +                            while (entries.hasMoreElements()) {
   2.222 +                                ZipEntry e = entries.nextElement();
   2.223 +                                if (e.isDirectory()) {
   2.224 +                                    continue;
   2.225 +                                }
   2.226 +                                final String name = String.format("/%s",e.getName());
   2.227 +                                final String owner = getOwner(name);
   2.228 +                                List<String> content = classPathContent.get(owner);
   2.229 +                                if (content == null) {
   2.230 +                                    content = new ArrayList<>();
   2.231 +                                    classPathContent.put(owner, content);
   2.232 +                                }
   2.233 +                                content.add(name);
   2.234 +                            }
   2.235 +                        } finally {
   2.236 +                            zf.close();
   2.237 +                        }
   2.238 +                    } else if (f.isDirectory()) {
   2.239 +                        addFiles(f,"/", classPathContent);
   2.240 +                    }
   2.241 +                }
   2.242 +            }                                    
   2.243 +        }
   2.244 +        List<String> content = classPathContent.get(folder);
   2.245 +        return content == null ? Collections.<String>emptyList() : content;
   2.246 +    }
   2.247 +
   2.248 +    private void addFiles(File folder, String path, Map<String,List<String>> into) {
   2.249 +        for (File f : folder.listFiles()) {
   2.250 +            String fname = path + (path.length() == 1 ? "" : "/") +  f.getName();
   2.251 +            if (f.isDirectory()) {
   2.252 +                addFiles(f, fname, into);
   2.253 +            } else {
   2.254 +                List<String> content = into.get(path);
   2.255 +                if (content == null) {
   2.256 +                    content = new ArrayList<>();
   2.257 +                    classPathContent.put(path, content);
   2.258 +                }
   2.259 +                content.add(fname);
   2.260 +            }
   2.261 +        }
   2.262 +    }
   2.263 +    
   2.264 +    private Map<String,List<String>> classPathContent;
   2.265 +
   2.266 +    private void register(Location loc, String resource, MemoryFileObject jfo) {
   2.267 +        Map<String,List<MemoryFileObject>> folders = generated.get(loc);
   2.268 +        final String folder = getOwner(resource);
   2.269 +        List<MemoryFileObject> content = folders.get(folder);
   2.270 +        if (content == null) {
   2.271 +            content = new ArrayList<>();
   2.272 +            folders.put(folder, content);
   2.273 +        }
   2.274 +        content.add(jfo);
   2.275 +    }
   2.276 +
   2.277 +    private static String getOwner(String resource) {
   2.278 +        int lastSlash = resource.lastIndexOf('/');
   2.279 +        assert lastSlash >= 0;
   2.280 +        return resource.substring(0, lastSlash);
   2.281 +    }
   2.282 +
   2.283 +    private static boolean canRead(Location loc) {
   2.284 +        for (Location rl : READ_LOCATIONS) {
   2.285 +            if (rl.equals(loc)) {
   2.286 +                return true;
   2.287 +            }
   2.288 +        }
   2.289 +        return false;
   2.290 +    }
   2.291 +
   2.292 +    private static boolean canWrite(Location loc) {
   2.293 +        for (Location wl : WRITE_LOCATIONS) {
   2.294 +            if (wl.equals(loc)) {
   2.295 +                return true;
   2.296 +            }
   2.297 +        }
   2.298 +        return false;
   2.299 +    }
   2.300 +
   2.301 +    private static boolean canClassLoad(Location loc) {
   2.302 +        for (Location cll : CLASS_LOADER_LOCATIONS) {
   2.303 +            if (cll.equals(loc)) {
   2.304 +                return true;
   2.305 +            }
   2.306 +        }
   2.307 +        return false;
   2.308 +    }
   2.309 +
   2.310 +    static String convertFQNToResource(String fqn) {
   2.311 +        return '/' + fqn.replace('.', '/');   //NOI18N
   2.312 +    }
   2.313 +
   2.314 +    static String convertResourceToFQN(String resource) {
   2.315 +        assert resource.startsWith("/");    //NOI18N
   2.316 +        int lastSlash = resource.lastIndexOf('/');  //NOI18N
   2.317 +        int lastDot = resource.lastIndexOf('.');    //NOI18N
   2.318 +        int stop = lastSlash < lastDot ?
   2.319 +            lastDot :
   2.320 +            resource.length();
   2.321 +        return resource.substring(1, stop).replace('/', '.');    //NOI18N
   2.322 +    }
   2.323 +
   2.324 +
   2.325 +    JavaFileObject createMemoryFileObject (String resourceName, JavaFileObject.Kind kind, byte[] content) {
   2.326 +        final InferableJavaFileObject jfo  = new MemoryFileObject(resourceName, kind, content);
   2.327 +        return jfo;
   2.328 +    }
   2.329 +
   2.330 +    Iterable<? extends MemoryFileObject> getGeneratedFiles(JavaFileObject.Kind... kinds) {
   2.331 +        final Set<JavaFileObject.Kind> ks = EnumSet.noneOf(JavaFileObject.Kind.class);
   2.332 +        Collections.addAll(ks, kinds);
   2.333 +        final List<MemoryFileObject> res = new ArrayList<>();
   2.334 +        for (Map<String,List<MemoryFileObject>> folders : generated.values()) {
   2.335 +            for (List<MemoryFileObject> content : folders.values()) {
   2.336 +                for (MemoryFileObject fo : content) {
   2.337 +                    if (ks.contains(fo.getKind()) && fo.getLastModified() >= 0) {
   2.338 +                        res.add(fo);
   2.339 +                    }
   2.340 +                }
   2.341 +            }
   2.342 +        }
   2.343 +        return res;
   2.344 +    }
   2.345 +
   2.346 +    private static final class SafeClassLoader extends ClassLoader {
   2.347 +        private final ClassLoader delegate;
   2.348 +
   2.349 +        SafeClassLoader(final ClassLoader delegate) {
   2.350 +            this.delegate = delegate;
   2.351 +
   2.352 +        }
   2.353 +
   2.354 +        @Override
   2.355 +        public URL getResource(String name) {
   2.356 +            return delegate.getResource(name);
   2.357 +        }
   2.358 +
   2.359 +        @Override
   2.360 +        public InputStream getResourceAsStream(String name) {
   2.361 +            return delegate.getResourceAsStream(name);
   2.362 +        }
   2.363 +
   2.364 +        @Override
   2.365 +        public Enumeration<URL> getResources(String name) throws IOException {
   2.366 +            return delegate.getResources(name);
   2.367 +        }
   2.368 +
   2.369 +        @Override
   2.370 +        public Class<?> loadClass(String name) throws ClassNotFoundException {
   2.371 +            return delegate.loadClass(name);
   2.372 +        }
   2.373 +    }
   2.374 +
   2.375 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/dew/src/main/java/org/apidesign/bck2brwsr/dew/ClassLoaderJavaFileObject.java	Thu Oct 03 10:07:18 2013 +0200
     3.3 @@ -0,0 +1,91 @@
     3.4 +/**
     3.5 + * Back 2 Browser Bytecode Translator
     3.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     3.7 + *
     3.8 + * This program is free software: you can redistribute it and/or modify
     3.9 + * it under the terms of the GNU General Public License as published by
    3.10 + * the Free Software Foundation, version 2 of the License.
    3.11 + *
    3.12 + * This program is distributed in the hope that it will be useful,
    3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.15 + * GNU General Public License for more details.
    3.16 + *
    3.17 + * You should have received a copy of the GNU General Public License
    3.18 + * along with this program. Look for COPYING file in the top folder.
    3.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    3.20 + */
    3.21 +
    3.22 +package org.apidesign.bck2brwsr.dew;
    3.23 +
    3.24 +import java.io.BufferedReader;
    3.25 +import java.io.FileNotFoundException;
    3.26 +import java.io.IOException;
    3.27 +import java.io.InputStream;
    3.28 +import java.io.InputStreamReader;
    3.29 +import java.io.OutputStream;
    3.30 +import java.io.OutputStreamWriter;
    3.31 +import java.io.Reader;
    3.32 +import java.io.Writer;
    3.33 +
    3.34 +/**
    3.35 + *
    3.36 + * @author Tomas Zezula
    3.37 + */
    3.38 +class ClassLoaderJavaFileObject extends BaseFileObject {
    3.39 +
    3.40 +    ClassLoaderJavaFileObject(final String path) {
    3.41 +        super(path, getKind(path));
    3.42 +    }    
    3.43 +
    3.44 +    @Override
    3.45 +    public InputStream openInputStream() throws IOException {
    3.46 +        final InputStream in = getClass().getClassLoader().getResourceAsStream(path.substring(1));
    3.47 +        if (in == null) {
    3.48 +            throw new FileNotFoundException(path);
    3.49 +        }
    3.50 +        return in;
    3.51 +    }
    3.52 +
    3.53 +    @Override
    3.54 +    public OutputStream openOutputStream() throws IOException {
    3.55 +        throw new UnsupportedOperationException("Read Only FileObject");    //NOI18N
    3.56 +    }
    3.57 +
    3.58 +    @Override
    3.59 +    public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
    3.60 +        return new InputStreamReader(openInputStream());
    3.61 +    }
    3.62 +
    3.63 +    @Override
    3.64 +    public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
    3.65 +        final BufferedReader in = new BufferedReader(openReader(ignoreEncodingErrors));
    3.66 +        try {
    3.67 +            final StringBuilder sb = new StringBuilder();
    3.68 +            String line;
    3.69 +            while ((line = in.readLine()) != null) {
    3.70 +                sb.append(line);
    3.71 +                sb.append('\n');    //NOI18N
    3.72 +            }
    3.73 +            return sb.toString();
    3.74 +        } finally {
    3.75 +            in.close();
    3.76 +        }
    3.77 +    }
    3.78 +
    3.79 +    @Override
    3.80 +    public Writer openWriter() throws IOException {
    3.81 +        return new OutputStreamWriter(openOutputStream());
    3.82 +    }
    3.83 +
    3.84 +    @Override
    3.85 +    public long getLastModified() {
    3.86 +        return System.currentTimeMillis();
    3.87 +    }
    3.88 +
    3.89 +    @Override
    3.90 +    public boolean delete() {
    3.91 +        return false;
    3.92 +    }
    3.93 +
    3.94 +}
     4.1 --- a/dew/src/main/java/org/apidesign/bck2brwsr/dew/Compile.java	Mon Sep 30 17:11:18 2013 +0200
     4.2 +++ b/dew/src/main/java/org/apidesign/bck2brwsr/dew/Compile.java	Thu Oct 03 10:07:18 2013 +0200
     4.3 @@ -83,90 +83,33 @@
     4.4      }
     4.5      
     4.6      private Map<String, byte[]> compile(final String html, final String code) throws IOException {
     4.7 -        StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
     4.8 +        final ClassLoaderFileManager clfm = new ClassLoaderFileManager();
     4.9 +        final JavaFileObject file = clfm.createMemoryFileObject(
    4.10 +                ClassLoaderFileManager.convertFQNToResource(pkg.isEmpty() ? cls : pkg + "." + cls) + Kind.SOURCE.extension,
    4.11 +                Kind.SOURCE,
    4.12 +                code.getBytes());
    4.13 +        final JavaFileObject htmlFile = clfm.createMemoryFileObject(
    4.14 +            ClassLoaderFileManager.convertFQNToResource(pkg),
    4.15 +            Kind.OTHER,
    4.16 +            html.getBytes());
    4.17  
    4.18 -        final Map<String, ByteArrayOutputStream> class2BAOS = new HashMap<>();
    4.19 -
    4.20 -        JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
    4.21 -            @Override
    4.22 -            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
    4.23 -                return code;
    4.24 -            }
    4.25 -        };
    4.26 -        final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
    4.27 -            @Override
    4.28 -            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
    4.29 -                return html;
    4.30 -            }
    4.31 -
    4.32 -            @Override
    4.33 -            public InputStream openInputStream() throws IOException {
    4.34 -                return new ByteArrayInputStream(html.getBytes());
    4.35 -            }
    4.36 -        };
    4.37 -        
    4.38 -        final URI scratch;
    4.39 -        try {
    4.40 -            scratch = new URI("mem://mem3");
    4.41 -        } catch (URISyntaxException ex) {
    4.42 -            throw new IOException(ex);
    4.43 -        }
    4.44 -        
    4.45 -        JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
    4.46 -            @Override
    4.47 -            public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
    4.48 -                if (kind  == Kind.CLASS) {
    4.49 -                    final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    4.50 -
    4.51 -                    class2BAOS.put(className.replace('.', '/') + ".class", buffer);
    4.52 -                    return new SimpleJavaFileObject(sibling.toUri(), kind) {
    4.53 -                        @Override
    4.54 -                        public OutputStream openOutputStream() throws IOException {
    4.55 -                            return buffer;
    4.56 -                        }
    4.57 -                    };
    4.58 -                }
    4.59 -                
    4.60 -                if (kind == Kind.SOURCE) {
    4.61 -                    return new SimpleJavaFileObject(scratch/*sibling.toUri()*/, kind) {
    4.62 -                        private final ByteArrayOutputStream data = new ByteArrayOutputStream();
    4.63 -                        @Override
    4.64 -                        public OutputStream openOutputStream() throws IOException {
    4.65 -                            return data;
    4.66 -                        }
    4.67 -
    4.68 -                        @Override
    4.69 -                        public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
    4.70 -                            data.close();
    4.71 -                            return new String(data.toByteArray());
    4.72 -                        }
    4.73 -                    };
    4.74 -                }
    4.75 -                
    4.76 -                throw new IllegalStateException();
    4.77 -            }
    4.78 -
    4.79 +        JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(clfm) {            
    4.80              @Override
    4.81              public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
    4.82                  if (location == StandardLocation.SOURCE_PATH) {
    4.83                      if (packageName.equals(pkg)) {
    4.84                          return htmlFile;
    4.85                      }
    4.86 -                }
    4.87 -                
    4.88 +                }                
    4.89                  return null;
    4.90              }
    4.91 -            
    4.92          };
    4.93  
    4.94 -        ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", "1.7", "-target", "1.7"), null, Arrays.asList(file)).call();
    4.95 -
    4.96 +        final Boolean res = ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", "1.7", "-target", "1.7"), null, Arrays.asList(file)).call();
    4.97          Map<String, byte[]> result = new HashMap<>();
    4.98 -
    4.99 -        for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
   4.100 -            result.put(e.getKey(), e.getValue().toByteArray());
   4.101 +        for (MemoryFileObject generated : clfm.getGeneratedFiles(Kind.CLASS)) {
   4.102 +            result.put(generated.getName().substring(1), generated.getContent());
   4.103          }
   4.104 -
   4.105          return result;
   4.106      }
   4.107  
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/dew/src/main/java/org/apidesign/bck2brwsr/dew/InferableJavaFileObject.java	Thu Oct 03 10:07:18 2013 +0200
     5.3 @@ -0,0 +1,29 @@
     5.4 +/**
     5.5 + * Back 2 Browser Bytecode Translator
     5.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     5.7 + *
     5.8 + * This program is free software: you can redistribute it and/or modify
     5.9 + * it under the terms of the GNU General Public License as published by
    5.10 + * the Free Software Foundation, version 2 of the License.
    5.11 + *
    5.12 + * This program is distributed in the hope that it will be useful,
    5.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.15 + * GNU General Public License for more details.
    5.16 + *
    5.17 + * You should have received a copy of the GNU General Public License
    5.18 + * along with this program. Look for COPYING file in the top folder.
    5.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    5.20 + */
    5.21 +
    5.22 +package org.apidesign.bck2brwsr.dew;
    5.23 +
    5.24 +import javax.tools.JavaFileObject;
    5.25 +
    5.26 +/**
    5.27 + *
    5.28 + * @author Tomas Zezula
    5.29 + */
    5.30 +interface InferableJavaFileObject extends JavaFileObject {
    5.31 +    String infer();
    5.32 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/dew/src/main/java/org/apidesign/bck2brwsr/dew/MemoryFileObject.java	Thu Oct 03 10:07:18 2013 +0200
     6.3 @@ -0,0 +1,137 @@
     6.4 +/**
     6.5 + * Back 2 Browser Bytecode Translator
     6.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     6.7 + *
     6.8 + * This program is free software: you can redistribute it and/or modify
     6.9 + * it under the terms of the GNU General Public License as published by
    6.10 + * the Free Software Foundation, version 2 of the License.
    6.11 + *
    6.12 + * This program is distributed in the hope that it will be useful,
    6.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.15 + * GNU General Public License for more details.
    6.16 + *
    6.17 + * You should have received a copy of the GNU General Public License
    6.18 + * along with this program. Look for COPYING file in the top folder.
    6.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    6.20 + */
    6.21 +
    6.22 +package org.apidesign.bck2brwsr.dew;
    6.23 +
    6.24 +import java.io.ByteArrayInputStream;
    6.25 +import java.io.ByteArrayOutputStream;
    6.26 +import java.io.IOException;
    6.27 +import java.io.InputStream;
    6.28 +import java.io.InputStreamReader;
    6.29 +import java.io.OutputStream;
    6.30 +import java.io.OutputStreamWriter;
    6.31 +import java.io.Reader;
    6.32 +import java.io.Writer;
    6.33 +
    6.34 +/**
    6.35 + *
    6.36 + * @author Tomas Zeuzla
    6.37 + */
    6.38 +class MemoryFileObject extends BaseFileObject {
    6.39 +
    6.40 +    private byte[] content;
    6.41 +    private long lastModified;
    6.42 +
    6.43 +    MemoryFileObject (
    6.44 +            String resourceName,
    6.45 +            Kind kind,
    6.46 +            byte[] content) {
    6.47 +        super(resourceName, kind);
    6.48 +        this.content = content;
    6.49 +        this.lastModified = this.content == null ?
    6.50 +            -1 :
    6.51 +            System.currentTimeMillis();
    6.52 +    }
    6.53 +
    6.54 +    MemoryFileObject (
    6.55 +            String resourceName,
    6.56 +            byte[] content) {
    6.57 +        this(resourceName, getKind(resourceName) ,content);
    6.58 +    }
    6.59 +
    6.60 +
    6.61 +    @Override
    6.62 +    public InputStream openInputStream() throws IOException {
    6.63 +        if (content == null) {
    6.64 +            throw new IOException();
    6.65 +        } else {
    6.66 +            return new ByteArrayInputStream(content);
    6.67 +        }
    6.68 +    }
    6.69 +
    6.70 +    @Override
    6.71 +    public OutputStream openOutputStream() throws IOException {
    6.72 +        return new CloseStream();
    6.73 +    }
    6.74 +
    6.75 +    @Override
    6.76 +    public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
    6.77 +        return new InputStreamReader(openInputStream());
    6.78 +    }
    6.79 +
    6.80 +    @Override
    6.81 +    public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
    6.82 +        if (content == null) {
    6.83 +            throw new IOException();
    6.84 +        } else {
    6.85 +            return new String(content);
    6.86 +        }
    6.87 +    }
    6.88 +
    6.89 +    @Override
    6.90 +    public Writer openWriter() throws IOException {
    6.91 +        return new OutputStreamWriter(openOutputStream());
    6.92 +    }
    6.93 +
    6.94 +    @Override
    6.95 +    public long getLastModified() {
    6.96 +        return lastModified;
    6.97 +    }
    6.98 +
    6.99 +    @Override
   6.100 +    public boolean delete() {
   6.101 +        return false;
   6.102 +    }
   6.103 +
   6.104 +    byte[] getContent() {
   6.105 +        return content;
   6.106 +    }
   6.107 +
   6.108 +    private class CloseStream extends OutputStream {
   6.109 +
   6.110 +        private final ByteArrayOutputStream delegate;
   6.111 +
   6.112 +        CloseStream() {
   6.113 +            delegate = new ByteArrayOutputStream();
   6.114 +        }
   6.115 +
   6.116 +        @Override
   6.117 +        public void write(int b) throws IOException {
   6.118 +            delegate.write(b);
   6.119 +        }
   6.120 +
   6.121 +        @Override
   6.122 +        public void write(byte[] b) throws IOException {
   6.123 +            delegate.write(b);
   6.124 +        }
   6.125 +
   6.126 +        @Override
   6.127 +        public void write(byte[] b, int off, int len) throws IOException {
   6.128 +            delegate.write(b, off, len);
   6.129 +        }
   6.130 +
   6.131 +        @Override
   6.132 +        public void close() throws IOException {
   6.133 +            delegate.close();
   6.134 +            content = delegate.toByteArray();
   6.135 +            lastModified = System.currentTimeMillis();
   6.136 +        }                                    
   6.137 +
   6.138 +    }
   6.139 +
   6.140 +}