/* * Copyright Jack Grigg */ apply plugin: I2PPlugin class Pack200Task extends DefaultTask { @InputFiles def FileCollection inputJars @OutputDirectory def File outputDir @TaskAction def packJars(IncrementalTaskInputs inputs) { if (!inputs.incremental) project.delete(outputDir.listFiles()) inputs.outOfDate { jar -> def tmp = jar.file def packed = "$outputDir/${jar.file.name}.pack" // Pretend that WARs are JARs if (jar.file.name.endsWith('.war')) { project.copy { from jar.file into temporaryDir rename { "${it}.jar" } } tmp = "$temporaryDir/${jar.file.name}.jar" } project.exec { executable 'pack200' args '--no-gzip', '--effort=9', '--modification-time=latest', packed, tmp } } inputs.removed { jar -> println "removed: ${jar.file.name}" def targetFile = new File(outputDir, "${jar.file.name}.pack") targetFile.delete() } } } class I2PPlugin implements Plugin { def pluginProps = [ 'name': ['name', true], 'signer': ['signer', true], 'version': ['version', true], 'author': ['author', false], 'description': ['description', false], 'websiteURL': ['websiteUrl', false], 'updateURL': ['updateUrl', false], 'updateURL.su3': ['su3UpdateUrl', false], 'license': ['license', false], 'disableStop': ['disableStop', false], 'consoleLinkName': ['consoleLinkName', false], 'consoleLinkURL': ['consoleLinkURL', false], 'consoleLinkTooltip': ['consoleLinkTooltip', false], 'console-icon': ['consoleIcon', false], 'icon-code': ['consoleIconCode', false], 'min-i2p-version': ['minI2PVersion', false], 'max-i2p-version': ['maxI2PVersion', false], 'min-java-version': ['minJavaVersion', false], 'min-jetty-version': ['minJettyVersion', false], 'max-jetty-version': ['maxJettyVersion', false], 'dont-start-at-install': ['dontStartAtInstall', false], 'router-restart-required': ['routerRestartRequired', false], 'update-only': ['updateOnly', false], 'install-only': ['installOnly', false], 'min-installed-version': ['minInstalledVersion', false], 'max-installed-version': ['maxInstalledVersion', false], ] def pluginLibs(Project project) { project.configurations.runtime.filter { lib -> !( // These are all in the standard classpath lib.name.startsWith('i2p-') || lib.name.startsWith('mstreaming-') || lib.name.startsWith('streaming-') )} } def pubKeyFile(Project project) { project.file(project.i2p.plugin.pubKeyFile ? project.i2p.plugin.pubKeyFile : "$project.i2p.plugin.pubKeyDir/$project.i2p.plugin.pubKeyFileName") } def privKeyFile(Project project) { project.file(project.i2p.plugin.privKeyFile ? project.i2p.plugin.privKeyFile : "$project.i2p.plugin.pubKeyDir/$project.i2p.plugin.privKeyFileName") } def b64KeyFile(Project project) { project.file(project.i2p.plugin.b64KeyFile ? project.i2p.plugin.b64KeyFile : "$project.i2p.plugin.pubKeyDir/$project.i2p.plugin.b64KeyFileName") } def pubKeyStore(Project project) { project.file(project.i2p.plugin.pubKeyStore ? project.i2p.plugin.pubKeyStore : "$project.i2p.plugin.pubKeyDir/$project.i2p.plugin.pubKeyStoreName") } def privKeyStore(Project project) { project.file(project.i2p.plugin.privKeyStore ? project.i2p.plugin.privKeyStore : "$project.i2p.plugin.pubKeyDir/$project.i2p.plugin.privKeyStoreName") } void apply(Project project) { project.extensions.create('i2p', I2PExtension) project.i2p.extensions.create('plugin', I2PPluginExtension) project.i2p.plugin.extensions.create('webapp', I2PPluginWebappExtension) def pluginBuildDir = "$project.buildDir/plugin.tmp" def tmpPluginConfig = "$pluginBuildDir/plugin.config" def tmpWebappsConfig = "$pluginBuildDir/webapps.config" project.task('preparePluginConfig') << { def hasProp = [] project.delete(tmpPluginConfig) project.copy { from 'src/main/i2p/plugin.config' into pluginBuildDir filter { line -> for (p in pluginProps) { if (line.startsWith("$p.key=")) { if (project.i2p.plugin[p.value[0]]) { return null } else { hasProp.add(p.key) } } } line } } File file = new File(tmpPluginConfig) for (p in pluginProps) { if (!(p.key in hasProp)) { def (confName, required) = p.value if (project.i2p.plugin[confName]) { file << System.getProperty('line.separator') file << "$p.key=" << project.i2p.plugin[confName] } else if (required) { throw new InvalidUserDataException( "You must set i2p.plugin.$confName in your build.gradle") } } } file << System.getProperty('line.separator') file << 'date=' << System.currentTimeMillis() file << System.getProperty('line.separator') file << 'key=' << b64KeyFile(project).text } project.task('prepareWebappsConfig') << { project.delete(tmpWebappsConfig) File file = new File(tmpWebappsConfig) file << 'webapps.' << project.archivesBaseName << '.classpath=' if (project.i2p.plugin.webapp.includeTaglib) { file << '$I2P/lib/jstl.jar,$I2P/lib/standard.jar,' } file << pluginLibs(project).collect { lib -> '$PLUGIN/lib/' + lib.name }.join(',') file << System.getProperty('line.separator') file << 'webapps.' << project.archivesBaseName << '.startOnLoad=' file << project.i2p.plugin.webapp.startOnLoad } project.task('packWebapp', type: Pack200Task) { inputJars = project.war.outputs.files outputDir project.file("$project.buildDir/packWebapp") } project.task('packLibs', type: Pack200Task) { inputJars = pluginLibs(project) outputDir project.file("$project.buildDir/packLibs") } project.task('pluginZip', type: Zip) { archiveName = 'plugin.zip' destinationDir = project.file(pluginBuildDir) from tmpPluginConfig into('console') { from tmpWebappsConfig into('webapps') { from project.packWebapp.outputs.files } } into('lib') { from project.packLibs.outputs.files } } project.pluginZip.dependsOn project.preparePluginConfig project.pluginZip.dependsOn project.prepareWebappsConfig project.task('checkKeys') << { def pkf = privKeyFile(project) if (!pkf.exists()) { println 'TODO: Creating new XPI2P DSA keys' } def pks = privKeyStore(project) if (!pks.exists()) { println "TODO: Creating new SU3 $project.i2p.plugin.keyType keys for $project.i2p.plugin.signer" } } project.configurations.create('i2pPluginSign') project.dependencies.add('i2pPluginSign', 'net.i2p:i2p:+') project.dependencies.add('i2pPluginSign', project.files('/usr/share/java/gnu-getopt.jar')) project.afterEvaluate { p -> def pluginDir = p.file("$p.buildDir/plugin") p.task('signXPI2PPlugin', type: JavaExec) { def xpi2pFile = p.file("$pluginDir/${p.i2p.plugin.name}.xpi2p") outputs.files xpi2pFile main = 'net.i2p.crypto.TrustedUpdate' classpath = p.configurations.i2pPluginSign args 'sign', p.pluginZip.outputs.files[0].absolutePath, xpi2pFile, privKeyFile(p), p.i2p.plugin.version doFirst { p.mkdir(pluginDir) } } p.signXPI2PPlugin.dependsOn p.pluginZip p.signXPI2PPlugin.dependsOn p.checkKeys p.task('signSU3Plugin', type: JavaExec) { def su3File = p.file("$pluginDir/${p.i2p.plugin.name}.su3") outputs.files su3File standardInput = System.in main = 'net.i2p.crypto.SU3File' classpath = p.configurations.i2pPluginSign args 'sign', '-c', 'PLUGIN', '-t', p.i2p.plugin.keyType, p.pluginZip.outputs.files[0].absolutePath, su3File, privKeyStore(p), p.i2p.plugin.version, p.i2p.plugin.signer doFirst { p.mkdir(pluginDir) } } p.signSU3Plugin.dependsOn p.pluginZip p.signSU3Plugin.dependsOn p.checkKeys p.task('verifyXPI2PPlugin', type: JavaExec) { def b64Key = b64KeyFile(p).text main = 'net.i2p.crypto.TrustedUpdate' classpath = p.configurations.i2pPluginSign jvmArgs "-Drouter.trustedUpdateKeys=$b64Key" args 'verifysig', p.signXPI2PPlugin.outputs.files[0].absolutePath } p.task('verifySU3Plugin', type: JavaExec) { main = 'net.i2p.crypto.SU3File' classpath = p.configurations.i2pPluginSign args 'verifysig', '-k', pubKeyStore(p), p.signSU3Plugin.outputs.files[0].absolutePath } p.task('plugin') << { } p.plugin.dependsOn p.signXPI2PPlugin p.plugin.dependsOn p.signSU3Plugin p.plugin.dependsOn p.verifyXPI2PPlugin p.plugin.dependsOn p.verifySU3Plugin } } } class I2PExtension { } class I2PPluginExtension { def String pubKeyDir = System.getProperty('user.home') + '/.i2p-plugin-keys' def String pubKeyFileName = 'plugin-public-signing.key' def String pubKeyFile def String privKeyFileName = 'plugin-private-signing.key' def String privKeyFile def String b64KeyFileName = 'plugin-public-signing.txt' def String b64KeyFile def String pubKeyStoreName = 'plugin-su3-public-signing.crt' def String pubKeyStore def String privKeyStoreName = 'plugin-su3-keystore.ks' def String privKeyStore def String keyType = 'RSA_SHA512_4096' def String name def String signer def String version def String author def String description def String websiteUrl def String updateUrl def String su3UpdateUrl def String license def String disableStop def String consoleLinkName def String consoleLinkURL def String consoleLinkTooltip def String consoleIcon def String consoleIconCode def String minI2PVersion def String maxI2PVersion def String minJavaVersion def String minJettyVersion def String maxJettyVersion def String dontStartAtInstall def String routerRestartRequired def String updateOnly def String installOnly def String minInstalledVersion def String maxInstalledVersion } class I2PPluginWebappExtension { def boolean startOnLoad = true def boolean includeTaglib = false }