/* * Copyright 2013 eXo Platform SAS * * 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 juzu.test; import junit.framework.Assert; import juzu.impl.compiler.CompilationException; import juzu.impl.compiler.Compiler; import juzu.impl.compiler.CompilerConfig; import juzu.impl.fs.Change; import juzu.impl.fs.FileSystemScanner; import juzu.impl.fs.Filter; import juzu.impl.fs.Snapshot; import juzu.impl.fs.spi.ReadFileSystem; import juzu.impl.fs.spi.ReadWriteFileSystem; import juzu.impl.common.Tools; import juzu.impl.fs.spi.disk.DiskFileSystem; import juzu.impl.fs.spi.ram.RAMFileSystem; import javax.annotation.processing.Processor; import javax.inject.Provider; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; /** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */ public abstract class CompileStrategy<I, O> { /** . */ final LinkedList<ReadFileSystem<?>> classPath; /** . */ final ReadWriteFileSystem<I> sourcePath; /** . */ final ReadWriteFileSystem<O> sourceOutput; /** . */ final ReadWriteFileSystem<O> classOutput; /** . */ JavaCompilerProvider javaCompiler; /** . */ Provider<? extends Processor> processorFactory; /** . */ final CompilerConfig config; public CompileStrategy( ReadWriteFileSystem<I> sourcePath, ReadWriteFileSystem<O> sourceOutput, ReadWriteFileSystem<O> classOutput) { // this.classPath = new LinkedList<ReadFileSystem<?>>(); this.sourcePath = sourcePath; this.sourceOutput = sourceOutput; this.classOutput = classOutput; this.config = new CompilerConfig().force(true); } final Compiler.Builder builder() { Compiler.Builder builder = Compiler.builder(); builder.javaCompiler(javaCompiler); builder.processor(processorFactory); builder.addClassPath(classPath); builder.sourcePath(sourcePath); builder.sourceOutput(sourceOutput); builder.classOutput(classOutput); builder.config(config); return builder; } Compiler compiler; abstract void compile() throws IOException, CompilationException; void addClassPath(ReadFileSystem<?> classPath) { this.classPath.add(classPath); } /** . */ private static final Pattern javaFilePattern = Pattern.compile("(.+)\\.java"); public static class Incremental<I, O> extends CompileStrategy<I, O> { /** . */ final FileSystemScanner<I> scanner; /** . */ private Snapshot<I> snapshot; public Incremental( ReadWriteFileSystem<I> sourcePath, ReadWriteFileSystem<O> sourceOutput, ReadWriteFileSystem<O> classOutput) { super(sourcePath, sourceOutput, classOutput); // this.scanner = FileSystemScanner.createHashing(sourcePath); this.snapshot = scanner.take(); } void compile() throws IOException, CompilationException { Compiler.Builder builder = builder(); // List<String> toCompile = new ArrayList<String>(); List<String> toDelete = new ArrayList<String>(); // Scan the sources snapshot = snapshot.scan(); for (Map.Entry<String, Change> change : snapshot.getChanges().entrySet()) { String path = change.getKey(); if (path.endsWith(".java")) { switch (change.getValue()) { case REMOVE: toDelete.add(path); break; case ADD: toCompile.add(path); break; case UPDATE: toCompile.add(path); toDelete.add(path); break; } } } // Delete the classes corresponding to the deleted classes for (String s : toDelete) { Matcher matcher = javaFilePattern.matcher(s); Assert.assertTrue(matcher.matches()); String path = matcher.group(1) + ".class"; String[] names = Tools.split(path, '/'); O clazz = classOutput.getPath(names); if (clazz != null) { classOutput.removePath(clazz); } } // Make the current classoutput part of the classpath if (classOutput.size(ReadFileSystem.FILE) > 0) { File root = File.createTempFile("juzu", ""); Assert.assertTrue(root.delete()); Assert.assertTrue(root.mkdirs()); root.deleteOnExit(); ReadWriteFileSystem classes = new DiskFileSystem(root); classOutput.copy(new Filter.Default<O>() { @Override public boolean acceptFile(O file, String name) throws IOException { return name.endsWith(".class"); } }, classes); builder.addClassPath(classes); } // Add our classpath to the compiler classpath for (ReadFileSystem<?> cp : classPath) { builder.addClassPath(cp); } // compiler = builder.build(); compiler.compile(toCompile.toArray(new String[toCompile.size()])); } } public static class Batch<I, O> extends CompileStrategy<I, O> { public Batch( ReadFileSystem<?> classPath, ReadWriteFileSystem<I> sourcePath, ReadWriteFileSystem<O> sourceOutput, ReadWriteFileSystem<O> classOutput) { super(sourcePath, sourceOutput, classOutput); } void compile() throws IOException, CompilationException { compiler = builder().build(); compiler.compile(); } } }