From 3b6fd50244496ad818ee56e766504e5ba783da84 Mon Sep 17 00:00:00 2001 From: stefanofranz Date: Fri, 29 Jun 2018 15:35:00 +0100 Subject: [PATCH] fix issue with base-directory not being set fix build issue with installer.sh not containing security.policy from JRE^ --- .../kotlin/net/corda/launcher/Launcher.kt | 35 ++++++++--- node/dist/build.gradle | 62 ++++++++++++++++++- .../src/main/resources/installer/installer.sh | 43 +++++++++++++ node/dist/src/main/resources/license/LICENSE | 3 + 4 files changed, 132 insertions(+), 11 deletions(-) create mode 100755 node/dist/src/main/resources/installer/installer.sh create mode 100644 node/dist/src/main/resources/license/LICENSE diff --git a/launcher/src/main/kotlin/net/corda/launcher/Launcher.kt b/launcher/src/main/kotlin/net/corda/launcher/Launcher.kt index 5913ff9fde..445dee7f4c 100644 --- a/launcher/src/main/kotlin/net/corda/launcher/Launcher.kt +++ b/launcher/src/main/kotlin/net/corda/launcher/Launcher.kt @@ -9,17 +9,19 @@ import kotlin.system.exitProcess fun main(args: Array) { - if(args.isEmpty()) { + if (args.isEmpty()) { println("Usage: launcher [args]") exitProcess(0) } // TODO: --base-directory is specific of the Node app, it should be controllable by a config property - val nodeBaseDir = Paths.get(Settings.WORKING_DIR) - .resolve(getBaseDirectory(args) ?: ".") + // we must use this directory for loading classpath components + //but it must be resolved relative to the CWD the user has launched the script from as they may use a relative path + val nodeBaseDirFromArgs = Paths.get(Settings.WORKING_DIR) + .resolve(getBaseDirectoryFromArgs(args) ?: ".") .toAbsolutePath() - val appClassLoader = setupClassLoader(nodeBaseDir) + val appClassLoader = setupClassLoader(nodeBaseDirFromArgs) val appMain = try { appClassLoader @@ -39,21 +41,37 @@ fun main(args: Array) { // e.g. if JDBC driver was not found, remove once Corda started by Capsule is no longer in use System.setProperty("corda-distribution.tarball", "true") + val argsWithBaseDir = fixBaseDirArg(args, nodeBaseDirFromArgs) + try { - appMain.invoke(null, args.sliceArray(1..args.lastIndex)) + appMain.invoke(null, argsWithBaseDir.sliceArray(1..argsWithBaseDir.lastIndex)) } catch (e: Exception) { e.printStackTrace() exitProcess(1) } } +@Suppress("unchecked") +private fun fixBaseDirArg(args: Array, nodeBaseDirFromArgs: Path): Array { + val baseDirIdx = args.indexOf("--base-directory") + if (baseDirIdx != -1){ + args[baseDirIdx+1] = nodeBaseDirFromArgs.toString() + return args + } + + val argsWithBaseDir = args.copyOf(args.size + 2) + argsWithBaseDir[argsWithBaseDir.lastIndex - 1] = "--base-directory" + argsWithBaseDir[argsWithBaseDir.lastIndex] = nodeBaseDirFromArgs.toString() + return argsWithBaseDir as Array +} + private fun setupClassLoader(nodeBaseDir: Path): ClassLoader { val sysClassLoader = ClassLoader.getSystemClassLoader() val appClassLoader = (sysClassLoader as? Loader) ?: { println("WARNING: failed to override system classloader") Loader(sysClassLoader) - } () + }() // Lookup plugins and extend classpath val pluginURLs = Settings.PLUGINS.flatMap { @@ -73,13 +91,14 @@ private fun setupClassLoader(nodeBaseDir: Path): ClassLoader { return appClassLoader } -private fun getBaseDirectory(args: Array): String? { +private fun getBaseDirectoryFromArgs(args: Array): String? { val idx = args.indexOf("--base-directory") return if (idx != -1 && idx < args.lastIndex) { args[idx + 1] } else null } + private fun Path.jarFiles(): List { return Files.newDirectoryStream(this).filter { it.toString().endsWith(".jar") } -} +} \ No newline at end of file diff --git a/node/dist/build.gradle b/node/dist/build.gradle index 91fa2eda0e..cae835c333 100644 --- a/node/dist/build.gradle +++ b/node/dist/build.gradle @@ -1,3 +1,5 @@ +import org.gradle.internal.jvm.Jvm + description 'Package Node as stand-alone application' evaluationDependsOn(":node") @@ -7,6 +9,8 @@ evaluationDependsOn(":launcher") ext { outputDir = "$buildDir/corda" tarballDir = "$buildDir/distribution" + tarballBaseName = 'corda-enterprise-distribution' + tarballExtension = "tar.bz2" } def tmpDir = "${buildDir}/tmp/" @@ -22,6 +26,11 @@ sourceSets { srcDir file('src/main/resources/bin') } } + installerFiles { + resources { + srcDir file('src/main/resources/installer') + } + } readmeFiles { resources { srcDir file('src/main/resources/readme') @@ -51,6 +60,8 @@ def isLinux = System.properties['os.name'].toLowerCase().contains('linux') def isMac = System.properties['os.name'].toLowerCase().contains('mac') if (isLinux || isMac) { println("Detected *nix system, enabling distribution creation") + + task buildLauncher(type: Exec, dependsOn: [copyLauncherLibs]) { description 'Build Launcher executable' @@ -74,6 +85,11 @@ if (isLinux || isMac) { workingDir project.projectDir doFirst { + def currentJvmPathContainsOpenJDK = Jvm.current().javaHome.absolutePath.toLowerCase().contains("openjdk") + if (currentJvmPathContainsOpenJDK) { + throw new BuildCancelledException("Building installer using an openJDK JDK") + } + def launcherLib = copyLauncherLibs.destinationDir def srcfiles = [] def launcherClasspath = [] @@ -144,6 +160,10 @@ if (isLinux || isMac) { into(".") } + from(file("src/main/resources/license/LICENSE")) { + into(".") + } + doLast { new File("${dir}/cordapps").mkdirs() new File("${dir}/drivers").mkdirs() @@ -153,17 +173,53 @@ if (isLinux || isMac) { } task buildCordaTarball(type: Tar, dependsOn: [buildNode]) { + from outputDir compression = Compression.BZIP2 - baseName = 'corda-enterprise-distribution' + baseName = tarballBaseName destinationDir = file(tarballDir) - extension = "tar.bz2" + extension = tarballExtension doLast { println("Distribution tarball available at:") - println("${tarballDir}/${baseName}.${extension}") + println("${tarballDir}/${archiveName}") } } + + task prepareInstallerEnvironment(type: Copy, dependsOn: buildCordaTarball) { + into(tarballDir) + from(sourceSets.installerFiles.resources) { + into("installer") + } + } + + task embedLicense(type: Exec, dependsOn: [prepareInstallerEnvironment]) { + commandLine "bash", "-c", "sed -i -e '/QQ_LICENSE_FILE_QQ/{r src/main/resources/license/LICENSE' -e 'd}' $tarballDir/installer/installer.sh" + } + + task embedTarball(type: Exec, dependsOn: [embedLicense]) { + commandLine "bash", "-c", "cat ${tarballDir}/${buildCordaTarball.archiveName} >> $tarballDir/installer/installer.sh" + } + + task buildInstaller(dependsOn: [embedTarball]) + + apply plugin: 'maven-publish' + apply plugin: 'java' + + def installerFile = file("$tarballDir/installer/installer.sh") + def installerArtifact = artifacts.add("archives", installerFile) { + type "sh" + builtBy(buildInstaller) + } + + publishing { + publications { + InstallerPublication(MavenPublication) { + artifact installerArtifact + } + } + } + } else { println("Not running on *nix, disabling distribution generation") } diff --git a/node/dist/src/main/resources/installer/installer.sh b/node/dist/src/main/resources/installer/installer.sh new file mode 100755 index 0000000000..d69ad64667 --- /dev/null +++ b/node/dist/src/main/resources/installer/installer.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# Script Varibles +ALREADY_ACCEPTED=$(case "( "$@" )" in *"accept-license"*) echo "YES" ;; esac) +HELP_REQUESTED=$(case "( "$@" )" in *"help"*) echo "YES" ;; esac) + +if [ "${HELP_REQUESTED}" == "YES" ] +then + echo "usage: ./installer.sh <--help> <--accept-license>" + echo "--help: display this help printout" + echo "--accept-license: confirm possession of a valid license without further user input" + exit 0 +fi + + +if [ "${ALREADY_ACCEPTED}" == "YES" ] +then + echo "skipping license as already accepted" +else + echo "Preparing License" + more << EOF + QQ_LICENSE_FILE_QQ +EOF + read -p "Do you have a valid license and agree with the license terms [yes/No]? " answer + + while true + do + case ${answer} in + [yY] | [yY][Ee][Ss]) echo "Accepting" + break;; + + * ) echo "You answered: $answer - quitting" ; exit;; + esac + done +fi + +# Extract +echo "Extracting install ... " +SKIP_TO_TAR=$(awk '/^__TARFILE_FOLLOWS__/ { print NR + 1; exit 0; }' $0) +tail -n +${SKIP_TO_TAR} $0 | tar xjv + +exit 0 +__TARFILE_FOLLOWS__ diff --git a/node/dist/src/main/resources/license/LICENSE b/node/dist/src/main/resources/license/LICENSE new file mode 100644 index 0000000000..ae68800409 --- /dev/null +++ b/node/dist/src/main/resources/license/LICENSE @@ -0,0 +1,3 @@ +This software is proprietary to and embodies the confidential technology of R3 LLC ("R3"). +Possession, use, duplication or dissemination of the software is authorized only pursuant to a valid license from R3. +You must obtain such a license from R3 directly. An evaluation license can be obtained from https://r3.com