diff --git a/build.gradle b/build.gradle index b87c3f0ead..460f7199e6 100644 --- a/build.gradle +++ b/build.gradle @@ -29,11 +29,12 @@ configure(javaProjects) { } configure(coreModuleProjects) { - apply from: "$rootDir/gradle/bundlor.gradle" - apply from: "$rootDir/gradle/maven-deployment.gradle" - apply from: "$rootDir/gradle/emma.gradle" // Gives better names in structure101 jar diagram sourceSets.main.classesDir = new File(buildDir, "classes/" + project.name.substring("spring-security".length() + 1)) + apply plugin: 'bundlor' + bundlor.expansions = bundlorProperties + apply from: "$rootDir/gradle/maven-deployment.gradle" + apply plugin: 'emma' } task coreBuild { @@ -41,7 +42,7 @@ task coreBuild { } configure (aspectjProjects) { - apply from: "$rootDir/gradle/aspectj.gradle" + apply plugin: 'aspectj' } apply from: "$rootDir/gradle/dist.gradle" diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index d0e61f4193..f2e04a3039 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -32,7 +32,23 @@ dependencies { compile 'com.google.appengine:appengine-tools-sdk:1.4.2' } +dependencies{ + compile "emma:emma:2.0.5312" +} + +// Bundlor +dependencies { + compile 'com.springsource.bundlor:com.springsource.bundlor:1.0.0.RELEASE', + 'com.springsource.bundlor:com.springsource.bundlor.blint:1.0.0.RELEASE' +} + task ide(type: Copy) { from configurations.runtime into 'ide' } + +apply plugin: 'idea' + +ideaModule { + excludeDirs += file('.gradle') +} diff --git a/buildSrc/src/main/groovy/aspectj/AspectJPlugin.groovy b/buildSrc/src/main/groovy/aspectj/AspectJPlugin.groovy new file mode 100644 index 0000000000..1a445b8ba5 --- /dev/null +++ b/buildSrc/src/main/groovy/aspectj/AspectJPlugin.groovy @@ -0,0 +1,76 @@ +package aspectj + +import org.gradle.api.Project +import org.gradle.api.Plugin +import org.gradle.api.tasks.TaskAction +import org.gradle.api.logging.LogLevel +import org.gradle.api.file.FileCollection +import org.gradle.api.tasks.SourceSet +import org.gradle.api.DefaultTask +import org.gradle.api.GradleException + +/** + * + * @author Luke Taylor + */ +class AspectJPlugin implements Plugin { + + void apply(Project project) { + if (!project.hasProperty('aspectjVersion')) { + throw new GradleException("You must set the property 'aspectjVersion' before applying the aspectj plugin") + } + + if (project.configurations.findByName('ajtools') == null) { + project.configurations.add('ajtools') + project.dependencies { + ajtools "org.aspectj:aspectjtools:${project.aspectjVersion}" + compile "org.aspectj:aspectjrt:${project.aspectjVersion}" + } + } + + if (project.configurations.findByName('aspectpath') == null) { + project.configurations.add('aspectpath') + } + + project.tasks.add(name: 'compileJava', overwrite: true, description: 'Compiles AspectJ Source', type: Ajc) { + dependsOn project.processResources + sourceSet = project.sourceSets.main + inputs.files(sourceSet.java.srcDirs) + outputs.dir(sourceSet.classesDir) + aspectPath = project.configurations.aspectpath + } + + project.tasks.add(name: 'compileTestJava', overwrite: true, description: 'Compiles AspectJ Test Source', type: Ajc) { + dependsOn project.processTestResources, project.compileJava, project.jar + sourceSet = project.sourceSets.test + inputs.files(sourceSet.java.srcDirs) + outputs.dir(sourceSet.classesDir) + aspectPath = project.files(project.configurations.aspectpath, project.jar.archivePath) + } + } +} + +class Ajc extends DefaultTask { + SourceSet sourceSet + FileCollection aspectPath + + Ajc() { + logging.captureStandardOutput(LogLevel.INFO) + } + + @TaskAction + def compile() { + logger.info("Running ajc ...") + ant.taskdef(resource: "org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties", classpath: project.configurations.ajtools.asPath) + ant.iajc(classpath: sourceSet.compileClasspath.asPath, fork: 'true', destDir: sourceSet.classesDir.absolutePath, + source: project.convention.plugins.java.sourceCompatibility, + target: project.convention.plugins.java.targetCompatibility, + aspectPath: aspectPath.asPath, sourceRootCopyFilter: '**/*.java', showWeaveInfo: 'true') { + sourceroots { + sourceSet.java.srcDirs.each { + pathelement(location: it.absolutePath) + } + } + } + } +} diff --git a/buildSrc/src/main/groovy/bundlor/BundlorPlugin.groovy b/buildSrc/src/main/groovy/bundlor/BundlorPlugin.groovy new file mode 100644 index 0000000000..c900280a0b --- /dev/null +++ b/buildSrc/src/main/groovy/bundlor/BundlorPlugin.groovy @@ -0,0 +1,136 @@ +package bundlor + +import com.springsource.bundlor.ClassPath +import com.springsource.bundlor.ManifestGenerator +import com.springsource.bundlor.ManifestWriter +import com.springsource.bundlor.blint.ManifestValidator +import com.springsource.bundlor.blint.support.DefaultManifestValidatorContributorsFactory +import com.springsource.bundlor.blint.support.StandardManifestValidator +import com.springsource.bundlor.support.DefaultManifestGeneratorContributorsFactory +import com.springsource.bundlor.support.StandardManifestGenerator +import com.springsource.bundlor.support.classpath.FileSystemClassPath +import com.springsource.bundlor.support.manifestwriter.FileSystemManifestWriter +import com.springsource.bundlor.support.properties.EmptyPropertiesSource +import com.springsource.bundlor.support.properties.FileSystemPropertiesSource +import com.springsource.bundlor.support.properties.PropertiesPropertiesSource +import com.springsource.bundlor.support.properties.PropertiesSource +import com.springsource.bundlor.util.BundleManifestUtils +import com.springsource.util.parser.manifest.ManifestContents +import org.gradle.api.DefaultTask +import org.gradle.api.GradleException +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.file.FileCollection +import org.gradle.api.logging.LogLevel +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Optional +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.OutputFile +import org.gradle.api.tasks.TaskAction + +/** + * @author Luke Taylor + */ +class BundlorPlugin implements Plugin { + void apply(Project project) { + Task bundlor = project.tasks.add('bundlor', Bundlor.class) + bundlor.setDescription('Generates OSGi manifest using bundlor tool') + bundlor.dependsOn(project.classes) + project.jar.dependsOn bundlor + } +} + +public class Bundlor extends DefaultTask { + @InputFile + File manifestTemplate + + @OutputDirectory + File bundlorDir = new File("${project.buildDir}/bundlor") + + @OutputFile + File manifest = project.file("${bundlorDir}/META-INF/MANIFEST.MF") + + @Input + Map expansions = [:] + + @InputFile + @Optional + File osgiProfile + + @InputFiles + @Optional + FileCollection inputPaths + + @Input + boolean failOnWarnings = false + + Bundlor() { + manifestTemplate = new File(project.projectDir, 'template.mf') + inputPaths = project.files(project.sourceSets.main.classesDir) + project.jar.manifest.from manifest + project.jar.inputs.files manifest + } + + @TaskAction + void createManifest() { + logging.captureStandardOutput(LogLevel.INFO) + + project.mkdir(bundlorDir) + + //String inputPath = project.sourceSets.main.classesDir + + List inputClassPath = [] as List; + + ManifestWriter manifestWriter = new FileSystemManifestWriter(project.file(bundlorDir.absolutePath)); + ManifestContents mfTemplate = BundleManifestUtils.getManifest(manifestTemplate); + + inputPaths.each {f -> + inputClassPath.add(new FileSystemClassPath(f)) + } + + // Must be a better way of doing this... + Properties p = new Properties() + expansions.each {entry -> + p.setProperty(entry.key, entry.value as String) + } + + PropertiesSource expansionProps = new PropertiesPropertiesSource(p) + PropertiesSource osgiProfileProps = osgiProfile == null ? new EmptyPropertiesSource() : + new FileSystemPropertiesSource(osgiProfile); + + ManifestGenerator manifestGenerator = new StandardManifestGenerator( + DefaultManifestGeneratorContributorsFactory.create(expansionProps, osgiProfileProps)); + + ManifestContents mf = manifestGenerator.generate(mfTemplate, inputClassPath.toArray(new ClassPath[inputClassPath.size()])); + + try { + manifestWriter.write(mf); + } finally { + manifestWriter.close(); + } + + ManifestValidator manifestValidator = new StandardManifestValidator(DefaultManifestValidatorContributorsFactory.create()); + + List warnings = manifestValidator.validate(mf); + + if (warnings.isEmpty()) { + return + } + + logger.warn("Bundlor Warnings:"); + for (String warning : warnings) { + logger.warn(" " + warning); + } + + if (failOnWarnings) { + throw new GradleException("Bundlor returned warnings. Please fix manifest template at " + manifestTemplate.absolutePath + " and try again.") + } + } + + def inputPath(FileCollection paths) { + inputPaths = project.files(inputPaths, paths) + } +} diff --git a/buildSrc/src/main/groovy/emma/EmmaPlugin.groovy b/buildSrc/src/main/groovy/emma/EmmaPlugin.groovy new file mode 100644 index 0000000000..d41cb9ed80 --- /dev/null +++ b/buildSrc/src/main/groovy/emma/EmmaPlugin.groovy @@ -0,0 +1,114 @@ +package emma; + +import org.gradle.api.* +import org.gradle.api.tasks.testing.Test +import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.Input +import com.vladium.emma.instr.InstrProcessor +import com.vladium.emma.report.ReportProcessor +import org.gradle.api.tasks.InputFiles +import com.vladium.util.XProperties; + +/** + * + * @author Luke Taylor + */ +class EmmaPlugin implements Plugin { + + void apply(Project project) { + Project rootProject = project.rootProject + def emmaMetaDataFile = "${rootProject.buildDir}/emma/emma.em" + def emmaCoverageFile = "${rootProject.buildDir}/emma/emma.ec" + + if (project.configurations.findByName('emma_rt') == null) { + project.configurations.add('emma_rt') + project.dependencies { + emma_rt 'emma:emma:2.0.5312' + } + } + + project.task('emmaInstrument') { + dependsOn project.classes + + doFirst { + InstrProcessor processor = InstrProcessor.create (); + String[] classesDirPath = [project.sourceSets.main.classesDir.absolutePath] + + processor.setInstrPath(classesDirPath, false); + processor.setOutMode(InstrProcessor.OutMode.OUT_MODE_COPY); + processor.setInstrOutDir("${project.buildDir}/emma/classes"); + processor.setMetaOutFile(emmaMetaDataFile); + processor.setMetaOutMerge(true); + //processor.setInclExclFilter (null); + processor.run(); + } + } + + // Modify test tasks in the project to generate coverage data + project.afterEvaluate { + if (project.hasProperty('coverage') && ['on','true'].contains(project.properties.coverage)) { + project.tasks.withType(Test.class).each { task -> + task.dependsOn project.emmaInstrument + task.configure() { + jvmArgs '-Dsec.log.level=DEBUG', "-Demma.coverage.out.file=$emmaCoverageFile" + jvmArgs '-Demma.verbosity.level=quiet' + } + task.doFirst { + classpath = project.files("${project.buildDir}/emma/classes") + project.configurations.emma_rt + classpath + } + } + } + } + + List reportTasks = rootProject.getTasksByName('coverageReport', false) as List; + CoverageReport task; + + if (reportTasks.isEmpty()) { + task = rootProject.tasks.add('coverageReport', CoverageReport.class); + task.dataPath = [emmaMetaDataFile, emmaCoverageFile]; + } else { + task = reportTasks[0]; + } + + task.modules.add(project); + } +} + +class CoverageReport extends DefaultTask { + @Input + List modules = []; + + @Input + String[] dataPath; + + @TaskAction + void generateReport() { + def buildDir = project.rootProject.buildDir + + if (!buildDir.exists()) { + throw new GradleException("No coverage data. Run gradle with -Pcoverage=on if using coverageReport"); + } + + ReportProcessor processor = ReportProcessor.create (); + processor.setDataPath(dataPath) + + def srcPath = [] + modules.each {module-> + module.sourceSets.main.java.srcDirs.each { + srcPath.add(it.absolutePath) + } + } + + processor.setSourcePath(srcPath as String[]); + + + def types = ['txt', 'html'] + processor.setReportTypes(types as String[]); + XProperties properties = new XProperties(); + properties.setProperty('report.html.out.file', "$buildDir/emma/coverage.html"); + properties.setProperty('report.txt.out.file', "$buildDir/emma/coverage.txt"); + processor.setPropertyOverrides(properties) + + processor.run() + } +} diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/aspectj.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/aspectj.properties new file mode 100644 index 0000000000..3e8a23c083 --- /dev/null +++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/aspectj.properties @@ -0,0 +1 @@ +implementation-class=aspectj.AspectJPlugin diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/bundlor.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/bundlor.properties new file mode 100644 index 0000000000..483572f837 --- /dev/null +++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/bundlor.properties @@ -0,0 +1 @@ +implementation-class=bundlor.BundlorPlugin diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/emma.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/emma.properties new file mode 100644 index 0000000000..29a6d56444 --- /dev/null +++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/emma.properties @@ -0,0 +1 @@ +implementation-class=emma.EmmaPlugin diff --git a/gradle/bundlor.gradle b/gradle/bundlor.gradle deleted file mode 100644 index 4237104291..0000000000 --- a/gradle/bundlor.gradle +++ /dev/null @@ -1,39 +0,0 @@ -apply plugin: 'java' - -configurations { - bundlor -} - -dependencies { - bundlor 'com.springsource.bundlor:com.springsource.bundlor.ant:1.0.0.RELEASE', - 'com.springsource.bundlor:com.springsource.bundlor:1.0.0.RELEASE', - 'com.springsource.bundlor:com.springsource.bundlor.blint:1.0.0.RELEASE' -} - -task bundlor(dependsOn: compileJava) { - def template = new File(projectDir, 'template.mf') - def bundlorDir = new File("${project.buildDir}/bundlor") - def manifest = file("${bundlorDir}/META-INF/MANIFEST.MF") - - outputs.dir bundlorDir - outputs.files manifest - inputs.files template, project.sourceSets.main.runtimeClasspath - - jar.manifest.from manifest - jar.inputs.files manifest - - doFirst { - ant.taskdef(resource: 'com/springsource/bundlor/ant/antlib.xml', classpath: configurations.bundlor.asPath) - logging.captureStandardOutput(LogLevel.INFO) - - mkdir(bundlorDir) - - ant.bundlor(inputPath: sourceSets.main.classesDir, outputPath: "$buildDir/bundlor", manifestTemplatePath: template) { - for (p in bundlorProperties) { - property(name: p.key, value: p.value) - } - } - } -} - -jar.dependsOn bundlor diff --git a/gradle/emma.gradle b/gradle/emma.gradle deleted file mode 100644 index eaba985649..0000000000 --- a/gradle/emma.gradle +++ /dev/null @@ -1,74 +0,0 @@ - -configurations{ - emma -} - -dependencies{ - emma "emma:emma:2.0.5312" - emma "emma:emma_ant:2.0.5312" -} - -def emmaMetaDataFile = "${rootProject.buildDir}/emma/emma.em" -def emmaCoverageFile = "${rootProject.buildDir}/emma/emma.ec" - -task emmaInstrument { - dependsOn classes - doFirst { - ant.taskdef(resource:"emma_ant.properties", classpath: configurations.emma.asPath) - ant.path(id: "emmarun.classpath") { - pathelement(location: sourceSets.main.classesDir.absolutePath) - } - ant.emma(verbosity: "quiet") { // use "info, verbose, trace1, trace2, trace3 for more info" - instr(merge: "true", destdir: "$buildDir/emma/classes", instrpathref: "emmarun.classpath", metadatafile: "$emmaMetaDataFile") { - instrpath { - fileset(dir: sourceSets.main.classesDir.absolutePath, includes: "*.class") - } - } - } - } -} - -// Modify test tasks in the project to generate coverage data -afterEvaluate { - if (project.hasProperty('coverage') && ['on','true'].contains(project.properties.coverage)) { - tasks.withType(Test.class).each { task -> - task.dependsOn emmaInstrument - task.configure() { - jvmArgs '-Dsec.log.level=DEBUG', "-Demma.coverage.out.file=$emmaCoverageFile" - jvmArgs '-Demma.verbosity.level=quiet' - } - task.doFirst { - classpath = files("$buildDir/emma/classes") + configurations.emma + classpath - } - } - } -} - -if (rootProject.getTasksByName('coverageReport', false).isEmpty()) { - rootProject.task('coverageReport') << { - ant.taskdef(resource:"emma_ant.properties", classpath: configurations.emma.asPath) - ant.path(id: "src.path") { - coreModuleProjects.each {module-> - module.sourceSets.main.java.srcDirs.each { - pathelement(location: it.absolutePath ) - } - } - } - - if (!rootProject.buildDir.exists()) { - throw new GradleException("No coverage data. Run gradle with -Pcoverage=on if using coverageRepor"); - } - - ant.emma(enabled: "true", verbosity: "info") { - report(sourcepathref:"src.path") { - fileset(dir: rootProject.buildDir) { - include: '*.ec' - include: '*.emma' - } - txt(outfile: "$rootProject.buildDir/emma/coverage.txt") - html(outfile: "$rootProject.buildDir/emma/coverage.html") -// xml(outfile: "$rootProject.buildDir/emma/coverage.xml") - } - } - } -} diff --git a/gradle/javaprojects.gradle b/gradle/javaprojects.gradle index 9d38ec5ff8..dc6393753f 100644 --- a/gradle/javaprojects.gradle +++ b/gradle/javaprojects.gradle @@ -92,6 +92,7 @@ sourceSets.main.compileClasspath += configurations.provided test { jvmArgs = ['-ea', '-Xmx500m'] maxParallelForks = guessMaxForks() + logging.captureStandardOutput(LogLevel.INFO) testReport = false }