1*e17b4558SAndroid Build Coastguard Worker /* 2*e17b4558SAndroid Build Coastguard Worker * Copyright (C) 2011 The Android Open Source Project 3*e17b4558SAndroid Build Coastguard Worker * 4*e17b4558SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*e17b4558SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*e17b4558SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*e17b4558SAndroid Build Coastguard Worker * 8*e17b4558SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*e17b4558SAndroid Build Coastguard Worker * 10*e17b4558SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*e17b4558SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*e17b4558SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*e17b4558SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*e17b4558SAndroid Build Coastguard Worker * limitations under the License. 15*e17b4558SAndroid Build Coastguard Worker */ 16*e17b4558SAndroid Build Coastguard Worker 17*e17b4558SAndroid Build Coastguard Worker package vogar.tasks; 18*e17b4558SAndroid Build Coastguard Worker 19*e17b4558SAndroid Build Coastguard Worker import java.io.File; 20*e17b4558SAndroid Build Coastguard Worker import java.io.FileNotFoundException; 21*e17b4558SAndroid Build Coastguard Worker import java.io.FileOutputStream; 22*e17b4558SAndroid Build Coastguard Worker import java.io.IOException; 23*e17b4558SAndroid Build Coastguard Worker import java.io.OutputStream; 24*e17b4558SAndroid Build Coastguard Worker import java.util.Collections; 25*e17b4558SAndroid Build Coastguard Worker import java.util.HashSet; 26*e17b4558SAndroid Build Coastguard Worker import java.util.Properties; 27*e17b4558SAndroid Build Coastguard Worker import java.util.Set; 28*e17b4558SAndroid Build Coastguard Worker import java.util.regex.Pattern; 29*e17b4558SAndroid Build Coastguard Worker 30*e17b4558SAndroid Build Coastguard Worker import com.google.common.collect.Sets; 31*e17b4558SAndroid Build Coastguard Worker 32*e17b4558SAndroid Build Coastguard Worker import vogar.Action; 33*e17b4558SAndroid Build Coastguard Worker import vogar.Classpath; 34*e17b4558SAndroid Build Coastguard Worker import vogar.Driver; 35*e17b4558SAndroid Build Coastguard Worker import vogar.Mode; 36*e17b4558SAndroid Build Coastguard Worker import vogar.Outcome; 37*e17b4558SAndroid Build Coastguard Worker import vogar.Result; 38*e17b4558SAndroid Build Coastguard Worker import vogar.Run; 39*e17b4558SAndroid Build Coastguard Worker import vogar.TestProperties; 40*e17b4558SAndroid Build Coastguard Worker import vogar.Toolchain; 41*e17b4558SAndroid Build Coastguard Worker import vogar.commands.Command; 42*e17b4558SAndroid Build Coastguard Worker import vogar.commands.CommandFailedException; 43*e17b4558SAndroid Build Coastguard Worker import vogar.commands.Javac; 44*e17b4558SAndroid Build Coastguard Worker 45*e17b4558SAndroid Build Coastguard Worker /** 46*e17b4558SAndroid Build Coastguard Worker * Compiles classes for the given action and makes them ready for execution. 47*e17b4558SAndroid Build Coastguard Worker */ 48*e17b4558SAndroid Build Coastguard Worker public final class BuildActionTask extends Task { 49*e17b4558SAndroid Build Coastguard Worker private static final Pattern JAVA_SOURCE_PATTERN = Pattern.compile("\\/(\\w)+\\.java$"); 50*e17b4558SAndroid Build Coastguard Worker 51*e17b4558SAndroid Build Coastguard Worker private final Action action; 52*e17b4558SAndroid Build Coastguard Worker private final Run run; 53*e17b4558SAndroid Build Coastguard Worker private final Driver driver; 54*e17b4558SAndroid Build Coastguard Worker private final File outputFile; 55*e17b4558SAndroid Build Coastguard Worker BuildActionTask(Run run, Action action, Driver driver, File outputFile)56*e17b4558SAndroid Build Coastguard Worker public BuildActionTask(Run run, Action action, Driver driver, File outputFile) { 57*e17b4558SAndroid Build Coastguard Worker super("build " + action.getName()); 58*e17b4558SAndroid Build Coastguard Worker this.run = run; 59*e17b4558SAndroid Build Coastguard Worker this.action = action; 60*e17b4558SAndroid Build Coastguard Worker this.driver = driver; 61*e17b4558SAndroid Build Coastguard Worker this.outputFile = outputFile; 62*e17b4558SAndroid Build Coastguard Worker } 63*e17b4558SAndroid Build Coastguard Worker execute()64*e17b4558SAndroid Build Coastguard Worker @Override protected Result execute() throws Exception { 65*e17b4558SAndroid Build Coastguard Worker try { 66*e17b4558SAndroid Build Coastguard Worker compile(action, outputFile); 67*e17b4558SAndroid Build Coastguard Worker return Result.SUCCESS; 68*e17b4558SAndroid Build Coastguard Worker } catch (CommandFailedException e) { 69*e17b4558SAndroid Build Coastguard Worker driver.addEarlyResult(new Outcome(action.getName(), Result.COMPILE_FAILED, 70*e17b4558SAndroid Build Coastguard Worker e.getOutputLines())); 71*e17b4558SAndroid Build Coastguard Worker return Result.COMPILE_FAILED; 72*e17b4558SAndroid Build Coastguard Worker } catch (IOException e) { 73*e17b4558SAndroid Build Coastguard Worker driver.addEarlyResult(new Outcome(action.getName(), Result.ERROR, e)); 74*e17b4558SAndroid Build Coastguard Worker return Result.ERROR; 75*e17b4558SAndroid Build Coastguard Worker } 76*e17b4558SAndroid Build Coastguard Worker } 77*e17b4558SAndroid Build Coastguard Worker 78*e17b4558SAndroid Build Coastguard Worker /** 79*e17b4558SAndroid Build Coastguard Worker * Returns the .jar file containing the action's compiled classes. 80*e17b4558SAndroid Build Coastguard Worker * 81*e17b4558SAndroid Build Coastguard Worker * @throws CommandFailedException if javac fails 82*e17b4558SAndroid Build Coastguard Worker */ compile(Action action, File jar)83*e17b4558SAndroid Build Coastguard Worker private void compile(Action action, File jar) throws IOException { 84*e17b4558SAndroid Build Coastguard Worker File classesDir = run.localFile(action, "classes"); 85*e17b4558SAndroid Build Coastguard Worker run.mkdir.mkdirs(classesDir); 86*e17b4558SAndroid Build Coastguard Worker createJarMetadataFiles(action, classesDir); 87*e17b4558SAndroid Build Coastguard Worker 88*e17b4558SAndroid Build Coastguard Worker Set<File> sourceFiles = new HashSet<File>(); 89*e17b4558SAndroid Build Coastguard Worker File javaFile = action.getJavaFile(); 90*e17b4558SAndroid Build Coastguard Worker Javac javac = new Javac(run.log, run.javaPath("javac")); 91*e17b4558SAndroid Build Coastguard Worker if (run.debugging) { 92*e17b4558SAndroid Build Coastguard Worker javac.debug(); 93*e17b4558SAndroid Build Coastguard Worker } 94*e17b4558SAndroid Build Coastguard Worker if (javaFile == null) { 95*e17b4558SAndroid Build Coastguard Worker if (JAVA_SOURCE_PATTERN.matcher(action.getTargetClass()).find()) { 96*e17b4558SAndroid Build Coastguard Worker // This is likely a missing source file rather than a class 97*e17b4558SAndroid Build Coastguard Worker // named something.java.... 98*e17b4558SAndroid Build Coastguard Worker throw new FileNotFoundException("Unlikely classname, assuming missing source file: " 99*e17b4558SAndroid Build Coastguard Worker + action.getTargetClass()); 100*e17b4558SAndroid Build Coastguard Worker } 101*e17b4558SAndroid Build Coastguard Worker } else { 102*e17b4558SAndroid Build Coastguard Worker if (!JAVA_SOURCE_PATTERN.matcher(javaFile.toString()).find()) { 103*e17b4558SAndroid Build Coastguard Worker throw new CommandFailedException(Collections.<String>emptyList(), 104*e17b4558SAndroid Build Coastguard Worker Collections.singletonList("Cannot compile: " + javaFile)); 105*e17b4558SAndroid Build Coastguard Worker } 106*e17b4558SAndroid Build Coastguard Worker sourceFiles.add(javaFile); 107*e17b4558SAndroid Build Coastguard Worker Classpath sourceDirs = Classpath.of(action.getSourcePath()); 108*e17b4558SAndroid Build Coastguard Worker sourceDirs.addAll(run.sourcepath); 109*e17b4558SAndroid Build Coastguard Worker javac.sourcepath(sourceDirs.getElements()); 110*e17b4558SAndroid Build Coastguard Worker } 111*e17b4558SAndroid Build Coastguard Worker if (!sourceFiles.isEmpty()) { 112*e17b4558SAndroid Build Coastguard Worker if (!run.buildClasspath.isEmpty()) { 113*e17b4558SAndroid Build Coastguard Worker javac.bootClasspath(run.buildClasspath); 114*e17b4558SAndroid Build Coastguard Worker } 115*e17b4558SAndroid Build Coastguard Worker javac.classpath(run.classpath) 116*e17b4558SAndroid Build Coastguard Worker .destination(classesDir) 117*e17b4558SAndroid Build Coastguard Worker .javaVersion(run.language.getJavacSourceAndTarget()) 118*e17b4558SAndroid Build Coastguard Worker .extra(run.javacArgs) 119*e17b4558SAndroid Build Coastguard Worker .compile(sourceFiles); 120*e17b4558SAndroid Build Coastguard Worker } 121*e17b4558SAndroid Build Coastguard Worker 122*e17b4558SAndroid Build Coastguard Worker new Command(run.log, run.javaPath("jar"), "cvfM", jar.getPath(), 123*e17b4558SAndroid Build Coastguard Worker "-C", classesDir.getPath(), "./").execute(); 124*e17b4558SAndroid Build Coastguard Worker } 125*e17b4558SAndroid Build Coastguard Worker 126*e17b4558SAndroid Build Coastguard Worker /** 127*e17b4558SAndroid Build Coastguard Worker * Writes files to {@code classesDir} to be included in the .jar file for 128*e17b4558SAndroid Build Coastguard Worker * {@code action}. 129*e17b4558SAndroid Build Coastguard Worker */ createJarMetadataFiles(Action action, File classesDir)130*e17b4558SAndroid Build Coastguard Worker private void createJarMetadataFiles(Action action, File classesDir) throws IOException { 131*e17b4558SAndroid Build Coastguard Worker OutputStream propertiesOut 132*e17b4558SAndroid Build Coastguard Worker = new FileOutputStream(new File(classesDir, TestProperties.FILE)); 133*e17b4558SAndroid Build Coastguard Worker Properties properties = new Properties(); 134*e17b4558SAndroid Build Coastguard Worker fillInProperties(properties, action); 135*e17b4558SAndroid Build Coastguard Worker properties.store(propertiesOut, "generated by " + Mode.class.getName()); 136*e17b4558SAndroid Build Coastguard Worker propertiesOut.close(); 137*e17b4558SAndroid Build Coastguard Worker } 138*e17b4558SAndroid Build Coastguard Worker 139*e17b4558SAndroid Build Coastguard Worker /** 140*e17b4558SAndroid Build Coastguard Worker * Fill in properties for running in this mode 141*e17b4558SAndroid Build Coastguard Worker */ fillInProperties(Properties properties, Action action)142*e17b4558SAndroid Build Coastguard Worker private void fillInProperties(Properties properties, Action action) { 143*e17b4558SAndroid Build Coastguard Worker properties.setProperty(TestProperties.TEST_CLASS_OR_PACKAGE, action.getTargetClass()); 144*e17b4558SAndroid Build Coastguard Worker properties.setProperty(TestProperties.MONITOR_PORT, Integer.toString(run.firstMonitorPort)); 145*e17b4558SAndroid Build Coastguard Worker properties.setProperty(TestProperties.TIMEOUT, Integer.toString(run.timeoutSeconds)); 146*e17b4558SAndroid Build Coastguard Worker properties.setProperty(TestProperties.RUNNER_TYPE, run.runnerType.toString()); 147*e17b4558SAndroid Build Coastguard Worker } 148*e17b4558SAndroid Build Coastguard Worker } 149