import org.apache.tools.ant.util.TeeOutputStream subprojects { apply plugin: 'java' sourceCompatibility = '1.8' targetCompatibility = '1.8' repositories { mavenLocal() mavenCentral() } sourceSets { main { java { srcDir projectDir } } } List tasks = [] projectDir.eachFileRecurse { if (it.name.endsWith('.java')) { List lines = it.readLines() Boolean hasMainMethod = lines.join('').contains('main(String[] args)') Boolean hasMainParam = lines.find { it.startsWith('// {main: ')} Boolean willNotCompile = lines.find { it.startsWith('// {CompileTimeError') } Boolean validateByHand = lines.find { it.startsWith('// {ValidateByHand}') } Boolean throwsException = lines.find { it.startsWith('// {ThrowsException}') } // add tasks for java sources with main methods if ((hasMainMethod || hasMainParam) && (!willNotCompile)) { String maybeArgsLine = lines.find { it.startsWith('// {Args: ')} List maybeArgs = [] if (maybeArgsLine != null) { maybeArgs = maybeArgsLine.trim().replaceAll('\\/\\/ \\{Args: ', '').reverse().replaceFirst('}', '').reverse().split(' ') } String mainClass = it.name.replaceAll('.java', '') String taskName = mainClass if (!validateByHand) { // only add tasks that we know we can run successfully to the task list tasks.add(taskName) } // some java sources with a main method specify a different main class String maybeMainLine = lines.find { it.startsWith('// {main: ')} if (maybeMainLine != null) { mainClass = maybeMainLine.trim().replaceAll('\\/\\/ \\{main: ', '').replaceAll('}', '') } // some java sources with JVM args List maybeJvmArgs = [] String maybeJvmArgsLine = lines.find { it.startsWith('// {JVMArgs: ')} if (maybeJvmArgsLine != null) { maybeJvmArgs = maybeJvmArgsLine.trim().replaceAll('\\/\\/ \\{JVMArgs: ', '').replaceAll('}', '').split(' ') } // some java sources depend on others to be run first String maybeRunFirst = null String maybeRunFirstLine = lines.find { it.startsWith('// {RunFirst: ')} if (maybeRunFirstLine != null) { maybeRunFirst = maybeRunFirstLine.trim().replaceAll('\\/\\/ \\{RunFirst: ', '').replaceAll('}', '') } // some java apps intentionally throw an exception Boolean maybeIgnoreExitValue = (validateByHand || throwsException) // some java apps need a timeout Boolean timeOutDuringTesting = false if (lines.find { it.startsWith('// {TimeOutDuringTesting}') } != null) { timeOutDuringTesting = true } // create run and test tasks if (timeOutDuringTesting) { // todo: apps with timeOutDuringTesting need special handling task "$taskName" << { println "not implemented" } } else { String basePath = it.absolutePath.replaceAll('\\.java', '') File outFile = new File(basePath + '.out') File errFile = new File(basePath + '.err') OutputStream runStandardOutput = new TeeOutputStream(new FileOutputStream(outFile), System.out) OutputStream runErrorOutput = new TeeOutputStream(new FileOutputStream(errFile), System.err) task "$taskName"(type: JavaExec, dependsOn: maybeRunFirst) { main = mainClass classpath = sourceSets.main.runtimeClasspath args = maybeArgs jvmArgs = maybeJvmArgs ignoreExitValue = maybeIgnoreExitValue standardOutput = runStandardOutput errorOutput = runErrorOutput addShutdownHook { runStandardOutput.close() runErrorOutput.close() if (outFile.size() == 0) outFile.delete() if (errFile.size() == 0) errFile.delete() } } } } // exclude java sources that will not compile if (willNotCompile) { sourceSets.main.java.excludes.add(it.name) } } } task run(dependsOn: tasks) } configure(subprojects - project(':onjava')) { dependencies { compile project(':onjava') } }