ClassLoaderFileManager
authortzezula
Wed, 02 Oct 2013 21:00:24 +0200
changeset 1324263482b074e9
parent 1310 635ee75d82a5
child 1325 f7f25ea1bbec
ClassLoaderFileManager
dew/src/main/java/org/apidesign/bck2brwsr/dew/BaseFileObject.java
dew/src/main/java/org/apidesign/bck2brwsr/dew/ClassLoaderFileManager.java
dew/src/main/java/org/apidesign/bck2brwsr/dew/ClassLoaderJavaFileObject.java
dew/src/main/java/org/apidesign/bck2brwsr/dew/Compile.java
dew/src/main/java/org/apidesign/bck2brwsr/dew/InferableJavaFileObject.java
dew/src/main/java/org/apidesign/bck2brwsr/dew/MemoryFileObject.java
     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	Wed Oct 02 21:00:24 2013 +0200
     1.3 @@ -0,0 +1,98 @@
     1.4 +/*
     1.5 + * To change this license header, choose License Headers in Project Properties.
     1.6 + * To change this template file, choose Tools | Templates
     1.7 + * and open the template in the editor.
     1.8 + */
     1.9 +
    1.10 +package org.apidesign.bck2brwsr.dew;
    1.11 +
    1.12 +import java.net.URI;
    1.13 +import javax.lang.model.element.Modifier;
    1.14 +import javax.lang.model.element.NestingKind;
    1.15 +
    1.16 +/**
    1.17 + *
    1.18 + * @author tom
    1.19 + */
    1.20 +public abstract class BaseFileObject implements InferableJavaFileObject {
    1.21 +
    1.22 +    protected final String path;
    1.23 +    protected final Kind kind;
    1.24 +
    1.25 +    BaseFileObject(
    1.26 +        String path,
    1.27 +        Kind kind) {
    1.28 +        if (!path.startsWith("/")) {    //NOI18N
    1.29 +            throw new IllegalArgumentException();
    1.30 +        }
    1.31 +        this.path = path;
    1.32 +        this.kind = kind;
    1.33 +    }
    1.34 +
    1.35 +
    1.36 +    @Override
    1.37 +    public String infer() {
    1.38 +        return ClassLoaderFileManager.convertResourceToFQN(path);
    1.39 +    }
    1.40 +
    1.41 +    @Override
    1.42 +    public Kind getKind() {
    1.43 +        return kind;
    1.44 +    }
    1.45 +
    1.46 +    @Override
    1.47 +    public boolean isNameCompatible(String simpleName, Kind kind) {
    1.48 +        return this.kind == kind &&
    1.49 +        getSimpleName(path).equals(simpleName);
    1.50 +    }
    1.51 +
    1.52 +    @Override
    1.53 +    public NestingKind getNestingKind() {
    1.54 +        return null;
    1.55 +    }
    1.56 +
    1.57 +    @Override
    1.58 +    public Modifier getAccessLevel() {
    1.59 +        return null;
    1.60 +    }
    1.61 +
    1.62 +    @Override
    1.63 +    public URI toUri() {
    1.64 +        return URI.create(escape(path));
    1.65 +    }
    1.66 +
    1.67 +    @Override
    1.68 +    public String getName() {
    1.69 +        return path;
    1.70 +    }
    1.71 +
    1.72 +
    1.73 +
    1.74 +    protected static String getSimpleName(String path) {
    1.75 +        int slashIndex = path.lastIndexOf('/');
    1.76 +        assert slashIndex >= 0;
    1.77 +        return (slashIndex + 1 < path.length()) ?
    1.78 +            path.substring(slashIndex + 1) :
    1.79 +            ""; //NOI18N
    1.80 +    }
    1.81 +
    1.82 +    protected static Kind getKind(final String path) {
    1.83 +        final String simpleName = getSimpleName(path);
    1.84 +        final int dotIndex = simpleName.lastIndexOf('.'); //NOI18N
    1.85 +        final String ext = dotIndex > 0 ?
    1.86 +            simpleName.substring(dotIndex) :
    1.87 +            "";
    1.88 +        for (Kind k : Kind.values()) {
    1.89 +            if (k.extension.equals(ext)) {
    1.90 +                return k;
    1.91 +            }
    1.92 +        }
    1.93 +        return Kind.OTHER;
    1.94 +    }
    1.95 +
    1.96 +    private String escape(String path) {
    1.97 +        return path;
    1.98 +    }
    1.99 +
   1.100 +
   1.101 +}
     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	Wed Oct 02 21:00:24 2013 +0200
     2.3 @@ -0,0 +1,331 @@
     2.4 +/*
     2.5 + * To change this license header, choose License Headers in Project Properties.
     2.6 + * To change this template file, choose Tools | Templates
     2.7 + * and open the template in the editor.
     2.8 + */
     2.9 +
    2.10 +package org.apidesign.bck2brwsr.dew;
    2.11 +
    2.12 +import java.io.BufferedReader;
    2.13 +import java.io.File;
    2.14 +import java.io.IOException;
    2.15 +import java.io.InputStreamReader;
    2.16 +import java.util.ArrayList;
    2.17 +import java.util.Collections;
    2.18 +import java.util.EnumSet;
    2.19 +import java.util.Enumeration;
    2.20 +import java.util.HashMap;
    2.21 +import java.util.Iterator;
    2.22 +import java.util.List;
    2.23 +import java.util.Map;
    2.24 +import java.util.Set;
    2.25 +import java.util.zip.ZipEntry;
    2.26 +import java.util.zip.ZipFile;
    2.27 +import javax.tools.FileObject;
    2.28 +import javax.tools.JavaFileManager;
    2.29 +import javax.tools.JavaFileObject;
    2.30 +import javax.tools.StandardLocation;
    2.31 +
    2.32 +/**
    2.33 + *
    2.34 + * @author Tomas Zezula
    2.35 + */
    2.36 +public class ClassLoaderFileManager implements JavaFileManager {
    2.37 +
    2.38 +    private static final Location[] READ_LOCATIONS = {
    2.39 +        StandardLocation.PLATFORM_CLASS_PATH,
    2.40 +        StandardLocation.CLASS_PATH,
    2.41 +        StandardLocation.SOURCE_PATH
    2.42 +    };
    2.43 +
    2.44 +    private static final Location[] WRITE_LOCATIONS = {
    2.45 +        StandardLocation.CLASS_OUTPUT,
    2.46 +        StandardLocation.SOURCE_OUTPUT
    2.47 +    };
    2.48 +
    2.49 +    private static final Location[] CLASS_LOADER_LOCATIONS = {
    2.50 +        StandardLocation.ANNOTATION_PROCESSOR_PATH
    2.51 +    };
    2.52 +
    2.53 +    private Map<Location, Map<String,List<MemoryFileObject>>> generated;
    2.54 +
    2.55 +
    2.56 +    ClassLoaderFileManager() {
    2.57 +        generated = new HashMap<>();
    2.58 +        for (Location l : WRITE_LOCATIONS) {
    2.59 +            generated.put(l, new HashMap<String, List<MemoryFileObject>>());
    2.60 +        }
    2.61 +    }
    2.62 +
    2.63 +
    2.64 +    @Override
    2.65 +    public ClassLoader getClassLoader(Location location) {
    2.66 +        if (canClassLoad(location)) {
    2.67 +            return getClass().getClassLoader();
    2.68 +        } else {
    2.69 +            return null;
    2.70 +        }
    2.71 +    }
    2.72 +
    2.73 +    @Override
    2.74 +    public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException {
    2.75 +        if (canRead(location)) {
    2.76 +            final List<JavaFileObject> res = new ArrayList<JavaFileObject>();
    2.77 +            for (String resource : getResources(convertFQNToResource(packageName))) {
    2.78 +                final JavaFileObject jfo = new ClassLoaderJavaFileObject(resource);
    2.79 +                if (kinds.contains(jfo.getKind())) {
    2.80 +                    res.add(jfo);
    2.81 +                }
    2.82 +            }
    2.83 +            return res;
    2.84 +        } else if (canWrite(location)) {
    2.85 +            Map<String,List<MemoryFileObject>> folders = generated.get(location);
    2.86 +            List<MemoryFileObject> files = folders.get(convertFQNToResource(packageName));
    2.87 +            if (files != null) {
    2.88 +                final List<JavaFileObject> res = new ArrayList<JavaFileObject>();
    2.89 +                for (JavaFileObject file : files) {
    2.90 +                    if (kinds.contains(file.getKind()) && file.getLastModified() >= 0) {
    2.91 +                        res.add(file);
    2.92 +                    }
    2.93 +                }
    2.94 +                return res;
    2.95 +            }
    2.96 +        }
    2.97 +        return Collections.<JavaFileObject>emptyList();
    2.98 +    }
    2.99 +
   2.100 +    @Override
   2.101 +    public String inferBinaryName(Location location, JavaFileObject file) {
   2.102 +        return ((InferableJavaFileObject)file).infer();
   2.103 +    }
   2.104 +
   2.105 +    @Override
   2.106 +    public boolean isSameFile(FileObject a, FileObject b) {
   2.107 +        return a.toUri().equals(b.toUri());
   2.108 +    }
   2.109 +
   2.110 +    @Override
   2.111 +    public boolean handleOption(String current, Iterator<String> remaining) {
   2.112 +        return false;
   2.113 +    }
   2.114 +
   2.115 +    @Override
   2.116 +    public boolean hasLocation(Location location) {
   2.117 +        for (Location l : StandardLocation.values()) {
   2.118 +            if (l.equals(location)) {
   2.119 +                return true;
   2.120 +            }
   2.121 +        }
   2.122 +        return false;
   2.123 +    }
   2.124 +
   2.125 +    @Override
   2.126 +    public JavaFileObject getJavaFileForInput(Location location, String className, JavaFileObject.Kind kind) throws IOException {
   2.127 +        if (canRead(location)) {
   2.128 +            return new ClassLoaderJavaFileObject(convertFQNToResource(className) + kind.extension);
   2.129 +        } else {
   2.130 +            throw new UnsupportedOperationException("Unsupported location for reading: " + location);   //NOI18N
   2.131 +        }
   2.132 +    }
   2.133 +
   2.134 +    @Override
   2.135 +    public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
   2.136 +        if (canWrite(location)) {
   2.137 +            final String resource = convertFQNToResource(className) + kind.extension;
   2.138 +            final MemoryFileObject res = new MemoryFileObject(resource, null);
   2.139 +            register(location, resource, res);
   2.140 +            return res;
   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 FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
   2.148 +        if (canRead(location)) {
   2.149 +            return new ClassLoaderJavaFileObject(convertFQNToResource(packageName) + '/' + relativeName); //NOI18N
   2.150 +        } else {
   2.151 +            throw new UnsupportedOperationException("Unsupported location for reading: " + location);   //NOI18N
   2.152 +        }
   2.153 +    }
   2.154 +
   2.155 +    @Override
   2.156 +    public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException {
   2.157 +        if (canWrite(location)) {
   2.158 +            final String resource = convertFQNToResource(packageName) + '/' + relativeName; //NOI18N
   2.159 +            final MemoryFileObject res = new MemoryFileObject(resource, null);
   2.160 +            register(location, resource, res);
   2.161 +            return res;
   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 void flush() throws IOException {
   2.169 +    }
   2.170 +
   2.171 +    @Override
   2.172 +    public void close() throws IOException {        
   2.173 +    }
   2.174 +
   2.175 +    @Override
   2.176 +    public int isSupportedOption(String option) {
   2.177 +        return -1;
   2.178 +    }
   2.179 +
   2.180 +//    private List<String> getResources(String folder) throws IOException {
   2.181 +//        final List<String> result = new ArrayList<String>();
   2.182 +//        final BufferedReader in = new BufferedReader(new InputStreamReader(
   2.183 +//                this.getClass().getClassLoader().getResourceAsStream(String.format("%s/pkg-list", folder.substring(0))),    //NOI18N
   2.184 +//                "UTF-8"));  //NOI18N
   2.185 +//        try {
   2.186 +//            String line;
   2.187 +//            while ((line = in.readLine()) != null) {
   2.188 +//                result.add(line);
   2.189 +//            }
   2.190 +//        } finally {
   2.191 +//            in.close();
   2.192 +//        }
   2.193 +//        return result;
   2.194 +//    }
   2.195 +
   2.196 +    //MOCK IMPL
   2.197 +    private List<String> getResources(String folder) throws IOException {
   2.198 +        if (classPathContent == null) {
   2.199 +            classPathContent = new HashMap<>();
   2.200 +//            final String boot = System.getProperty("sun.boot.class.path");  //NOI18N
   2.201 +            final String cp = System.getProperty("java.class.path");
   2.202 +            for (String entry : cp.split(File.pathSeparator)) {
   2.203 +                File f = new File (entry);
   2.204 +                if (f.canRead()) {
   2.205 +                    if (f.isFile()) {
   2.206 +                        ZipFile zf = new ZipFile(f);
   2.207 +                        try {
   2.208 +                            Enumeration<? extends ZipEntry> entries = zf.entries();
   2.209 +                            while (entries.hasMoreElements()) {
   2.210 +                                ZipEntry e = entries.nextElement();
   2.211 +                                if (e.isDirectory()) {
   2.212 +                                    continue;
   2.213 +                                }
   2.214 +                                final String name = String.format("/%s",e.getName());
   2.215 +                                final String owner = getOwner(name);
   2.216 +                                List<String> content = classPathContent.get(owner);
   2.217 +                                if (content == null) {
   2.218 +                                    content = new ArrayList<>();
   2.219 +                                    classPathContent.put(owner, content);
   2.220 +                                }
   2.221 +                                content.add(name);
   2.222 +                            }
   2.223 +                        } finally {
   2.224 +                            zf.close();
   2.225 +                        }
   2.226 +                    } else if (f.isDirectory()) {
   2.227 +                        addFiles(f,"/", classPathContent);
   2.228 +                    }
   2.229 +                }
   2.230 +            }                                    
   2.231 +        }
   2.232 +        List<String> content = classPathContent.get(folder);
   2.233 +        return content == null ? Collections.<String>emptyList() : content;
   2.234 +    }
   2.235 +
   2.236 +    private void addFiles(File folder, String path, Map<String,List<String>> into) {
   2.237 +        for (File f : folder.listFiles()) {
   2.238 +            String fname = path + (path.length() == 1 ? "" : "/") +  f.getName();
   2.239 +            if (f.isDirectory()) {
   2.240 +                addFiles(f, fname, into);
   2.241 +            } else {
   2.242 +                List<String> content = into.get(path);
   2.243 +                if (content == null) {
   2.244 +                    content = new ArrayList<>();
   2.245 +                    classPathContent.put(path, content);
   2.246 +                }
   2.247 +                content.add(fname);
   2.248 +            }
   2.249 +        }
   2.250 +    }
   2.251 +    
   2.252 +    private Map<String,List<String>> classPathContent;
   2.253 +
   2.254 +    private void register(Location loc, String resource, MemoryFileObject jfo) {
   2.255 +        Map<String,List<MemoryFileObject>> folders = generated.get(loc);
   2.256 +        final String folder = getOwner(resource);
   2.257 +        List<MemoryFileObject> content = folders.get(folder);
   2.258 +        if (content == null) {
   2.259 +            content = new ArrayList<>();
   2.260 +            folders.put(folder, content);
   2.261 +        }
   2.262 +        content.add(jfo);
   2.263 +    }
   2.264 +
   2.265 +    private static String getOwner(String resource) {
   2.266 +        int lastSlash = resource.lastIndexOf('/');
   2.267 +        assert lastSlash >= 0;
   2.268 +        return resource.substring(0, lastSlash);
   2.269 +    }
   2.270 +
   2.271 +    private static boolean canRead(Location loc) {
   2.272 +        for (Location rl : READ_LOCATIONS) {
   2.273 +            if (rl.equals(loc)) {
   2.274 +                return true;
   2.275 +            }
   2.276 +        }
   2.277 +        return false;
   2.278 +    }
   2.279 +
   2.280 +    private static boolean canWrite(Location loc) {
   2.281 +        for (Location wl : WRITE_LOCATIONS) {
   2.282 +            if (wl.equals(loc)) {
   2.283 +                return true;
   2.284 +            }
   2.285 +        }
   2.286 +        return false;
   2.287 +    }
   2.288 +
   2.289 +    private static boolean canClassLoad(Location loc) {
   2.290 +        for (Location cll : CLASS_LOADER_LOCATIONS) {
   2.291 +            if (cll.equals(loc)) {
   2.292 +                return true;
   2.293 +            }
   2.294 +        }
   2.295 +        return false;
   2.296 +    }
   2.297 +
   2.298 +    static String convertFQNToResource(String fqn) {
   2.299 +        return '/' + fqn.replace('.', '/');   //NOI18N
   2.300 +    }
   2.301 +
   2.302 +    static String convertResourceToFQN(String resource) {
   2.303 +        assert resource.startsWith("/");    //NOI18N
   2.304 +        int lastSlash = resource.lastIndexOf('/');  //NOI18N
   2.305 +        int lastDot = resource.lastIndexOf('.');    //NOI18N
   2.306 +        int stop = lastSlash < lastDot ?
   2.307 +            lastDot :
   2.308 +            resource.length();
   2.309 +        return resource.substring(1, stop).replace('/', '.');    //NOI18N
   2.310 +    }
   2.311 +
   2.312 +
   2.313 +    JavaFileObject createMemoryFileObject (String resourceName, JavaFileObject.Kind kind, byte[] content) {
   2.314 +        final InferableJavaFileObject jfo  = new MemoryFileObject(resourceName, kind, content);
   2.315 +        return jfo;
   2.316 +    }
   2.317 +
   2.318 +    Iterable<? extends MemoryFileObject> getGeneratedFiles(JavaFileObject.Kind... kinds) {
   2.319 +        final Set<JavaFileObject.Kind> ks = EnumSet.noneOf(JavaFileObject.Kind.class);
   2.320 +        Collections.addAll(ks, kinds);
   2.321 +        final List<MemoryFileObject> res = new ArrayList<>();
   2.322 +        for (Map<String,List<MemoryFileObject>> folders : generated.values()) {
   2.323 +            for (List<MemoryFileObject> content : folders.values()) {
   2.324 +                for (MemoryFileObject fo : content) {
   2.325 +                    if (ks.contains(fo.getKind()) && fo.getLastModified() >= 0) {
   2.326 +                        res.add(fo);
   2.327 +                    }
   2.328 +                }
   2.329 +            }
   2.330 +        }
   2.331 +        return res;
   2.332 +    }
   2.333 +
   2.334 +}
     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	Wed Oct 02 21:00:24 2013 +0200
     3.3 @@ -0,0 +1,81 @@
     3.4 +/*
     3.5 + * To change this license header, choose License Headers in Project Properties.
     3.6 + * To change this template file, choose Tools | Templates
     3.7 + * and open the template in the editor.
     3.8 + */
     3.9 +
    3.10 +package org.apidesign.bck2brwsr.dew;
    3.11 +
    3.12 +import java.io.BufferedReader;
    3.13 +import java.io.FileNotFoundException;
    3.14 +import java.io.IOException;
    3.15 +import java.io.InputStream;
    3.16 +import java.io.InputStreamReader;
    3.17 +import java.io.OutputStream;
    3.18 +import java.io.OutputStreamWriter;
    3.19 +import java.io.Reader;
    3.20 +import java.io.Writer;
    3.21 +
    3.22 +/**
    3.23 + *
    3.24 + * @author Tomas Zezula
    3.25 + */
    3.26 +class ClassLoaderJavaFileObject extends BaseFileObject {
    3.27 +
    3.28 +    ClassLoaderJavaFileObject(final String path) {
    3.29 +        super(path, getKind(path));
    3.30 +    }    
    3.31 +
    3.32 +    @Override
    3.33 +    public InputStream openInputStream() throws IOException {
    3.34 +        final InputStream in = getClass().getClassLoader().getResourceAsStream(path.substring(1));
    3.35 +        if (in == null) {
    3.36 +            getClass().getClassLoader().getResourceAsStream(path.substring(1));
    3.37 +            throw new FileNotFoundException(path);
    3.38 +
    3.39 +        }
    3.40 +        return in;
    3.41 +    }
    3.42 +
    3.43 +    @Override
    3.44 +    public OutputStream openOutputStream() throws IOException {
    3.45 +        throw new UnsupportedOperationException("Read Only FileObject");    //NOI18N
    3.46 +    }
    3.47 +
    3.48 +    @Override
    3.49 +    public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
    3.50 +        return new InputStreamReader(openInputStream());
    3.51 +    }
    3.52 +
    3.53 +    @Override
    3.54 +    public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
    3.55 +        final BufferedReader in = new BufferedReader(openReader(ignoreEncodingErrors));
    3.56 +        try {
    3.57 +            final StringBuilder sb = new StringBuilder();
    3.58 +            String line;
    3.59 +            while ((line = in.readLine()) != null) {
    3.60 +                sb.append(line);
    3.61 +                sb.append('\n');    //NOI18N
    3.62 +            }
    3.63 +            return sb.toString();
    3.64 +        } finally {
    3.65 +            in.close();
    3.66 +        }
    3.67 +    }
    3.68 +
    3.69 +    @Override
    3.70 +    public Writer openWriter() throws IOException {
    3.71 +        return new OutputStreamWriter(openOutputStream());
    3.72 +    }
    3.73 +
    3.74 +    @Override
    3.75 +    public long getLastModified() {
    3.76 +        return System.currentTimeMillis();
    3.77 +    }
    3.78 +
    3.79 +    @Override
    3.80 +    public boolean delete() {
    3.81 +        return false;
    3.82 +    }
    3.83 +
    3.84 +}
     4.1 --- a/dew/src/main/java/org/apidesign/bck2brwsr/dew/Compile.java	Fri Sep 27 20:20:50 2013 +0200
     4.2 +++ b/dew/src/main/java/org/apidesign/bck2brwsr/dew/Compile.java	Wed Oct 02 21:00:24 2013 +0200
     4.3 @@ -85,90 +85,35 @@
     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 +        final Boolean res = ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", "1.7", "-target", "1.7"), null, Arrays.asList(file)).call();
    4.96 +
    4.97  
    4.98          Map<String, byte[]> result = new HashMap<>();
    4.99 -
   4.100 -        for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
   4.101 -            result.put(e.getKey(), e.getValue().toByteArray());
   4.102 +        for (MemoryFileObject generated : clfm.getGeneratedFiles(Kind.CLASS)) {
   4.103 +            result.put(generated.infer(), generated.getContent());
   4.104          }
   4.105 -
   4.106          return result;
   4.107      }
   4.108  
     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	Wed Oct 02 21:00:24 2013 +0200
     5.3 @@ -0,0 +1,17 @@
     5.4 +/*
     5.5 + * To change this license header, choose License Headers in Project Properties.
     5.6 + * To change this template file, choose Tools | Templates
     5.7 + * and open the template in the editor.
     5.8 + */
     5.9 +
    5.10 +package org.apidesign.bck2brwsr.dew;
    5.11 +
    5.12 +import javax.tools.JavaFileObject;
    5.13 +
    5.14 +/**
    5.15 + *
    5.16 + * @author Tomas Zezula
    5.17 + */
    5.18 +interface InferableJavaFileObject extends JavaFileObject {
    5.19 +    String infer();
    5.20 +}
     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	Wed Oct 02 21:00:24 2013 +0200
     6.3 @@ -0,0 +1,125 @@
     6.4 +/*
     6.5 + * To change this license header, choose License Headers in Project Properties.
     6.6 + * To change this template file, choose Tools | Templates
     6.7 + * and open the template in the editor.
     6.8 + */
     6.9 +
    6.10 +package org.apidesign.bck2brwsr.dew;
    6.11 +
    6.12 +import java.io.ByteArrayInputStream;
    6.13 +import java.io.ByteArrayOutputStream;
    6.14 +import java.io.IOException;
    6.15 +import java.io.InputStream;
    6.16 +import java.io.InputStreamReader;
    6.17 +import java.io.OutputStream;
    6.18 +import java.io.OutputStreamWriter;
    6.19 +import java.io.Reader;
    6.20 +import java.io.Writer;
    6.21 +
    6.22 +/**
    6.23 + *
    6.24 + * @author Tomas Zeuzla
    6.25 + */
    6.26 +class MemoryFileObject extends BaseFileObject {
    6.27 +
    6.28 +    private byte[] content;
    6.29 +    private long lastModified;
    6.30 +
    6.31 +    MemoryFileObject (
    6.32 +            String resourceName,
    6.33 +            Kind kind,
    6.34 +            byte[] content) {
    6.35 +        super(resourceName, kind);
    6.36 +        this.content = content;
    6.37 +        this.lastModified = this.content == null ?
    6.38 +            -1 :
    6.39 +            System.currentTimeMillis();
    6.40 +    }
    6.41 +
    6.42 +    MemoryFileObject (
    6.43 +            String resourceName,
    6.44 +            byte[] content) {
    6.45 +        this(resourceName, getKind(resourceName) ,content);
    6.46 +    }
    6.47 +
    6.48 +
    6.49 +    @Override
    6.50 +    public InputStream openInputStream() throws IOException {
    6.51 +        if (content == null) {
    6.52 +            throw new IOException();
    6.53 +        } else {
    6.54 +            return new ByteArrayInputStream(content);
    6.55 +        }
    6.56 +    }
    6.57 +
    6.58 +    @Override
    6.59 +    public OutputStream openOutputStream() throws IOException {
    6.60 +        return new CloseStream();
    6.61 +    }
    6.62 +
    6.63 +    @Override
    6.64 +    public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
    6.65 +        return new InputStreamReader(openInputStream());
    6.66 +    }
    6.67 +
    6.68 +    @Override
    6.69 +    public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
    6.70 +        if (content == null) {
    6.71 +            throw new IOException();
    6.72 +        } else {
    6.73 +            return new String(content);
    6.74 +        }
    6.75 +    }
    6.76 +
    6.77 +    @Override
    6.78 +    public Writer openWriter() throws IOException {
    6.79 +        return new OutputStreamWriter(openOutputStream());
    6.80 +    }
    6.81 +
    6.82 +    @Override
    6.83 +    public long getLastModified() {
    6.84 +        return lastModified;
    6.85 +    }
    6.86 +
    6.87 +    @Override
    6.88 +    public boolean delete() {
    6.89 +        return false;
    6.90 +    }
    6.91 +
    6.92 +    byte[] getContent() {
    6.93 +        return content;
    6.94 +    }
    6.95 +
    6.96 +    private class CloseStream extends OutputStream {
    6.97 +
    6.98 +        private final ByteArrayOutputStream delegate;
    6.99 +
   6.100 +        CloseStream() {
   6.101 +            delegate = new ByteArrayOutputStream();
   6.102 +        }
   6.103 +
   6.104 +        @Override
   6.105 +        public void write(int b) throws IOException {
   6.106 +            delegate.write(b);
   6.107 +        }
   6.108 +
   6.109 +        @Override
   6.110 +        public void write(byte[] b) throws IOException {
   6.111 +            delegate.write(b);
   6.112 +        }
   6.113 +
   6.114 +        @Override
   6.115 +        public void write(byte[] b, int off, int len) throws IOException {
   6.116 +            delegate.write(b, off, len);
   6.117 +        }
   6.118 +
   6.119 +        @Override
   6.120 +        public void close() throws IOException {
   6.121 +            delegate.close();
   6.122 +            content = delegate.toByteArray();
   6.123 +            lastModified = System.currentTimeMillis();
   6.124 +        }                                    
   6.125 +
   6.126 +    }
   6.127 +
   6.128 +}