import org.apache.tools.ant.util.TeeOutputStream class Tags { Boolean mainMethod = false Boolean compileTimeError = false Boolean throwsException = false Boolean errorOutputExpected = false Boolean validateByHand = false Boolean ignoreOutput = false // probably don't need this tag String fileRoot String mainClass String javaCmd = null List args = [] List jVMArgs = [] String exec = null String runFirst = null private List lines private String block def Tags(List lines) { this.lines = lines block = lines.join('') mainMethod = block.contains('main(String[] args)') fileRoot = lines[0].split("/")[-1] - ".java" mainClass = fileRoot javaCmd = extract('main:') if(javaCmd) mainClass = javaCmd compileTimeError = testFor('CompileTimeError') throwsException = testFor('ThrowsException') errorOutputExpected = testFor('ErrorOutputExpected') validateByHand = testFor('ValidateByHand') ignoreOutput = testFor('IgnoreOutput') def argString = extract('Args:') if(argString) args = argString.split(' ') def jvmArgString = extract('JVMArgs:') if(jvmArgString) jVMArgs = jvmArgString.split(' ') exec = extract('Exec:') runFirst = extract('RunFirst:') } private def testFor(String marker) { return block.contains("// {" + marker + "}") } private def extract(String marker) { if(!block.contains("// {" + marker)) return null def re = "\\/\\/ \\{" + marker + /[^}]+}/ def tagline = block =~ re if(tagline.getCount()) { def rtrim = tagline[0].reverse().dropWhile{ it != '}'}.reverse()[0..-2] def ltrim = rtrim - ("// {" + marker) return ltrim.trim() } else { println "Searching for: " + re println block System.exit(1) } } public boolean hasTags() { return compileTimeError || throwsException || errorOutputExpected || validateByHand || ignoreOutput || javaCmd || args || jVMArgs || exec || runFirst } public String toString() { String result = "" for(ln in lines) if(ln.startsWith("//") || ln.startsWith("package ")) result += ln + "\n" else break if(mainMethod) result += "mainMethod: " + mainMethod + "\n" if(compileTimeError) result += "compileTimeError: " + compileTimeError + "\n" if(throwsException) result += "throwsException: " + throwsException + "\n" if(errorOutputExpected) result += "errorOutputExpected: " + errorOutputExpected + "\n" if(validateByHand) result += "validateByHand: " + validateByHand + "\n" if(ignoreOutput) result += "ignoreOutput: " + ignoreOutput + "\n" if(javaCmd) result += "javaCmd: " + javaCmd + "\n" if(args) result += "args: " + args + "\n" if(jVMArgs) result += "jVMArgs: " + jVMArgs + "\n" if(exec) result += "exec: " + exec + "\n" if(runFirst) result += "runFirst: " + runFirst + "\n" return result } } 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() Tags tags = new Tags(lines) // Not used yet; just for demo // if(tags.hasTags()) println tags // Trace output for debugging // Add tasks for java sources with main methods if ((tags.mainMethod || tags.javaCmd) && (!tags.compileTimeError)) { if (!tags.validateByHand) { // only add tasks that we know we can run successfully to the task list tasks.add(tags.fileRoot) } // 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 = (tags.validateByHand || tags.throwsException) 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 "$tags.fileRoot"(type: JavaExec, dependsOn: maybeRunFirst) { main = tags.mainClass classpath = sourceSets.main.runtimeClasspath args = tags.args jvmArgs = tags.jVMArgs ignoreExitValue = maybeIgnoreExitValue standardOutput = runStandardOutput errorOutput = runErrorOutput } << { runStandardOutput.close() runErrorOutput.close() if (outFile.size() == 0) outFile.delete() if (errFile.size() == 0) errFile.delete() } } // exclude java sources that will not compile if (tags.compileTimeError) { sourceSets.main.java.excludes.add(it.name) } } } task run(dependsOn: tasks) } configure(subprojects - project(':onjava')) { dependencies { compile project(':onjava') } }