diff --git a/gradle-plugins/README.rst b/gradle-plugins/README.rst deleted file mode 100644 index 0ede7c216f..0000000000 --- a/gradle-plugins/README.rst +++ /dev/null @@ -1,29 +0,0 @@ -Gradle Plugins for Cordapps -=========================== - -The projects at this level of the project are gradle plugins for cordapps and are published to Maven Local with -the rest of the Corda libraries. - -.. note:: - - Some of the plugins here are duplicated with the ones in buildSrc. While the duplication is unwanted any - currently known solution (such as publishing from buildSrc or setting up a separate project/repo) would - introduce a two step build which is less convenient. - -Version number --------------- - -To modify the version number edit constants.properties in root dir - -Installing ----------- - -If you need to bootstrap the corda repository you can install these plugins with - -.. code-block:: text - - cd publish-utils - ../../gradlew -u install - cd ../ - ../gradlew install - diff --git a/gradle-plugins/api-scanner/README.md b/gradle-plugins/api-scanner/README.md deleted file mode 100644 index a0256d480b..0000000000 --- a/gradle-plugins/api-scanner/README.md +++ /dev/null @@ -1,79 +0,0 @@ -# API Scanner - -Generates a text summary of Corda's public API that we can check for API-breaking changes. - -```bash -$ gradlew generateApi -``` - -See [here](../../docs/source/corda-api.rst) for Corda's public API strategy. We will need to -apply this plugin to other modules in future Corda releases as those modules' APIs stabilise. - -Basically, this plugin will document a module's `public` and `protected` classes/methods/fields, -excluding those from our `*.internal.*` packgages, any synthetic methods, bridge methods, or methods -identified as having Kotlin's `internal` scope. (Kotlin doesn't seem to have implemented `internal` -scope for classes or fields yet as these are currently `public` inside the `.class` file.) - -## Usage -Include this line in the `build.gradle` file of every Corda module that exports public API: - -```gradle -apply plugin: 'net.corda.plugins.api-scanner' -``` - -This will create a Gradle task called `scanApi` which will analyse that module's Jar artifacts. More precisely, -it will analyse all of the Jar artifacts that have not been assigned a Maven classifier, on the basis -that these should be the module's main artifacts. - -The `scanApi` task supports the following configuration options: -```gradle -scanApi { - // Make the classpath-scanning phase more verbose. - verbose = {true|false} - - // Enable / disable the task within this module. - enabled = {true|false} - - // Names of classes that should be excluded from the output. - excludeClasses = [ - ... - ] -} -``` - -All of the `ScanApi` tasks write their output files to their own `$buildDir/api` directory, where they -are collated into a single output file by the `GenerateApi` task. The `GenerateApi` task is declared -in the root project's `build.gradle` file: - -```gradle -task generateApi(type: net.corda.plugins.GenerateApi){ - baseName = "api-corda" -} -``` - -The final API file is written to `$buildDir/api/$baseName-$project.version.txt` - -### Sample Output -``` -public interface net.corda.core.contracts.Attachment extends net.corda.core.contracts.NamedByHash - public abstract void extractFile(String, java.io.OutputStream) - @org.jetbrains.annotations.NotNull public abstract List getSigners() - @org.jetbrains.annotations.NotNull public abstract java.io.InputStream open() - @org.jetbrains.annotations.NotNull public abstract jar.JarInputStream openAsJAR() -## -public interface net.corda.core.contracts.AttachmentConstraint - public abstract boolean isSatisfiedBy(net.corda.core.contracts.Attachment) -## -public final class net.corda.core.contracts.AttachmentResolutionException extends net.corda.core.flows.FlowException - public (net.corda.core.crypto.SecureHash) - @org.jetbrains.annotations.NotNull public final net.corda.core.crypto.SecureHash getHash() -## -``` - -#### Notes -The `GenerateApi` task will collate the output of every `ScanApi` task found either in the same project, -or in any of that project's subprojects. So it is _theoretically_ possible also to collate the API output -from subtrees of modules simply by defining a new `GenerateApi` task at the root of that subtree. - -## Plugin Installation -See [here](../README.rst) for full installation instructions. diff --git a/gradle-plugins/api-scanner/build.gradle b/gradle-plugins/api-scanner/build.gradle deleted file mode 100644 index c178472d58..0000000000 --- a/gradle-plugins/api-scanner/build.gradle +++ /dev/null @@ -1,19 +0,0 @@ -apply plugin: 'java' -apply plugin: 'net.corda.plugins.publish-utils' -apply plugin: 'com.jfrog.artifactory' - -description "Generates a summary of the artifact's public API" - -repositories { - mavenCentral() -} - -dependencies { - compile gradleApi() - compile "io.github.lukehutch:fast-classpath-scanner:2.7.0" - testCompile "junit:junit:4.12" -} - -publish { - name project.name -} diff --git a/gradle-plugins/api-scanner/src/main/java/net/corda/plugins/ApiScanner.java b/gradle-plugins/api-scanner/src/main/java/net/corda/plugins/ApiScanner.java deleted file mode 100644 index 75f238891c..0000000000 --- a/gradle-plugins/api-scanner/src/main/java/net/corda/plugins/ApiScanner.java +++ /dev/null @@ -1,70 +0,0 @@ -package net.corda.plugins; - -import org.gradle.api.Plugin; -import org.gradle.api.Project; -import org.gradle.api.artifacts.ConfigurationContainer; -import org.gradle.api.file.FileCollection; -import org.gradle.api.tasks.TaskCollection; -import org.gradle.jvm.tasks.Jar; - -public class ApiScanner implements Plugin { - - /** - * Identify the Gradle Jar tasks creating jars - * without Maven classifiers, and generate API - * documentation for them. - * @param p Current project. - */ - @Override - public void apply(Project p) { - p.getLogger().info("Applying API scanner to {}", p.getName()); - - ScannerExtension extension = p.getExtensions().create("scanApi", ScannerExtension.class); - - p.afterEvaluate(project -> { - TaskCollection jarTasks = project.getTasks() - .withType(Jar.class) - .matching(jarTask -> jarTask.getClassifier().isEmpty() && jarTask.isEnabled()); - if (jarTasks.isEmpty()) { - return; - } - - project.getLogger().info("Adding scanApi task to {}", project.getName()); - project.getTasks().create("scanApi", ScanApi.class, scanTask -> { - scanTask.setClasspath(compilationClasspath(project.getConfigurations())); - // Automatically creates a dependency on jar tasks. - scanTask.setSources(project.files(jarTasks)); - scanTask.setExcludeClasses(extension.getExcludeClasses()); - scanTask.setVerbose(extension.isVerbose()); - scanTask.setEnabled(extension.isEnabled()); - - // Declare this ScanApi task to be a dependency of any - // GenerateApi tasks belonging to any of our ancestors. - project.getRootProject().getTasks() - .withType(GenerateApi.class) - .matching(generateTask -> isAncestorOf(generateTask.getProject(), project)) - .forEach(generateTask -> generateTask.dependsOn(scanTask)); - }); - }); - } - - /* - * Recurse through a child project's parents until we reach the root, - * and return true iff we find our target project along the way. - */ - private static boolean isAncestorOf(Project target, Project child) { - Project p = child; - while (p != null) { - if (p == target) { - return true; - } - p = p.getParent(); - } - return false; - } - - private static FileCollection compilationClasspath(ConfigurationContainer configurations) { - return configurations.getByName("compile") - .plus(configurations.getByName("compileOnly")); - } -} diff --git a/gradle-plugins/api-scanner/src/main/java/net/corda/plugins/GenerateApi.java b/gradle-plugins/api-scanner/src/main/java/net/corda/plugins/GenerateApi.java deleted file mode 100644 index 9c87224075..0000000000 --- a/gradle-plugins/api-scanner/src/main/java/net/corda/plugins/GenerateApi.java +++ /dev/null @@ -1,61 +0,0 @@ -package net.corda.plugins; - -import org.gradle.api.DefaultTask; -import org.gradle.api.file.FileCollection; -import org.gradle.api.tasks.InputFiles; -import org.gradle.api.tasks.OutputFile; -import org.gradle.api.tasks.TaskAction; - -import java.io.*; -import java.nio.file.Files; - -import static java.util.Comparator.comparing; -import static java.util.stream.Collectors.toList; - -@SuppressWarnings("unused") -public class GenerateApi extends DefaultTask { - - private final File outputDir; - private String baseName; - - public GenerateApi() { - outputDir = new File(getProject().getBuildDir(), "api"); - baseName = "api-" + getProject().getName(); - } - - public void setBaseName(String baseName) { - this.baseName = baseName; - } - - @InputFiles - public FileCollection getSources() { - return getProject().files(getProject().getAllprojects().stream() - .flatMap(project -> project.getTasks() - .withType(ScanApi.class) - .matching(ScanApi::isEnabled) - .stream()) - .flatMap(scanTask -> scanTask.getTargets().getFiles().stream()) - .sorted(comparing(File::getName)) - .collect(toList()) - ); - } - - @OutputFile - public File getTarget() { - return new File(outputDir, String.format("%s-%s.txt", baseName, getProject().getVersion())); - } - - @TaskAction - public void generate() { - FileCollection apiFiles = getSources(); - if (!apiFiles.isEmpty()) { - try (OutputStream output = new BufferedOutputStream(new FileOutputStream(getTarget()))) { - for (File apiFile : apiFiles) { - Files.copy(apiFile.toPath(), output); - } - } catch (IOException e) { - getLogger().error("Failed to generate API file", e); - } - } - } -} diff --git a/gradle-plugins/api-scanner/src/main/java/net/corda/plugins/ScanApi.java b/gradle-plugins/api-scanner/src/main/java/net/corda/plugins/ScanApi.java deleted file mode 100644 index eb2b7e5599..0000000000 --- a/gradle-plugins/api-scanner/src/main/java/net/corda/plugins/ScanApi.java +++ /dev/null @@ -1,389 +0,0 @@ -package net.corda.plugins; - -import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner; -import io.github.lukehutch.fastclasspathscanner.scanner.ClassInfo; -import io.github.lukehutch.fastclasspathscanner.scanner.FieldInfo; -import io.github.lukehutch.fastclasspathscanner.scanner.MethodInfo; -import io.github.lukehutch.fastclasspathscanner.scanner.ScanResult; -import org.gradle.api.DefaultTask; -import org.gradle.api.file.ConfigurableFileCollection; -import org.gradle.api.file.FileCollection; -import org.gradle.api.tasks.CompileClasspath; -import org.gradle.api.tasks.Input; -import org.gradle.api.tasks.InputFiles; -import org.gradle.api.tasks.OutputFiles; -import org.gradle.api.tasks.TaskAction; - -import java.io.*; -import java.lang.annotation.Annotation; -import java.lang.annotation.Inherited; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.*; -import java.util.stream.StreamSupport; - -import static java.util.Collections.*; -import static java.util.stream.Collectors.*; - -@SuppressWarnings("unused") -public class ScanApi extends DefaultTask { - private static final int CLASS_MASK = Modifier.classModifiers(); - private static final int INTERFACE_MASK = Modifier.interfaceModifiers() & ~Modifier.ABSTRACT; - private static final int METHOD_MASK = Modifier.methodModifiers(); - private static final int FIELD_MASK = Modifier.fieldModifiers(); - private static final int VISIBILITY_MASK = Modifier.PUBLIC | Modifier.PROTECTED; - - private static final Set ANNOTATION_BLACKLIST; - static { - Set blacklist = new LinkedHashSet<>(); - blacklist.add("kotlin.jvm.JvmOverloads"); - ANNOTATION_BLACKLIST = unmodifiableSet(blacklist); - } - - /** - * This information has been lifted from: - * @link Metadata.kt - */ - private static final String KOTLIN_METADATA = "kotlin.Metadata"; - private static final String KOTLIN_CLASSTYPE_METHOD = "k"; - private static final int KOTLIN_SYNTHETIC = 3; - - private final ConfigurableFileCollection sources; - private final ConfigurableFileCollection classpath; - private final Set excludeClasses; - private final File outputDir; - private boolean verbose; - - public ScanApi() { - sources = getProject().files(); - classpath = getProject().files(); - excludeClasses = new LinkedHashSet<>(); - outputDir = new File(getProject().getBuildDir(), "api"); - } - - @InputFiles - public FileCollection getSources() { - return sources; - } - - void setSources(FileCollection sources) { - this.sources.setFrom(sources); - } - - @CompileClasspath - @InputFiles - public FileCollection getClasspath() { - return classpath; - } - - void setClasspath(FileCollection classpath) { - this.classpath.setFrom(classpath); - } - - @Input - public Collection getExcludeClasses() { - return unmodifiableSet(excludeClasses); - } - - void setExcludeClasses(Collection excludeClasses) { - this.excludeClasses.clear(); - this.excludeClasses.addAll(excludeClasses); - } - - @OutputFiles - public FileCollection getTargets() { - return getProject().files( - StreamSupport.stream(sources.spliterator(), false) - .map(this::toTarget) - .collect(toList()) - ); - } - - public boolean isVerbose() { - return verbose; - } - - void setVerbose(boolean verbose) { - this.verbose = verbose; - } - - private File toTarget(File source) { - return new File(outputDir, source.getName().replaceAll(".jar$", ".txt")); - } - - @TaskAction - public void scan() { - try (Scanner scanner = new Scanner(classpath)) { - for (File source : sources) { - scanner.scan(source); - } - } catch (IOException e) { - getLogger().error("Failed to write API file", e); - } - } - - class Scanner implements Closeable { - private final URLClassLoader classpathLoader; - private final Class metadataClass; - private final Method classTypeMethod; - - @SuppressWarnings("unchecked") - Scanner(URLClassLoader classpathLoader) { - this.classpathLoader = classpathLoader; - - Class kClass; - Method kMethod; - try { - kClass = (Class) Class.forName(KOTLIN_METADATA, true, classpathLoader); - kMethod = kClass.getDeclaredMethod(KOTLIN_CLASSTYPE_METHOD); - } catch (ClassNotFoundException | NoSuchMethodException e) { - kClass = null; - kMethod = null; - } - - metadataClass = kClass; - classTypeMethod = kMethod; - } - - Scanner(FileCollection classpath) throws MalformedURLException { - this(new URLClassLoader(toURLs(classpath))); - } - - @Override - public void close() throws IOException { - classpathLoader.close(); - } - - void scan(File source) { - File target = toTarget(source); - try ( - URLClassLoader appLoader = new URLClassLoader(new URL[]{ toURL(source) }, classpathLoader); - PrintWriter writer = new PrintWriter(target, "UTF-8") - ) { - scan(writer, appLoader); - } catch (IOException e) { - getLogger().error("API scan has failed", e); - } - } - - void scan(PrintWriter writer, ClassLoader appLoader) { - ScanResult result = new FastClasspathScanner(getScanSpecification()) - .overrideClassLoaders(appLoader) - .ignoreParentClassLoaders() - .ignoreMethodVisibility() - .ignoreFieldVisibility() - .enableMethodInfo() - .enableFieldInfo() - .verbose(verbose) - .scan(); - writeApis(writer, result); - } - - private String[] getScanSpecification() { - String[] spec = new String[2 + excludeClasses.size()]; - spec[0] = "!"; // Don't blacklist system classes from the output. - spec[1] = "-dir:"; // Ignore classes on the filesystem. - - int i = 2; - for (String excludeClass : excludeClasses) { - spec[i++] = '-' + excludeClass; - } - return spec; - } - - private void writeApis(PrintWriter writer, ScanResult result) { - Map allInfo = result.getClassNameToClassInfo(); - result.getNamesOfAllClasses().forEach(className -> { - if (className.contains(".internal.")) { - // These classes belong to internal Corda packages. - return; - } - ClassInfo classInfo = allInfo.get(className); - if (classInfo.getClassLoaders() == null) { - // Ignore classes that belong to one of our target ClassLoader's parents. - return; - } - - Class javaClass = result.classNameToClassRef(className); - if (!isVisible(javaClass.getModifiers())) { - // Excludes private and package-protected classes - return; - } - - int kotlinClassType = getKotlinClassType(javaClass); - if (kotlinClassType == KOTLIN_SYNTHETIC) { - // Exclude classes synthesised by the Kotlin compiler. - return; - } - - writeClass(writer, classInfo, javaClass.getModifiers()); - writeMethods(writer, classInfo.getMethodAndConstructorInfo()); - writeFields(writer, classInfo.getFieldInfo()); - writer.println("##"); - }); - } - - private void writeClass(PrintWriter writer, ClassInfo classInfo, int modifiers) { - if (classInfo.isAnnotation()) { - /* - * Annotation declaration. - */ - writer.append(Modifier.toString(modifiers & INTERFACE_MASK)); - writer.append(" @interface ").print(classInfo); - } else if (classInfo.isStandardClass()) { - /* - * Class declaration. - */ - List annotationNames = toNames(readClassAnnotationsFor(classInfo)); - if (!annotationNames.isEmpty()) { - writer.append(asAnnotations(annotationNames)); - } - writer.append(Modifier.toString(modifiers & CLASS_MASK)); - writer.append(" class ").print(classInfo); - Set superclasses = classInfo.getDirectSuperclasses(); - if (!superclasses.isEmpty()) { - writer.append(" extends ").print(stringOf(superclasses)); - } - Set interfaces = classInfo.getDirectlyImplementedInterfaces(); - if (!interfaces.isEmpty()) { - writer.append(" implements ").print(stringOf(interfaces)); - } - } else { - /* - * Interface declaration. - */ - List annotationNames = toNames(readInterfaceAnnotationsFor(classInfo)); - if (!annotationNames.isEmpty()) { - writer.append(asAnnotations(annotationNames)); - } - writer.append(Modifier.toString(modifiers & INTERFACE_MASK)); - writer.append(" interface ").print(classInfo); - Set superinterfaces = classInfo.getDirectSuperinterfaces(); - if (!superinterfaces.isEmpty()) { - writer.append(" extends ").print(stringOf(superinterfaces)); - } - } - writer.println(); - } - - private void writeMethods(PrintWriter writer, List methods) { - sort(methods); - for (MethodInfo method : methods) { - if (isVisible(method.getAccessFlags()) // Only public and protected methods - && isValid(method.getAccessFlags(), METHOD_MASK) // Excludes bridge and synthetic methods - && !isKotlinInternalScope(method)) { - writer.append(" ").println(filterAnnotationsFor(method)); - } - } - } - - private void writeFields(PrintWriter output, List fields) { - sort(fields); - for (FieldInfo field : fields) { - if (isVisible(field.getAccessFlags()) && isValid(field.getAccessFlags(), FIELD_MASK)) { - output.append(" ").println(field); - } - } - } - - private int getKotlinClassType(Class javaClass) { - if (metadataClass != null) { - Annotation metadata = javaClass.getAnnotation(metadataClass); - if (metadata != null) { - try { - return (int) classTypeMethod.invoke(metadata); - } catch (IllegalAccessException | InvocationTargetException e) { - getLogger().error("Failed to read Kotlin annotation", e); - } - } - } - return 0; - } - - private List toNames(Collection classes) { - return classes.stream() - .map(ClassInfo::toString) - .filter(ScanApi::isApplicationClass) - .collect(toList()); - } - - private Set readClassAnnotationsFor(ClassInfo classInfo) { - Set annotations = new HashSet<>(classInfo.getAnnotations()); - annotations.addAll(selectInheritedAnnotations(classInfo.getSuperclasses())); - annotations.addAll(selectInheritedAnnotations(classInfo.getImplementedInterfaces())); - return annotations; - } - - private Set readInterfaceAnnotationsFor(ClassInfo classInfo) { - Set annotations = new HashSet<>(classInfo.getAnnotations()); - annotations.addAll(selectInheritedAnnotations(classInfo.getSuperinterfaces())); - return annotations; - } - - /** - * Returns those annotations which have themselves been annotated as "Inherited". - */ - private List selectInheritedAnnotations(Collection classes) { - return classes.stream() - .flatMap(cls -> cls.getAnnotations().stream()) - .filter(ann -> ann.hasMetaAnnotation(Inherited.class.getName())) - .collect(toList()); - } - - private MethodInfo filterAnnotationsFor(MethodInfo method) { - return new MethodInfo( - method.getClassName(), - method.getMethodName(), - method.getAccessFlags(), - method.getTypeDescriptor(), - method.getAnnotationNames().stream() - .filter(ScanApi::isVisibleAnnotation) - .collect(toList()) - ); - } - } - - private static boolean isVisibleAnnotation(String annotationName) { - return !ANNOTATION_BLACKLIST.contains(annotationName); - } - - private static boolean isKotlinInternalScope(MethodInfo method) { - return method.getMethodName().indexOf('$') >= 0; - } - - private static boolean isValid(int modifiers, int mask) { - return (modifiers & mask) == modifiers; - } - - private static boolean isVisible(int accessFlags) { - return (accessFlags & VISIBILITY_MASK) != 0; - } - - private static String stringOf(Collection items) { - return items.stream().map(ClassInfo::toString).collect(joining(", ")); - } - - private static String asAnnotations(Collection items) { - return items.stream().collect(joining(" @", "@", " ")); - } - - private static boolean isApplicationClass(String typeName) { - return !typeName.startsWith("java.") && !typeName.startsWith("kotlin."); - } - - private static URL toURL(File file) throws MalformedURLException { - return file.toURI().toURL(); - } - - private static URL[] toURLs(Iterable files) throws MalformedURLException { - List urls = new LinkedList<>(); - for (File file : files) { - urls.add(toURL(file)); - } - return urls.toArray(new URL[urls.size()]); - } -} diff --git a/gradle-plugins/api-scanner/src/main/java/net/corda/plugins/ScannerExtension.java b/gradle-plugins/api-scanner/src/main/java/net/corda/plugins/ScannerExtension.java deleted file mode 100644 index 4e77437cfc..0000000000 --- a/gradle-plugins/api-scanner/src/main/java/net/corda/plugins/ScannerExtension.java +++ /dev/null @@ -1,37 +0,0 @@ -package net.corda.plugins; - -import java.util.List; - -import static java.util.Collections.emptyList; - -@SuppressWarnings("unused") -public class ScannerExtension { - - private boolean verbose; - private boolean enabled = true; - private List excludeClasses = emptyList(); - - public boolean isVerbose() { - return verbose; - } - - public void setVerbose(boolean verbose) { - this.verbose = verbose; - } - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public List getExcludeClasses() { - return excludeClasses; - } - - public void setExcludeClasses(List excludeClasses) { - this.excludeClasses = excludeClasses; - } -} diff --git a/gradle-plugins/api-scanner/src/main/resources/META-INF/gradle-plugins/net.corda.plugins.api-scanner.properties b/gradle-plugins/api-scanner/src/main/resources/META-INF/gradle-plugins/net.corda.plugins.api-scanner.properties deleted file mode 100644 index fc9e2277a5..0000000000 --- a/gradle-plugins/api-scanner/src/main/resources/META-INF/gradle-plugins/net.corda.plugins.api-scanner.properties +++ /dev/null @@ -1 +0,0 @@ -implementation-class=net.corda.plugins.ApiScanner diff --git a/gradle-plugins/build.gradle b/gradle-plugins/build.gradle deleted file mode 100644 index 1e04813546..0000000000 --- a/gradle-plugins/build.gradle +++ /dev/null @@ -1,83 +0,0 @@ -// This script exists just to allow bootstrapping the gradle plugins if maven central or jcenter are unavailable -// or if you are developing these plugins. See the readme for more information. - -buildscript { - // For sharing constants between builds - Properties constants = new Properties() - file("$projectDir/../constants.properties").withInputStream { constants.load(it) } - - // If you bump this version you must re-bootstrap the codebase. See the README for more information. - ext { - gradle_plugins_version = constants.getProperty("gradlePluginsVersion") - bouncycastle_version = constants.getProperty("bouncycastleVersion") - typesafe_config_version = constants.getProperty("typesafeConfigVersion") - jsr305_version = constants.getProperty("jsr305Version") - kotlin_version = constants.getProperty("kotlinVersion") - artifactory_plugin_version = constants.getProperty('artifactoryPluginVersion') - } - - repositories { - mavenLocal() - jcenter() - } - - dependencies { - classpath "net.corda.plugins:publish-utils:$gradle_plugins_version" - classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath "org.jfrog.buildinfo:build-info-extractor-gradle:$artifactory_plugin_version" - } -} - -apply plugin: 'net.corda.plugins.publish-utils' -apply plugin: 'com.jfrog.artifactory' - -allprojects { - version gradle_plugins_version - group 'net.corda.plugins' -} - -bintrayConfig { - user = System.getenv('CORDA_BINTRAY_USER') - key = System.getenv('CORDA_BINTRAY_KEY') - repo = 'corda' - org = 'r3' - licenses = ['Apache-2.0'] - vcsUrl = 'https://github.com/corda/corda' - projectUrl = 'https://github.com/corda/corda' - gpgSign = true - gpgPassphrase = System.getenv('CORDA_BINTRAY_GPG_PASSPHRASE') - publications = ['cordformation', 'quasar-utils', 'cordform-common', 'api-scanner', 'cordapp'] - license { - name = 'Apache-2.0' - url = 'https://www.apache.org/licenses/LICENSE-2.0' - distribution = 'repo' - } - developer { - id = 'R3' - name = 'R3' - email = 'dev@corda.net' - } -} - -artifactory { - publish { - contextUrl = 'https://ci-artifactory.corda.r3cev.com/artifactory' - repository { - repoKey = 'corda-dev' - username = 'teamcity' - password = System.getenv('CORDA_ARTIFACTORY_PASSWORD') - } - - defaults { - // Publish utils does not have a publish block because it would be circular for it to apply it's own - // extensions to itself - if(project.name == 'publish-utils') { - publications('publishUtils') - // Root project applies the plugin (for this block) but does not need to be published - } else if(project != rootProject) { - publications(project.extensions.publish.name()) - } - } - } -} \ No newline at end of file diff --git a/gradle-plugins/cordapp/README.md b/gradle-plugins/cordapp/README.md deleted file mode 100644 index 6b0cebe690..0000000000 --- a/gradle-plugins/cordapp/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Cordapp Gradle Plugin - -## Purpose - -To transform any project this plugin is applied to into a cordapp project that generates a cordapp JAR. - -## Effects - -Will modify the default JAR task to create a CorDapp format JAR instead [see here](https://docs.corda.net/cordapp-build-systems.html) -for more information. \ No newline at end of file diff --git a/gradle-plugins/cordapp/build.gradle b/gradle-plugins/cordapp/build.gradle deleted file mode 100644 index 3d1ecb6b53..0000000000 --- a/gradle-plugins/cordapp/build.gradle +++ /dev/null @@ -1,19 +0,0 @@ -apply plugin: 'kotlin' -apply plugin: 'net.corda.plugins.publish-utils' -apply plugin: 'com.jfrog.artifactory' - -description 'Turns a project into a cordapp project that produces cordapp fat JARs' - -repositories { - mavenCentral() - jcenter() -} - -dependencies { - compile gradleApi() - compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version" -} - -publish { - name project.name -} \ No newline at end of file diff --git a/gradle-plugins/cordapp/src/main/kotlin/net/corda/plugins/CordappPlugin.kt b/gradle-plugins/cordapp/src/main/kotlin/net/corda/plugins/CordappPlugin.kt deleted file mode 100644 index 62119cf0f5..0000000000 --- a/gradle-plugins/cordapp/src/main/kotlin/net/corda/plugins/CordappPlugin.kt +++ /dev/null @@ -1,75 +0,0 @@ -package net.corda.plugins - -import org.gradle.api.* -import org.gradle.api.artifacts.* -import org.gradle.jvm.tasks.Jar -import java.io.File - -/** - * The Cordapp plugin will turn a project into a cordapp project which builds cordapp JARs with the correct format - * and with the information needed to run on Corda. - */ -class CordappPlugin : Plugin { - override fun apply(project: Project) { - project.logger.info("Configuring ${project.name} as a cordapp") - - Utils.createCompileConfiguration("cordapp", project) - Utils.createCompileConfiguration("cordaCompile", project) - - val configuration: Configuration = project.configurations.create("cordaRuntime") - configuration.isTransitive = false - project.configurations.single { it.name == "runtime" }.extendsFrom(configuration) - - configureCordappJar(project) - } - - /** - * Configures this project's JAR as a Cordapp JAR - */ - private fun configureCordappJar(project: Project) { - // Note: project.afterEvaluate did not have full dependency resolution completed, hence a task is used instead - val task = project.task("configureCordappFatJar") - val jarTask = project.tasks.getByName("jar") as Jar - task.doLast { - jarTask.from(getDirectNonCordaDependencies(project).map { project.zipTree(it)}).apply { - exclude("META-INF/*.SF") - exclude("META-INF/*.DSA") - exclude("META-INF/*.RSA") - } - } - jarTask.dependsOn(task) - } - - private fun getDirectNonCordaDependencies(project: Project): Set { - project.logger.info("Finding direct non-corda dependencies for inclusion in CorDapp JAR") - val excludes = listOf( - mapOf("group" to "org.jetbrains.kotlin", "name" to "kotlin-stdlib"), - mapOf("group" to "org.jetbrains.kotlin", "name" to "kotlin-stdlib-jre8"), - mapOf("group" to "org.jetbrains.kotlin", "name" to "kotlin-reflect"), - mapOf("group" to "co.paralleluniverse", "name" to "quasar-core") - ) - - val runtimeConfiguration = project.configuration("runtime") - // The direct dependencies of this project - val excludeDeps = project.configuration("cordapp").allDependencies + - project.configuration("cordaCompile").allDependencies + - project.configuration("cordaRuntime").allDependencies - val directDeps = runtimeConfiguration.allDependencies - excludeDeps - // We want to filter out anything Corda related or provided by Corda, like kotlin-stdlib and quasar - val filteredDeps = directDeps.filter { dep -> - excludes.none { exclude -> (exclude["group"] == dep.group) && (exclude["name"] == dep.name) } - } - filteredDeps.forEach { - // net.corda or com.r3.corda may be a core dependency which shouldn't be included in this cordapp so give a warning - val group = it.group?.toString() ?: "" - if (group.startsWith("net.corda.") || group.startsWith("com.r3.corda.")) { - project.logger.warn("You appear to have included a Corda platform component ($it) using a 'compile' or 'runtime' dependency." + - "This can cause node stability problems. Please use 'corda' instead." + - "See http://docs.corda.net/cordapp-build-systems.html") - } else { - project.logger.info("Including dependency in CorDapp JAR: $it") - } - } - return filteredDeps.map { runtimeConfiguration.files(it) }.flatten().toSet() - } -} diff --git a/gradle-plugins/cordapp/src/main/kotlin/net/corda/plugins/Utils.kt b/gradle-plugins/cordapp/src/main/kotlin/net/corda/plugins/Utils.kt deleted file mode 100644 index 7572cd9876..0000000000 --- a/gradle-plugins/cordapp/src/main/kotlin/net/corda/plugins/Utils.kt +++ /dev/null @@ -1,35 +0,0 @@ -package net.corda.plugins - -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.artifacts.Configuration -import org.gradle.api.plugins.ExtraPropertiesExtension - -/** - * Mimics the "project.ext" functionality in groovy which provides a direct - * accessor to the "ext" extention (See: ExtraPropertiesExtension) - */ -@Suppress("UNCHECKED_CAST") -fun Project.ext(name: String): T = (extensions.findByName("ext") as ExtraPropertiesExtension).get(name) as T -fun Project.configuration(name: String): Configuration = configurations.single { it.name == name } - -class Utils { - companion object { - @JvmStatic - fun createCompileConfiguration(name: String, project: Project) { - if(!project.configurations.any { it.name == name }) { - val configuration = project.configurations.create(name) - configuration.isTransitive = false - project.configurations.single { it.name == "compile" }.extendsFrom(configuration) - } - } - fun createRuntimeConfiguration(name: String, project: Project) { - if(!project.configurations.any { it.name == name }) { - val configuration = project.configurations.create(name) - configuration.isTransitive = false - project.configurations.single { it.name == "runtime" }.extendsFrom(configuration) - } - } - } - -} \ No newline at end of file diff --git a/gradle-plugins/cordapp/src/main/resources/META-INF/gradle-plugins/net.corda.plugins.cordapp.properties b/gradle-plugins/cordapp/src/main/resources/META-INF/gradle-plugins/net.corda.plugins.cordapp.properties deleted file mode 100644 index 90871e27c8..0000000000 --- a/gradle-plugins/cordapp/src/main/resources/META-INF/gradle-plugins/net.corda.plugins.cordapp.properties +++ /dev/null @@ -1 +0,0 @@ -implementation-class=net.corda.plugins.CordappPlugin diff --git a/gradle-plugins/cordform-common/README.md b/gradle-plugins/cordform-common/README.md deleted file mode 100644 index 8b83c20e93..0000000000 --- a/gradle-plugins/cordform-common/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Cordform Common - -This project contains common node types that both the Corda gradle plugin suite and Corda project -require in order to build Corda nodes. \ No newline at end of file diff --git a/gradle-plugins/cordform-common/build.gradle b/gradle-plugins/cordform-common/build.gradle deleted file mode 100644 index be2fa0cf16..0000000000 --- a/gradle-plugins/cordform-common/build.gradle +++ /dev/null @@ -1,24 +0,0 @@ -apply plugin: 'java' -apply plugin: 'maven-publish' -apply plugin: 'net.corda.plugins.publish-utils' -apply plugin: 'com.jfrog.artifactory' - -repositories { - mavenCentral() -} - -// This tracks the gradle plugins version and not Corda -version gradle_plugins_version -group 'net.corda.plugins' - -dependencies { - // JSR 305: Nullability annotations - compile "com.google.code.findbugs:jsr305:$jsr305_version" - - // TypeSafe Config: for simple and human friendly config files. - compile "com.typesafe:config:$typesafe_config_version" -} - -publish { - name project.name -} \ No newline at end of file diff --git a/gradle-plugins/cordform-common/src/main/java/net/corda/cordform/CordformContext.java b/gradle-plugins/cordform-common/src/main/java/net/corda/cordform/CordformContext.java deleted file mode 100644 index 7687f68a11..0000000000 --- a/gradle-plugins/cordform-common/src/main/java/net/corda/cordform/CordformContext.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.corda.cordform; - -import java.nio.file.Path; - -public interface CordformContext { - Path baseDirectory(String nodeName); -} diff --git a/gradle-plugins/cordform-common/src/main/java/net/corda/cordform/CordformDefinition.java b/gradle-plugins/cordform-common/src/main/java/net/corda/cordform/CordformDefinition.java deleted file mode 100644 index fc62b1bbee..0000000000 --- a/gradle-plugins/cordform-common/src/main/java/net/corda/cordform/CordformDefinition.java +++ /dev/null @@ -1,40 +0,0 @@ -package net.corda.cordform; - -import javax.annotation.Nonnull; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - -public abstract class CordformDefinition { - private Path nodesDirectory = Paths.get("build", "nodes"); - private final List> nodeConfigurers = new ArrayList<>(); - private final List cordappPackages = new ArrayList<>(); - - public Path getNodesDirectory() { - return nodesDirectory; - } - - public void setNodesDirectory(Path nodesDirectory) { - this.nodesDirectory = nodesDirectory; - } - - public List> getNodeConfigurers() { - return nodeConfigurers; - } - - public void addNode(Consumer configurer) { - nodeConfigurers.add(configurer); - } - - public List getCordappPackages() { - return cordappPackages; - } - - /** - * Make arbitrary changes to the node directories before they are started. - * @param context Lookup of node directory by node name. - */ - public abstract void setup(@Nonnull CordformContext context); -} diff --git a/gradle-plugins/cordform-common/src/main/java/net/corda/cordform/CordformNode.java b/gradle-plugins/cordform-common/src/main/java/net/corda/cordform/CordformNode.java deleted file mode 100644 index 52300f0f63..0000000000 --- a/gradle-plugins/cordform-common/src/main/java/net/corda/cordform/CordformNode.java +++ /dev/null @@ -1,173 +0,0 @@ -package net.corda.cordform; - -import com.typesafe.config.Config; -import com.typesafe.config.ConfigFactory; -import com.typesafe.config.ConfigValueFactory; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.List; -import java.util.Map; - -import static java.util.Collections.emptyList; - -public class CordformNode implements NodeDefinition { - /** - * Path relative to the running node where the serialized NodeInfos are stored. - */ - public static final String NODE_INFO_DIRECTORY = "additional-node-infos"; - - protected static final String DEFAULT_HOST = "localhost"; - - /** - * Name of the node. - */ - private String name; - - public String getName() { - return name; - } - - /** - * Set the RPC users for this node. This configuration block allows arbitrary configuration. - * The recommended current structure is: - * [[['username': "username_here", 'password': "password_here", 'permissions': ["permissions_here"]]] - * The above is a list to a map of keys to values using Groovy map and list shorthands. - * - * Incorrect configurations will not cause a DSL error. - */ - public List> rpcUsers = emptyList(); - - /** - * Apply the notary configuration if this node is a notary. The map is the config structure of - * net.corda.node.services.config.NotaryConfig - */ - public Map notary = null; - - public Map extraConfig = null; - - protected Config config = ConfigFactory.empty(); - - public Config getConfig() { - return config; - } - - /** - * Set the name of the node. - * - * @param name The node name. - */ - public void name(String name) { - this.name = name; - setValue("myLegalName", name); - } - - /** - * Get the artemis address for this node. - * - * @return This node's P2P address. - */ - @Nonnull - public String getP2pAddress() { - return config.getString("p2pAddress"); - } - - /** - * Set the Artemis P2P port for this node on localhost. - * - * @param p2pPort The Artemis messaging queue port. - */ - public void p2pPort(int p2pPort) { - p2pAddress(DEFAULT_HOST + ':' + p2pPort); - } - - /** - * Set the Artemis P2P address for this node. - * - * @param p2pAddress The Artemis messaging queue host and port. - */ - public void p2pAddress(String p2pAddress) { - setValue("p2pAddress", p2pAddress); - } - - /** - * Returns the RPC address for this node, or null if one hasn't been specified. - */ - @Nullable - public String getRpcAddress() { - if (config.hasPath("rpcSettings.address")) { - return config.getConfig("rpcSettings").getString("address"); - } - return getOptionalString("rpcAddress"); - } - - /** - * Set the Artemis RPC port for this node on localhost. - * - * @param rpcPort The Artemis RPC queue port. - * @deprecated Use {@link CordformNode#rpcSettings(RpcSettings)} instead. - */ - @Deprecated - public void rpcPort(int rpcPort) { - rpcAddress(DEFAULT_HOST + ':' + rpcPort); - } - - /** - * Set the Artemis RPC address for this node. - * - * @param rpcAddress The Artemis RPC queue host and port. - * @deprecated Use {@link CordformNode#rpcSettings(RpcSettings)} instead. - */ - @Deprecated - public void rpcAddress(String rpcAddress) { - setValue("rpcAddress", rpcAddress); - } - - /** - * Returns the address of the web server that will connect to the node, or null if one hasn't been specified. - */ - @Nullable - public String getWebAddress() { - return getOptionalString("webAddress"); - } - - /** - * Configure a webserver to connect to the node via RPC. This port will specify the port it will listen on. The node - * must have an RPC address configured. - */ - public void webPort(int webPort) { - webAddress(DEFAULT_HOST + ':' + webPort); - } - - /** - * Configure a webserver to connect to the node via RPC. This address will specify the port it will listen on. The node - * must have an RPC address configured. - */ - public void webAddress(String webAddress) { - setValue("webAddress", webAddress); - } - - /** - * Specifies RPC settings for the node. - */ - public void rpcSettings(RpcSettings settings) { - config = settings.addTo("rpcSettings", config); - } - - /** - * Set the path to a file with optional properties, which are appended to the generated node.conf file. - * - * @param configFile The file path. - */ - public void configFile(String configFile) { - setValue("configFile", configFile); - } - - private String getOptionalString(String path) { - return config.hasPath(path) ? config.getString(path) : null; - } - - private void setValue(String path, Object value) { - config = config.withValue(path, ConfigValueFactory.fromAnyRef(value)); - } -} diff --git a/gradle-plugins/cordform-common/src/main/java/net/corda/cordform/NodeDefinition.java b/gradle-plugins/cordform-common/src/main/java/net/corda/cordform/NodeDefinition.java deleted file mode 100644 index 0b86b98627..0000000000 --- a/gradle-plugins/cordform-common/src/main/java/net/corda/cordform/NodeDefinition.java +++ /dev/null @@ -1,9 +0,0 @@ -package net.corda.cordform; - -import com.typesafe.config.Config; - -public interface NodeDefinition { - String getName(); - - Config getConfig(); -} diff --git a/gradle-plugins/cordform-common/src/main/java/net/corda/cordform/RpcSettings.java b/gradle-plugins/cordform-common/src/main/java/net/corda/cordform/RpcSettings.java deleted file mode 100644 index e429bb0ca6..0000000000 --- a/gradle-plugins/cordform-common/src/main/java/net/corda/cordform/RpcSettings.java +++ /dev/null @@ -1,56 +0,0 @@ -package net.corda.cordform; - -import com.typesafe.config.Config; -import com.typesafe.config.ConfigFactory; -import com.typesafe.config.ConfigValueFactory; - -public final class RpcSettings { - - private Config config = ConfigFactory.empty(); - - /** - * RPC address for the node. - */ - public final void address(final String value) { - setValue("address", value); - } - - /** - * RPC admin address for the node (necessary if [useSsl] is false or unset). - */ - public final void adminAddress(final String value) { - setValue("adminAddress", value); - } - - /** - * Specifies whether the node RPC layer will require SSL from clients. - */ - public final void useSsl(final Boolean value) { - setValue("useSsl", value); - } - - /** - * Specifies whether the RPC broker is separate from the node. - */ - public final void standAloneBroker(final Boolean value) { - setValue("standAloneBroker", value); - } - - /** - * Specifies SSL certificates options for the RPC layer. - */ - public final void ssl(final SslOptions options) { - config = options.addTo("ssl", config); - } - - final Config addTo(final String key, final Config config) { - if (this.config.isEmpty()) { - return config; - } - return config.withValue(key, this.config.root()); - } - - private void setValue(String path, Object value) { - config = config.withValue(path, ConfigValueFactory.fromAnyRef(value)); - } -} diff --git a/gradle-plugins/cordform-common/src/main/java/net/corda/cordform/SslOptions.java b/gradle-plugins/cordform-common/src/main/java/net/corda/cordform/SslOptions.java deleted file mode 100644 index da3cc22288..0000000000 --- a/gradle-plugins/cordform-common/src/main/java/net/corda/cordform/SslOptions.java +++ /dev/null @@ -1,56 +0,0 @@ -package net.corda.cordform; - -import com.typesafe.config.Config; -import com.typesafe.config.ConfigFactory; -import com.typesafe.config.ConfigValueFactory; - -public final class SslOptions { - - private Config config = ConfigFactory.empty(); - - /** - * Password for the keystore. - */ - public final void keyStorePassword(final String value) { - setValue("keyStorePassword", value); - } - - /** - * Password for the truststore. - */ - public final void trustStorePassword(final String value) { - setValue("trustStorePassword", value); - } - - /** - * Directory under which key stores are to be placed. - */ - public final void certificatesDirectory(final String value) { - setValue("certificatesDirectory", value); - } - - /** - * Absolute path to SSL keystore. Default: "[certificatesDirectory]/sslkeystore.jks" - */ - public final void sslKeystore(final String value) { - setValue("sslKeystore", value); - } - - /** - * Absolute path to SSL truststore. Default: "[certificatesDirectory]/truststore.jks" - */ - public final void trustStoreFile(final String value) { - setValue("trustStoreFile", value); - } - - final Config addTo(final String key, final Config config) { - if (this.config.isEmpty()) { - return config; - } - return config.withValue(key, this.config.root()); - } - - private void setValue(String path, Object value) { - config = config.withValue(path, ConfigValueFactory.fromAnyRef(value)); - } -} diff --git a/gradle-plugins/cordformation/README.rst b/gradle-plugins/cordformation/README.rst deleted file mode 100644 index f619737a91..0000000000 --- a/gradle-plugins/cordformation/README.rst +++ /dev/null @@ -1 +0,0 @@ -Please refer to the documentation in /doc/build/html/running-a-node.html#cordformation. \ No newline at end of file diff --git a/gradle-plugins/cordformation/build.gradle b/gradle-plugins/cordformation/build.gradle deleted file mode 100644 index 6c22f78a9e..0000000000 --- a/gradle-plugins/cordformation/build.gradle +++ /dev/null @@ -1,62 +0,0 @@ -buildscript { - repositories { - mavenCentral() - } - - dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - -apply plugin: 'kotlin' -apply plugin: 'net.corda.plugins.publish-utils' -apply plugin: 'com.jfrog.artifactory' - -description 'A small gradle plugin for adding some basic Quasar tasks and configurations to reduce build.gradle bloat.' - -repositories { - mavenCentral() -} - -configurations { - noderunner - compile.extendsFrom noderunner -} - -sourceSets { - runnodes { - kotlin { - srcDir file('src/noderunner/kotlin') - compileClasspath += configurations.noderunner - } - } -} - -dependencies { - compile gradleApi() - compile project(":cordapp") - compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version" - - noderunner "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version" - - compile project(':cordform-common') -} - -task createNodeRunner(type: Jar, dependsOn: [classes]) { - manifest { - attributes('Main-Class': 'net.corda.plugins.NodeRunnerKt') - } - classifier = 'fatjar' - from { configurations.noderunner.collect { it.isDirectory() ? it : zipTree(it) } } - from sourceSets.runnodes.output -} - -jar { - from(createNodeRunner) { - rename { 'net/corda/plugins/runnodes.jar' } - } -} - -publish { - name project.name -} diff --git a/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/Cordform.kt b/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/Cordform.kt deleted file mode 100644 index 1d44484eb2..0000000000 --- a/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/Cordform.kt +++ /dev/null @@ -1,218 +0,0 @@ -package net.corda.plugins - -import groovy.lang.Closure -import net.corda.cordform.CordformDefinition -import org.apache.tools.ant.filters.FixCrLfFilter -import org.gradle.api.DefaultTask -import org.gradle.api.plugins.JavaPluginConvention -import org.gradle.api.tasks.SourceSet.MAIN_SOURCE_SET_NAME -import org.gradle.api.tasks.TaskAction -import java.io.File -import java.lang.reflect.InvocationTargetException -import java.net.URLClassLoader -import java.nio.file.Path -import java.nio.file.Paths -import java.util.jar.JarInputStream - -/** - * Creates nodes based on the configuration of this task in the gradle configuration DSL. - * - * See documentation for examples. - */ -@Suppress("unused") -open class Cordform : DefaultTask() { - private companion object { - val nodeJarName = "corda.jar" - private val defaultDirectory: Path = Paths.get("build", "nodes") - } - - /** - * Optionally the name of a CordformDefinition subclass to which all configuration will be delegated. - */ - @Suppress("MemberVisibilityCanPrivate") - var definitionClass: String? = null - private var directory = defaultDirectory - private val nodes = mutableListOf() - - /** - * Set the directory to install nodes into. - * - * @param directory The directory the nodes will be installed into. - */ - fun directory(directory: String) { - this.directory = Paths.get(directory) - } - - /** - * Add a node configuration. - * - * @param configureClosure A node configuration that will be deployed. - */ - @Suppress("MemberVisibilityCanPrivate") - fun node(configureClosure: Closure) { - nodes += project.configure(Node(project), configureClosure) as Node - } - - /** - * Add a node configuration - * - * @param configureFunc A node configuration that will be deployed - */ - @Suppress("MemberVisibilityCanPrivate") - fun node(configureFunc: Node.() -> Any?): Node { - val node = Node(project).apply { configureFunc() } - nodes += node - return node - } - - /** - * Returns a node by name. - * - * @param name The name of the node as specified in the node configuration DSL. - * @return A node instance. - */ - private fun getNodeByName(name: String): Node? = nodes.firstOrNull { it.name == name } - - /** - * Installs the run script into the nodes directory. - */ - private fun installRunScript() { - project.copy { - it.apply { - from(Cordformation.getPluginFile(project, "net/corda/plugins/runnodes.jar")) - fileMode = Cordformation.executableFileMode - into("$directory/") - } - } - - project.copy { - it.apply { - from(Cordformation.getPluginFile(project, "net/corda/plugins/runnodes")) - // Replaces end of line with lf to avoid issues with the bash interpreter and Windows style line endings. - filter(mapOf("eol" to FixCrLfFilter.CrLf.newInstance("lf")), FixCrLfFilter::class.java) - fileMode = Cordformation.executableFileMode - into("$directory/") - } - } - - project.copy { - it.apply { - from(Cordformation.getPluginFile(project, "net/corda/plugins/runnodes.bat")) - into("$directory/") - } - } - } - - /** - * The definitionClass needn't be compiled until just before our build method, so we load it manually via sourceSets.main.runtimeClasspath. - */ - private fun loadCordformDefinition(): CordformDefinition { - val plugin = project.convention.getPlugin(JavaPluginConvention::class.java) - val classpath = plugin.sourceSets.getByName(MAIN_SOURCE_SET_NAME).runtimeClasspath - val urls = classpath.files.map { it.toURI().toURL() }.toTypedArray() - return URLClassLoader(urls, CordformDefinition::class.java.classLoader) - .loadClass(definitionClass) - .asSubclass(CordformDefinition::class.java) - .newInstance() - } - - /** - * The NetworkBootstrapper needn't be compiled until just before our build method, so we load it manually via sourceSets.main.runtimeClasspath. - */ - private fun loadNetworkBootstrapperClass(): Class<*> { - val plugin = project.convention.getPlugin(JavaPluginConvention::class.java) - val classpath = plugin.sourceSets.getByName(MAIN_SOURCE_SET_NAME).runtimeClasspath - val urls = classpath.files.map { it.toURI().toURL() }.toTypedArray() - return URLClassLoader(urls, javaClass.classLoader).loadClass("net.corda.nodeapi.internal.network.NetworkBootstrapper") - } - - /** - * This task action will create and install the nodes based on the node configurations added. - */ - @TaskAction - fun build() { - project.logger.info("Running Cordform task") - initializeConfiguration() - nodes.forEach(Node::installConfig) - installCordaJar() - installRunScript() - bootstrapNetwork() - nodes.forEach(Node::build) - } - - /** - * Installs the corda fat JAR to the root directory, for the network bootstrapper to use. - */ - private fun installCordaJar() { - val cordaJar = Cordformation.verifyAndGetRuntimeJar(project, "corda") - project.copy { - it.apply { - from(cordaJar) - into(directory) - rename(cordaJar.name, nodeJarName) - fileMode = Cordformation.executableFileMode - } - } - } - - private fun initializeConfiguration() { - if (definitionClass != null) { - val cd = loadCordformDefinition() - // If the user has specified their own directory (even if it's the same default path) then let them know - // it's not used and should just rely on the one in CordformDefinition - require(directory === defaultDirectory) { - "'directory' cannot be used when 'definitionClass' is specified. Use CordformDefinition.nodesDirectory instead." - } - directory = cd.nodesDirectory - val cordapps = cd.getMatchingCordapps() - cd.nodeConfigurers.forEach { - val node = node { } - it.accept(node) - node.additionalCordapps.addAll(cordapps) - node.rootDir(directory) - } - cd.setup { nodeName -> project.projectDir.toPath().resolve(getNodeByName(nodeName)!!.nodeDir.toPath()) } - } else { - nodes.forEach { - it.rootDir(directory) - } - } - } - - private fun bootstrapNetwork() { - val networkBootstrapperClass = loadNetworkBootstrapperClass() - val networkBootstrapper = networkBootstrapperClass.newInstance() - val bootstrapMethod = networkBootstrapperClass.getMethod("bootstrap", Path::class.java).apply { isAccessible = true } - // Call NetworkBootstrapper.bootstrap - try { - val rootDir = project.projectDir.toPath().resolve(directory).toAbsolutePath().normalize() - bootstrapMethod.invoke(networkBootstrapper, rootDir) - } catch (e: InvocationTargetException) { - throw e.cause!! - } - } - - private fun CordformDefinition.getMatchingCordapps(): List { - val cordappJars = project.configuration("cordapp").files - return cordappPackages.map { `package` -> - val cordappsWithPackage = cordappJars.filter { it.containsPackage(`package`) } - when (cordappsWithPackage.size) { - 0 -> throw IllegalArgumentException("There are no cordapp dependencies containing the package $`package`") - 1 -> cordappsWithPackage[0] - else -> throw IllegalArgumentException("More than one cordapp dependency contains the package $`package`: $cordappsWithPackage") - } - } - } - - private fun File.containsPackage(`package`: String): Boolean { - JarInputStream(inputStream()).use { - while (true) { - val name = it.nextJarEntry?.name ?: break - if (name.endsWith(".class") && name.replace('/', '.').startsWith(`package`)) { - return true - } - } - return false - } - } -} diff --git a/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/Cordformation.kt b/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/Cordformation.kt deleted file mode 100644 index 82a818992d..0000000000 --- a/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/Cordformation.kt +++ /dev/null @@ -1,62 +0,0 @@ -package net.corda.plugins - -import org.gradle.api.Plugin -import org.gradle.api.Project -import java.io.File - -/** - * The Cordformation plugin deploys nodes to a directory in a state ready to be used by a developer for experimentation, - * testing, and debugging. It will prepopulate several fields in the configuration and create a simple node runner. - */ -class Cordformation : Plugin { - internal companion object { - const val CORDFORMATION_TYPE = "cordformationInternal" - - /** - * Gets a resource file from this plugin's JAR file. - * - * @param project The project environment this plugin executes in. - * @param filePathInJar The file in the JAR, relative to root, you wish to access. - * @return A file handle to the file in the JAR. - */ - fun getPluginFile(project: Project, filePathInJar: String): File { - val archive = project.rootProject.buildscript.configurations - .single { it.name == "classpath" } - .first { it.name.contains("cordformation") } - return project.rootProject.resources.text - .fromArchiveEntry(archive, filePathInJar) - .asFile() - } - - /** - * Gets a current built corda jar file - * - * @param project The project environment this plugin executes in. - * @param jarName The name of the JAR you wish to access. - * @return A file handle to the file in the JAR. - */ - fun verifyAndGetRuntimeJar(project: Project, jarName: String): File { - val releaseVersion = project.rootProject.ext("corda_release_version") - val maybeJar = project.configuration("runtime").filter { - "$jarName-$releaseVersion.jar" in it.toString() || "$jarName-r3-$releaseVersion.jar" in it.toString() - } - if (maybeJar.isEmpty) { - throw IllegalStateException("No $jarName JAR found. Have you deployed the Corda project to Maven? Looked for \"$jarName-$releaseVersion.jar\"") - } else { - val jar = maybeJar.singleFile - require(jar.isFile) - return jar - } - } - - val executableFileMode = "0755".toInt(8) - } - - override fun apply(project: Project) { - Utils.createCompileConfiguration("cordapp", project) - Utils.createRuntimeConfiguration(CORDFORMATION_TYPE, project) - // TODO: improve how we re-use existing declared external variables from root gradle.build - val jolokiaVersion = try { project.rootProject.ext("jolokia_version") } catch (e: Exception) { "1.3.7" } - project.dependencies.add(CORDFORMATION_TYPE, "org.jolokia:jolokia-jvm:$jolokiaVersion:agent") - } -} diff --git a/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/Node.kt b/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/Node.kt deleted file mode 100644 index 2f8cb543d0..0000000000 --- a/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/Node.kt +++ /dev/null @@ -1,239 +0,0 @@ -package net.corda.plugins - -import com.typesafe.config.ConfigFactory -import com.typesafe.config.ConfigRenderOptions -import com.typesafe.config.ConfigValueFactory -import groovy.lang.Closure -import net.corda.cordform.CordformNode -import org.gradle.api.Project -import java.io.File -import java.nio.charset.StandardCharsets -import java.nio.file.Files -import java.nio.file.Path - -/** - * Represents a node that will be installed. - */ -class Node(private val project: Project) : CordformNode() { - companion object { - @JvmStatic - val webJarName = "corda-webserver.jar" - private val configFileProperty = "configFile" - } - - /** - * Set the list of CorDapps to install to the plugins directory. Each cordapp is a fully qualified Maven - * dependency name, eg: com.example:product-name:0.1 - * - * @note Your app will be installed by default and does not need to be included here. - * @note Type is any due to gradle's use of "GStrings" - each value will have "toString" called on it - */ - var cordapps = mutableListOf() - internal var additionalCordapps = mutableListOf() - internal lateinit var nodeDir: File - private set - internal lateinit var rootDir: File - private set - - /** - * Sets whether this node will use HTTPS communication. - * - * @param isHttps True if this node uses HTTPS communication. - */ - fun https(isHttps: Boolean) { - config = config.withValue("useHTTPS", ConfigValueFactory.fromAnyRef(isHttps)) - } - - /** - * Sets the H2 port for this node - */ - fun h2Port(h2Port: Int) { - config = config.withValue("h2port", ConfigValueFactory.fromAnyRef(h2Port)) - } - - fun useTestClock(useTestClock: Boolean) { - config = config.withValue("useTestClock", ConfigValueFactory.fromAnyRef(useTestClock)) - } - - /** - * Specifies RPC settings for the node. - */ - fun rpcSettings(configureClosure: Closure) { - val rpcSettings = project.configure(RpcSettings(project), configureClosure) as RpcSettings - config = rpcSettings.addTo("rpcSettings", config) - } - - /** - * Enables SSH access on given port - * - * @param sshdPort The port for SSH server to listen on - */ - fun sshdPort(sshdPort: Int?) { - config = config.withValue("sshd.port", ConfigValueFactory.fromAnyRef(sshdPort)) - } - - internal fun build() { - if (config.hasPath("webAddress")) { - installWebserverJar() - } - installAgentJar() - installBuiltCordapp() - installCordapps() - } - - internal fun rootDir(rootDir: Path) { - if (name == null) { - project.logger.error("Node has a null name - cannot create node") - throw IllegalStateException("Node has a null name - cannot create node") - } - // Parsing O= part directly because importing BouncyCastle provider in Cordformation causes problems - // with loading our custom X509EdDSAEngine. - val organizationName = name.trim().split(",").firstOrNull { it.startsWith("O=") }?.substringAfter("=") - val dirName = organizationName ?: name - this.rootDir = rootDir.toFile() - nodeDir = File(this.rootDir, dirName.replace("\\s", "")) - Files.createDirectories(nodeDir.toPath()) - } - - private fun configureProperties() { - config = config.withValue("database.runMigration", ConfigValueFactory.fromAnyRef(true)) - config = config.withValue("rpcUsers", ConfigValueFactory.fromIterable(rpcUsers)) - if (notary != null) { - config = config.withValue("notary", ConfigValueFactory.fromMap(notary)) - } - if (extraConfig != null) { - config = config.withFallback(ConfigFactory.parseMap(extraConfig)) - } - } - - /** - * Installs the corda webserver JAR to the node directory - */ - private fun installWebserverJar() { - val webJar = Cordformation.verifyAndGetRuntimeJar(project, "corda-webserver") - project.copy { - it.apply { - from(webJar) - into(nodeDir) - rename(webJar.name, webJarName) - } - } - } - - /** - * Installs this project's cordapp to this directory. - */ - private fun installBuiltCordapp() { - val cordappsDir = File(nodeDir, "cordapps") - project.copy { - it.apply { - from(project.tasks.getByName("jar")) - into(cordappsDir) - } - } - } - - /** - * Installs the jolokia monitoring agent JAR to the node/drivers directory - */ - private fun installAgentJar() { - // TODO: improve how we re-use existing declared external variables from root gradle.build - val jolokiaVersion = try { project.rootProject.ext("jolokia_version") } catch (e: Exception) { "1.3.7" } - val agentJar = project.configuration("runtime").files { - (it.group == "org.jolokia") && - (it.name == "jolokia-jvm") && - (it.version == jolokiaVersion) - // TODO: revisit when classifier attribute is added. eg && (it.classifier = "agent") - }.first() // should always be the jolokia agent fat jar: eg. jolokia-jvm-1.3.7-agent.jar - project.logger.info("Jolokia agent jar: $agentJar") - if (agentJar.isFile) { - val driversDir = File(nodeDir, "drivers") - project.copy { - it.apply { - from(agentJar) - into(driversDir) - } - } - } - } - - private fun createTempConfigFile(): File { - val options = ConfigRenderOptions - .defaults() - .setOriginComments(false) - .setComments(false) - .setFormatted(true) - .setJson(false) - val configFileText = config.root().render(options).split("\n").toList() - // Need to write a temporary file first to use the project.copy, which resolves directories correctly. - val tmpDir = File(project.buildDir, "tmp") - Files.createDirectories(tmpDir.toPath()) - var fileName = "${nodeDir.name}.conf" - val tmpConfFile = File(tmpDir, fileName) - Files.write(tmpConfFile.toPath(), configFileText, StandardCharsets.UTF_8) - return tmpConfFile - } - - /** - * Installs the configuration file to the root directory and detokenises it. - */ - internal fun installConfig() { - configureProperties() - val tmpConfFile = createTempConfigFile() - appendOptionalConfig(tmpConfFile) - project.copy { - it.apply { - from(tmpConfFile) - into(rootDir) - } - } - } - - /** - * Appends installed config file with properties from an optional file. - */ - private fun appendOptionalConfig(confFile: File) { - val optionalConfig: File? = when { - project.findProperty(configFileProperty) != null -> //provided by -PconfigFile command line property when running Gradle task - File(project.findProperty(configFileProperty) as String) - config.hasPath(configFileProperty) -> File(config.getString(configFileProperty)) - else -> null - } - - if (optionalConfig != null) { - if (!optionalConfig.exists()) { - project.logger.error("$configFileProperty '$optionalConfig' not found") - } else { - confFile.appendBytes(optionalConfig.readBytes()) - } - } - } - - /** - * Installs other cordapps to this node's cordapps directory. - */ - internal fun installCordapps() { - additionalCordapps.addAll(getCordappList()) - val cordappsDir = File(nodeDir, "cordapps") - project.copy { - it.apply { - from(additionalCordapps) - into(cordappsDir) - } - } - } - - /** - * Gets a list of cordapps based on what dependent cordapps were specified. - * - * @return List of this node's cordapps. - */ - private fun getCordappList(): Collection { - // Cordapps can sometimes contain a GString instance which fails the equality test with the Java string - @Suppress("RemoveRedundantCallsOfConversionMethods") - val cordapps: List = cordapps.map { it.toString() } - return project.configuration("cordapp").files { - cordapps.contains(it.group + ":" + it.name + ":" + it.version) - } - } -} diff --git a/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/RpcSettings.kt b/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/RpcSettings.kt deleted file mode 100644 index 2f46f0b2c5..0000000000 --- a/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/RpcSettings.kt +++ /dev/null @@ -1,59 +0,0 @@ -package net.corda.plugins - -import com.typesafe.config.Config -import com.typesafe.config.ConfigFactory -import com.typesafe.config.ConfigValueFactory -import groovy.lang.Closure -import org.gradle.api.Project - -class RpcSettings(private val project: Project) { - private var config: Config = ConfigFactory.empty() - - /** - * RPC address for the node. - */ - fun address(value: String) { - config += "address" to value - } - - /** - * RPC admin address for the node (necessary if [useSsl] is false or unset). - */ - fun adminAddress(value: String) { - config += "adminAddress" to value - } - - /** - * Specifies whether the node RPC layer will require SSL from clients. - */ - fun useSsl(value: Boolean) { - config += "useSsl" to value - } - - /** - * Specifies whether the RPC broker is separate from the node. - */ - fun standAloneBroker(value: Boolean) { - config += "standAloneBroker" to value - } - - /** - * Specifies SSL certificates options for the RPC layer. - */ - fun ssl(configureClosure: Closure) { - val sslOptions = project.configure(SslOptions(), configureClosure) as SslOptions - config = sslOptions.addTo("ssl", config) - } - - internal fun addTo(key: String, config: Config): Config { - if (this.config.isEmpty) { - return config - } - return config + (key to this.config.root()) - } -} - -internal operator fun Config.plus(entry: Pair): Config { - - return withValue(entry.first, ConfigValueFactory.fromAnyRef(entry.second)) -} \ No newline at end of file diff --git a/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/SslOptions.kt b/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/SslOptions.kt deleted file mode 100644 index bb8fed288e..0000000000 --- a/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/SslOptions.kt +++ /dev/null @@ -1,50 +0,0 @@ -package net.corda.plugins - -import com.typesafe.config.Config -import com.typesafe.config.ConfigFactory - -class SslOptions { - private var config: Config = ConfigFactory.empty() - - /** - * Password for the keystore. - */ - fun keyStorePassword(value: String) { - config += "keyStorePassword" to value - } - - /** - * Password for the truststore. - */ - fun trustStorePassword(value: String) { - config += "trustStorePassword" to value - } - - /** - * Directory under which key stores are to be placed. - */ - fun certificatesDirectory(value: String) { - config += "certificatesDirectory" to value - } - - /** - * Absolute path to SSL keystore. Default: "[certificatesDirectory]/sslkeystore.jks" - */ - fun sslKeystore(value: String) { - config += "sslKeystore" to value - } - - /** - * Absolute path to SSL truststore. Default: "[certificatesDirectory]/truststore.jks" - */ - fun trustStoreFile(value: String) { - config += "trustStoreFile" to value - } - - internal fun addTo(key: String, config: Config): Config { - if (this.config.isEmpty) { - return config - } - return config + (key to this.config.root()) - } -} \ No newline at end of file diff --git a/gradle-plugins/cordformation/src/main/resources/META-INF/gradle-plugins/net.corda.plugins.cordformation.properties b/gradle-plugins/cordformation/src/main/resources/META-INF/gradle-plugins/net.corda.plugins.cordformation.properties deleted file mode 100644 index 4475d5c692..0000000000 --- a/gradle-plugins/cordformation/src/main/resources/META-INF/gradle-plugins/net.corda.plugins.cordformation.properties +++ /dev/null @@ -1 +0,0 @@ -implementation-class=net.corda.plugins.Cordformation diff --git a/gradle-plugins/cordformation/src/main/resources/net/corda/plugins/runnodes b/gradle-plugins/cordformation/src/main/resources/net/corda/plugins/runnodes deleted file mode 100644 index 9e3ba4c5be..0000000000 --- a/gradle-plugins/cordformation/src/main/resources/net/corda/plugins/runnodes +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -# Allow the script to be run from outside the nodes directory. -basedir=$( dirname "$0" ) -cd "$basedir" - -if which osascript >/dev/null; then - /usr/libexec/java_home -v 1.8 --exec java -jar runnodes.jar "$@" -else - "${JAVA_HOME:+$JAVA_HOME/bin/}java" -jar runnodes.jar "$@" -fi diff --git a/gradle-plugins/cordformation/src/main/resources/net/corda/plugins/runnodes.bat b/gradle-plugins/cordformation/src/main/resources/net/corda/plugins/runnodes.bat deleted file mode 100644 index a6acf1f737..0000000000 --- a/gradle-plugins/cordformation/src/main/resources/net/corda/plugins/runnodes.bat +++ /dev/null @@ -1,8 +0,0 @@ -@echo off - -REM Change to the directory of this script (%~dp0) -Pushd %~dp0 - -java -jar runnodes.jar %* - -Popd \ No newline at end of file diff --git a/gradle-plugins/cordformation/src/noderunner/kotlin/net/corda/plugins/NodeRunner.kt b/gradle-plugins/cordformation/src/noderunner/kotlin/net/corda/plugins/NodeRunner.kt deleted file mode 100644 index bb308a8191..0000000000 --- a/gradle-plugins/cordformation/src/noderunner/kotlin/net/corda/plugins/NodeRunner.kt +++ /dev/null @@ -1,151 +0,0 @@ -package net.corda.plugins - -import java.awt.GraphicsEnvironment -import java.io.File -import java.nio.file.Files -import java.util.* - -private val HEADLESS_FLAG = "--headless" -private val CAPSULE_DEBUG_FLAG = "--capsule-debug" - -private val os by lazy { - val osName = System.getProperty("os.name", "generic").toLowerCase(Locale.ENGLISH) - if ("mac" in osName || "darwin" in osName) OS.MACOS - else if ("win" in osName) OS.WINDOWS - else OS.LINUX -} - -private enum class OS { MACOS, WINDOWS, LINUX } - -private object debugPortAlloc { - private var basePort = 5005 - internal fun next() = basePort++ -} - -private object monitoringPortAlloc { - private var basePort = 7005 - internal fun next() = basePort++ -} - -fun main(args: Array) { - val startedProcesses = mutableListOf() - val headless = GraphicsEnvironment.isHeadless() || args.contains(HEADLESS_FLAG) - val capsuleDebugMode = args.contains(CAPSULE_DEBUG_FLAG) - val workingDir = File(System.getProperty("user.dir")) - val javaArgs = args.filter { it != HEADLESS_FLAG && it != CAPSULE_DEBUG_FLAG } - val jvmArgs = if (capsuleDebugMode) listOf("-Dcapsule.log=verbose") else emptyList() - println("Starting nodes in $workingDir") - workingDir.listFiles { file -> file.isDirectory }.forEach { dir -> - listOf(NodeJarType, WebJarType).forEach { jarType -> - jarType.acceptDirAndStartProcess(dir, headless, javaArgs, jvmArgs)?.let { startedProcesses += it } - } - } - println("Started ${startedProcesses.size} processes") - println("Finished starting nodes") -} - -private abstract class JarType(private val jarName: String) { - internal abstract fun acceptNodeConf(nodeConf: File): Boolean - internal fun acceptDirAndStartProcess(dir: File, headless: Boolean, javaArgs: List, jvmArgs: List): Process? { - if (!File(dir, jarName).exists()) { - return null - } - if (!File(dir, "node.conf").let { it.exists() && acceptNodeConf(it) }) { - return null - } - val debugPort = debugPortAlloc.next() - val monitoringPort = monitoringPortAlloc.next() - println("Starting $jarName in $dir on debug port $debugPort") - val process = (if (headless) ::HeadlessJavaCommand else ::TerminalWindowJavaCommand)(jarName, dir, debugPort, monitoringPort, javaArgs, jvmArgs).start() - if (os == OS.MACOS) Thread.sleep(1000) - return process - } -} - -private object NodeJarType : JarType("corda.jar") { - override fun acceptNodeConf(nodeConf: File) = true -} - -private object WebJarType : JarType("corda-webserver.jar") { - // TODO: Add a webserver.conf, or use TypeSafe config instead of this hack - override fun acceptNodeConf(nodeConf: File) = Files.lines(nodeConf.toPath()).anyMatch { "webAddress" in it } -} - -private abstract class JavaCommand( - jarName: String, - internal val dir: File, - debugPort: Int?, - monitoringPort: Int?, - internal val nodeName: String, - init: MutableList.() -> Unit, args: List, - jvmArgs: List -) { - private val jolokiaJar by lazy { - File("$dir/drivers").listFiles { _, filename -> - filename.matches("jolokia-jvm-.*-agent\\.jar$".toRegex()) - }.first().name - } - - internal val command: List = mutableListOf().apply { - add(getJavaPath()) - addAll(jvmArgs) - add("-Dname=$nodeName") - val jvmArgs: MutableList = mutableListOf() - null != debugPort && jvmArgs.add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$debugPort") - null != monitoringPort && jvmArgs.add("-javaagent:drivers/$jolokiaJar=port=$monitoringPort") - if (jvmArgs.isNotEmpty()) { - add("-Dcapsule.jvm.args=${jvmArgs.joinToString(separator = " ")}") - } - add("-jar") - add(jarName) - init() - addAll(args) - } - - internal abstract fun processBuilder(): ProcessBuilder - internal fun start() = processBuilder().directory(dir).start() - internal abstract fun getJavaPath(): String -} - -private class HeadlessJavaCommand(jarName: String, dir: File, debugPort: Int?, monitoringPort: Int?, args: List, jvmArgs: List) - : JavaCommand(jarName, dir, debugPort, monitoringPort, dir.name, { add("--no-local-shell") }, args, jvmArgs) { - override fun processBuilder() = ProcessBuilder(command).redirectError(File("error.$nodeName.log")).inheritIO() - override fun getJavaPath() = File(File(System.getProperty("java.home"), "bin"), "java").path -} - -private class TerminalWindowJavaCommand(jarName: String, dir: File, debugPort: Int?, monitoringPort: Int?, args: List, jvmArgs: List) - : JavaCommand(jarName, dir, debugPort, monitoringPort, "${dir.name}-$jarName", {}, args, jvmArgs) { - override fun processBuilder() = ProcessBuilder(when (os) { - OS.MACOS -> { - listOf("osascript", "-e", """tell app "Terminal" - activate - delay 0.5 - tell app "System Events" to tell process "Terminal" to keystroke "t" using command down - delay 0.5 - do script "bash -c 'cd \"$dir\" ; \"${command.joinToString("""\" \"""")}\" && exit'" in selected tab of the front window -end tell""") - } - OS.WINDOWS -> { - listOf("cmd", "/C", "start ${command.joinToString(" ") { windowsSpaceEscape(it) }}") - } - OS.LINUX -> { - // Start shell to keep window open unless java terminated normally or due to SIGTERM: - val command = "${unixCommand()}; [ $? -eq 0 -o $? -eq 143 ] || sh" - if (isTmux()) { - listOf("tmux", "new-window", "-n", nodeName, command) - } else { - listOf("xterm", "-T", nodeName, "-e", command) - } - } - }) - - private fun unixCommand() = command.map(::quotedFormOf).joinToString(" ") - override fun getJavaPath(): String = File(File(System.getProperty("java.home"), "bin"), "java").path - - // Replace below is to fix an issue with spaces in paths on Windows. - // Quoting the entire path does not work, only the space or directory within the path. - private fun windowsSpaceEscape(s:String) = s.replace(" ", "\" \"") -} - -private fun quotedFormOf(text: String) = "'${text.replace("'", "'\\''")}'" // Suitable for UNIX shells. -private fun isTmux() = System.getenv("TMUX")?.isNotEmpty() ?: false diff --git a/gradle-plugins/publish-utils/README.rst b/gradle-plugins/publish-utils/README.rst deleted file mode 100644 index d1657ee5fe..0000000000 --- a/gradle-plugins/publish-utils/README.rst +++ /dev/null @@ -1,92 +0,0 @@ -Publish Utils -============= - -Publishing utilities adds a couple of tasks to any project it is applied to that hide some boilerplate that would -otherwise be placed in the Cordapp template's build.gradle. - -There are two tasks exposed: `sourceJar` and `javadocJar` and both return a `FileCollection`. - -It is used within the `publishing` block of a build.gradle as such; - -.. code-block:: text - - // This will publish the sources, javadoc, and Java components to Maven. - // See the `maven-publish` plugin for more info: https://docs.gradle.org/current/userguide/publishing_maven.html - publishing { - publications { - jarAndSources(MavenPublication) { - from components.java - // The two lines below are the tasks added by this plugin. - artifact sourceJar - artifact javadocJar - } - } - } - -Bintray Publishing ------------------- - -For large multibuild projects it can be inconvenient to store the entire configuration for bintray and maven central -per project (with a bintray and publishing block with extended POM information). Publish utils can bring the number of -configuration blocks down to one in the ideal scenario. - -To use this plugin you must first apply it to both the root project and any project that will be published with - -.. code-block:: text - - apply plugin: 'net.corda.plugins.publish-utils' - -Next you must setup the general bintray configuration you wish to use project wide, for example: - -.. code-block:: text - - bintrayConfig { - user = - key = - repo = 'example repo' - org = 'example organisation' - licenses = ['a license'] - vcsUrl = 'https://example.com' - projectUrl = 'https://example.com' - gpgSign = true // Whether to GPG sign - gpgPassphrase = // Only required if gpgSign is true and your key is passworded - publications = ['example'] // a list of publications (see below) - license { - name = 'example' - url = 'https://example.com' - distribution = 'repo' - } - developer { - id = 'a developer id' - name = 'a developer name' - email = 'example@example.com' - } - } - -.. note:: You can currently only have one license and developer in the maven POM sections - -**Publications** - -This plugin assumes, by default, that publications match the name of the project. This means, by default, you can -just list the names of the projects you wish to publish (e.g. to publish `test:myapp` you need `publications = ['myapp']`. -If a project requires a different name you can configure it *per project* with the project configuration block. - -The project configuration block has the following structure: - -.. code-block:: text - - publish { - disableDefaultJar = false // set to true to disable the default JAR being created (e.g. when creating a fat JAR) - name 'non-default-project-name' // Always put this last because it causes configuration to happen - } - -**Artifacts** - -To add additional artifacts to the project you can use the default gradle `artifacts` block with the `publish` -configuration. For example: - - artifacts { - publish buildFatJar { - // You can configure this as a regular maven publication - } - } diff --git a/gradle-plugins/publish-utils/build.gradle b/gradle-plugins/publish-utils/build.gradle deleted file mode 100644 index da9c659498..0000000000 --- a/gradle-plugins/publish-utils/build.gradle +++ /dev/null @@ -1,109 +0,0 @@ -apply plugin: 'groovy' -apply plugin: 'maven-publish' -apply plugin: 'com.jfrog.bintray' -apply plugin: 'com.jfrog.artifactory' - -// Used for bootstrapping project -buildscript { - Properties constants = new Properties() - file("../../constants.properties").withInputStream { constants.load(it) } - - ext { - gradle_plugins_version = constants.getProperty("gradlePluginsVersion") - artifactory_plugin_version = constants.getProperty('artifactoryPluginVersion') - } - - repositories { - jcenter() - } - - dependencies { - classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.4' - classpath "org.jfrog.buildinfo:build-info-extractor-gradle:$artifactory_plugin_version" - } -} - -version "$gradle_plugins_version" - -dependencies { - compile gradleApi() - compile localGroovy() -} - -repositories { - mavenCentral() -} - -task("sourceJar", type: Jar, dependsOn: classes) { - classifier = 'sources' - from sourceSets.main.allSource -} - -task("javadocJar", type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' - from javadoc.destinationDir -} - -bintray { - user = System.getenv('CORDA_BINTRAY_USER') - key = System.getenv('CORDA_BINTRAY_KEY') - publications = ['publishUtils'] - dryRun = false - pkg { - repo = 'corda' - name = 'publish-utils' - userOrg = 'r3' - licenses = ['Apache-2.0'] - - version { - gpg { - sign = true - passphrase = System.getenv('CORDA_BINTRAY_GPG_PASSPHRASE') - } - } - } -} - -publishing { - publications { - publishUtils(MavenPublication) { - from components.java - groupId 'net.corda.plugins' - artifactId 'publish-utils' - - artifact sourceJar - artifact javadocJar - - pom.withXml { - asNode().children().last() + { - resolveStrategy = Closure.DELEGATE_FIRST - name 'publish-utils' - description 'A small gradle plugin that adds a couple of convenience functions for publishing to Maven' - url 'https://github.com/corda/corda' - scm { - url 'https://github.com/corda/corda' - } - - licenses { - license { - name 'Apache-2.0' - url 'https://www.apache.org/licenses/LICENSE-2.0' - distribution 'repo' - } - } - - developers { - developer { - id 'R3' - name 'R3' - email 'dev@corda.net' - } - } - } - } - } - } -} - -// Aliasing the publishToMavenLocal for simplicity. -task(install, dependsOn: 'publishToMavenLocal') diff --git a/gradle-plugins/publish-utils/src/main/groovy/net/corda/plugins/ProjectPublishExtension.groovy b/gradle-plugins/publish-utils/src/main/groovy/net/corda/plugins/ProjectPublishExtension.groovy deleted file mode 100644 index edb543fa51..0000000000 --- a/gradle-plugins/publish-utils/src/main/groovy/net/corda/plugins/ProjectPublishExtension.groovy +++ /dev/null @@ -1,39 +0,0 @@ -package net.corda.plugins - -class ProjectPublishExtension { - private PublishTasks task - - void setPublishTask(PublishTasks task) { - this.task = task - } - - /** - * Use a different name from the current project name for publishing. - * Set this after all other settings that need to be configured - */ - void name(String name) { - task.setPublishName(name) - } - - /** - * Get the publishing name for this project. - */ - String name() { - return task.getPublishName() - } - - /** - * True when we do not want to publish default Java components - */ - Boolean disableDefaultJar = false - - /** - * True if publishing a WAR instead of a JAR. Forces disableDefaultJAR to "true" when true - */ - Boolean publishWar = false - - /** - * True if publishing sources to remote repositories - */ - Boolean publishSources = true -} \ No newline at end of file diff --git a/gradle-plugins/publish-utils/src/main/groovy/net/corda/plugins/PublishTasks.groovy b/gradle-plugins/publish-utils/src/main/groovy/net/corda/plugins/PublishTasks.groovy deleted file mode 100644 index 7112ee8117..0000000000 --- a/gradle-plugins/publish-utils/src/main/groovy/net/corda/plugins/PublishTasks.groovy +++ /dev/null @@ -1,161 +0,0 @@ -package net.corda.plugins - -import org.gradle.api.* -import org.gradle.api.tasks.bundling.Jar -import org.gradle.api.tasks.javadoc.Javadoc -import org.gradle.api.Project -import org.gradle.api.publish.maven.MavenPublication -import org.gradle.api.publish.maven.MavenPom -import net.corda.plugins.bintray.* - -/** - * A utility plugin that when applied will automatically create source and javadoc publishing tasks - * To apply this plugin you must also add 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.4' to your - * buildscript's classpath dependencies. - * - * To use this plugin you can add a new configuration block (extension) to your root build.gradle. See the fields - * in BintrayConfigExtension. - */ -class PublishTasks implements Plugin { - Project project - String publishName - ProjectPublishExtension publishConfig - - void apply(Project project) { - this.project = project - this.publishName = project.name - - createTasks() - createExtensions() - createConfigurations() - } - - void setPublishName(String publishName) { - project.logger.info("Changing publishing name from ${project.name} to ${publishName}") - this.publishName = publishName - checkAndConfigurePublishing() - } - - void checkAndConfigurePublishing() { - project.logger.info("Checking whether to publish $publishName") - def bintrayConfig = project.rootProject.extensions.findByType(BintrayConfigExtension.class) - if((bintrayConfig != null) && (bintrayConfig.publications) && (bintrayConfig.publications.findAll { it == publishName }.size() > 0)) { - configurePublishing(bintrayConfig) - } - } - - void configurePublishing(BintrayConfigExtension bintrayConfig) { - project.logger.info("Configuring bintray for ${publishName}") - configureMavenPublish(bintrayConfig) - configureBintray(bintrayConfig) - } - - void configureMavenPublish(BintrayConfigExtension bintrayConfig) { - project.apply([plugin: 'maven-publish']) - project.publishing.publications.create(publishName, MavenPublication) { - groupId project.group - artifactId publishName - - if (publishConfig.publishSources) { - artifact project.tasks.sourceJar - } - artifact project.tasks.javadocJar - - project.configurations.publish.artifacts.each { - project.logger.debug("Adding artifact: $it") - delegate.artifact it - } - - if (!publishConfig.disableDefaultJar && !publishConfig.publishWar) { - from project.components.java - } else if (publishConfig.publishWar) { - from project.components.web - } - - extendPomForMavenCentral(pom, bintrayConfig) - } - project.task("install", dependsOn: "publishToMavenLocal") - } - - // Maven central requires all of the below fields for this to be a valid POM - void extendPomForMavenCentral(MavenPom pom, BintrayConfigExtension config) { - pom.withXml { - asNode().children().last() + { - resolveStrategy = Closure.DELEGATE_FIRST - name publishName - description project.description - url config.projectUrl - scm { - url config.vcsUrl - } - - licenses { - license { - name config.license.name - url config.license.url - distribution config.license.url - } - } - - developers { - developer { - id config.developer.id - name config.developer.name - email config.developer.email - } - } - } - } - } - - void configureBintray(BintrayConfigExtension bintrayConfig) { - project.apply([plugin: 'com.jfrog.bintray']) - project.bintray { - user = bintrayConfig.user - key = bintrayConfig.key - publications = [ publishName ] - dryRun = bintrayConfig.dryRun ?: false - pkg { - repo = bintrayConfig.repo - name = publishName - userOrg = bintrayConfig.org - licenses = bintrayConfig.licenses - - version { - gpg { - sign = bintrayConfig.gpgSign ?: false - passphrase = bintrayConfig.gpgPassphrase - } - } - } - } - } - - void createTasks() { - if(project.hasProperty('classes')) { - project.task("sourceJar", type: Jar, dependsOn: project.classes) { - classifier = 'sources' - from project.sourceSets.main.allSource - } - } - - if(project.hasProperty('javadoc')) { - project.task("javadocJar", type: Jar, dependsOn: project.javadoc) { - classifier = 'javadoc' - from project.javadoc.destinationDir - } - } - } - - void createExtensions() { - if(project == project.rootProject) { - project.extensions.create("bintrayConfig", BintrayConfigExtension) - } - publishConfig = project.extensions.create("publish", ProjectPublishExtension) - publishConfig.setPublishTask(this) - } - - void createConfigurations() { - project.configurations.create("publish") - } -} diff --git a/gradle-plugins/publish-utils/src/main/groovy/net/corda/plugins/bintray/BintrayConfigExtension.groovy b/gradle-plugins/publish-utils/src/main/groovy/net/corda/plugins/bintray/BintrayConfigExtension.groovy deleted file mode 100644 index 1a1c4e49e5..0000000000 --- a/gradle-plugins/publish-utils/src/main/groovy/net/corda/plugins/bintray/BintrayConfigExtension.groovy +++ /dev/null @@ -1,70 +0,0 @@ -package net.corda.plugins.bintray - -import org.gradle.util.ConfigureUtil - -class BintrayConfigExtension { - /** - * Bintray username - */ - String user - /** - * Bintray access key - */ - String key - /** - * Bintray repository - */ - String repo - /** - * Bintray organisation - */ - String org - /** - * Licenses for packages uploaded by this configuration - */ - String[] licenses - /** - * Whether to sign packages uploaded by this configuration - */ - Boolean gpgSign - /** - * The passphrase for the key used to sign releases. - */ - String gpgPassphrase - /** - * VCS URL - */ - String vcsUrl - /** - * Project URL - */ - String projectUrl - /** - * The publications that will be uploaded as a part of this configuration. These must match both the name on - * bintray and the gradle module name. ie; it must be "some-package" as a gradle sub-module (root project not - * supported, this extension is to improve multi-build bintray uploads). The publication must also be called - * "some-package". Only one publication can be uploaded per module (a bintray plugin restriction(. - * If any of these conditions are not met your package will not be uploaded. - */ - String[] publications - /** - * Whether to test the publication without uploading to bintray. - */ - Boolean dryRun - /** - * The license this project will use (currently limited to one) - */ - License license = new License() - /** - * The developer of this project (currently limited to one) - */ - Developer developer = new Developer() - - void license(Closure closure) { - ConfigureUtil.configure(closure, license) - } - - void developer(Closure closure) { - ConfigureUtil.configure(closure, developer) - } -} \ No newline at end of file diff --git a/gradle-plugins/publish-utils/src/main/groovy/net/corda/plugins/bintray/Developer.groovy b/gradle-plugins/publish-utils/src/main/groovy/net/corda/plugins/bintray/Developer.groovy deleted file mode 100644 index 1d66f68c7d..0000000000 --- a/gradle-plugins/publish-utils/src/main/groovy/net/corda/plugins/bintray/Developer.groovy +++ /dev/null @@ -1,16 +0,0 @@ -package net.corda.plugins.bintray - -class Developer { - /** - * A unique identifier the developer (eg; organisation ID) - */ - String id - /** - * The full name of the developer - */ - String name - /** - * An email address for contacting the developer - */ - String email -} \ No newline at end of file diff --git a/gradle-plugins/publish-utils/src/main/groovy/net/corda/plugins/bintray/License.groovy b/gradle-plugins/publish-utils/src/main/groovy/net/corda/plugins/bintray/License.groovy deleted file mode 100644 index 1d06867bcf..0000000000 --- a/gradle-plugins/publish-utils/src/main/groovy/net/corda/plugins/bintray/License.groovy +++ /dev/null @@ -1,16 +0,0 @@ -package net.corda.plugins.bintray - -class License { - /** - * The name of license (eg; Apache 2.0) - */ - String name - /** - * URL to the full license file - */ - String url - /** - * The distribution level this license corresponds to (eg: repo) - */ - String distribution -} \ No newline at end of file diff --git a/gradle-plugins/publish-utils/src/main/resources/META-INF/gradle-plugins/net.corda.plugins.publish-utils.properties b/gradle-plugins/publish-utils/src/main/resources/META-INF/gradle-plugins/net.corda.plugins.publish-utils.properties deleted file mode 100644 index b680f7d301..0000000000 --- a/gradle-plugins/publish-utils/src/main/resources/META-INF/gradle-plugins/net.corda.plugins.publish-utils.properties +++ /dev/null @@ -1 +0,0 @@ -implementation-class=net.corda.plugins.PublishTasks diff --git a/gradle-plugins/quasar-utils/README.rst b/gradle-plugins/quasar-utils/README.rst deleted file mode 100644 index 481d8ec66b..0000000000 --- a/gradle-plugins/quasar-utils/README.rst +++ /dev/null @@ -1,4 +0,0 @@ -Quasar Utils -============ - -Quasar utilities adds several tasks and configuration that provide a default Quasar setup and removes some boilerplate. \ No newline at end of file diff --git a/gradle-plugins/quasar-utils/build.gradle b/gradle-plugins/quasar-utils/build.gradle deleted file mode 100644 index 8f9eca30f2..0000000000 --- a/gradle-plugins/quasar-utils/build.gradle +++ /dev/null @@ -1,19 +0,0 @@ -apply plugin: 'groovy' -apply plugin: 'maven-publish' -apply plugin: 'net.corda.plugins.publish-utils' -apply plugin: 'com.jfrog.artifactory' - -description 'A small gradle plugin for adding some basic Quasar tasks and configurations to reduce build.gradle bloat.' - -repositories { - mavenCentral() -} - -dependencies { - compile gradleApi() - compile localGroovy() -} - -publish { - name project.name -} diff --git a/gradle-plugins/quasar-utils/src/main/groovy/net/corda/plugins/QuasarPlugin.groovy b/gradle-plugins/quasar-utils/src/main/groovy/net/corda/plugins/QuasarPlugin.groovy deleted file mode 100644 index 6a4ffaf25a..0000000000 --- a/gradle-plugins/quasar-utils/src/main/groovy/net/corda/plugins/QuasarPlugin.groovy +++ /dev/null @@ -1,28 +0,0 @@ -package net.corda.plugins - -import org.gradle.api.Project -import org.gradle.api.Plugin -import org.gradle.api.tasks.testing.Test -import org.gradle.api.tasks.JavaExec - -/** - * QuasarPlugin creates a "quasar" configuration and adds quasar as a dependency. - */ -class QuasarPlugin implements Plugin { - void apply(Project project) { - project.configurations.create("quasar") -// To add a local .jar dependency: -// project.dependencies.add("quasar", project.files("${project.rootProject.projectDir}/lib/quasar.jar")) - project.dependencies.add("quasar", "co.paralleluniverse:quasar-core:${project.rootProject.ext.quasar_version}:jdk8@jar") - project.dependencies.add("runtime", project.configurations.getByName("quasar")) - - project.tasks.withType(Test) { - jvmArgs "-javaagent:${project.configurations.quasar.singleFile}" - jvmArgs "-Dco.paralleluniverse.fibers.verifyInstrumentation" - } - project.tasks.withType(JavaExec) { - jvmArgs "-javaagent:${project.configurations.quasar.singleFile}" - jvmArgs "-Dco.paralleluniverse.fibers.verifyInstrumentation" - } - } -} diff --git a/gradle-plugins/quasar-utils/src/main/resources/META-INF/gradle-plugins/net.corda.plugins.quasar-utils.properties b/gradle-plugins/quasar-utils/src/main/resources/META-INF/gradle-plugins/net.corda.plugins.quasar-utils.properties deleted file mode 100644 index fb7042bb42..0000000000 --- a/gradle-plugins/quasar-utils/src/main/resources/META-INF/gradle-plugins/net.corda.plugins.quasar-utils.properties +++ /dev/null @@ -1 +0,0 @@ -implementation-class=net.corda.plugins.QuasarPlugin diff --git a/gradle-plugins/settings.gradle b/gradle-plugins/settings.gradle deleted file mode 100644 index 995cd8c899..0000000000 --- a/gradle-plugins/settings.gradle +++ /dev/null @@ -1,7 +0,0 @@ -rootProject.name = 'corda-gradle-plugins' -include 'publish-utils' -include 'quasar-utils' -include 'cordformation' -include 'cordform-common' -include 'api-scanner' -include 'cordapp' \ No newline at end of file