Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CORE-17494: Add check to CPB creation to ensure that 2 CPKs don't share a name #596

Merged
merged 12 commits into from
Dec 6, 2023
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ public void apply(@NotNull Project project) {
cpbTask.getArchiveAppendix().convention(cpkTask.flatMap(Jar::getArchiveAppendix));
cpbTask.getArchiveVersion().convention(cpkTask.flatMap(Jar::getArchiveVersion));

cpbTask.doFirst(task -> cpbTask.checkForDuplicateCpkCordappNames());

cpbTask.doLast(task -> {
if (cordappExtension.getSigning().getEnabled().get()) {
sign(task, cordappExtension.getSigning().getOptions(), cpbTask.getArchiveFile().get().getAsFile());
Expand Down
26 changes: 26 additions & 0 deletions cordapp-cpk2/src/main/java/net/corda/plugins/cpb2/CpbTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.gradle.api.InvalidUserDataException;
import org.gradle.api.file.DuplicatesStrategy;
import org.gradle.api.file.FileCollection;
import org.gradle.api.file.FileTreeElement;
import org.gradle.api.tasks.AbstractCopyTask;
import org.gradle.api.tasks.bundling.Jar;
Expand All @@ -10,15 +11,18 @@
import org.jetbrains.annotations.NotNull;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarInputStream;

import static java.util.Collections.singleton;
import static net.corda.plugins.cpk2.CordappUtils.CORDAPP_TASK_GROUP;
import static net.corda.plugins.cpk2.CordappUtils.CORDA_CPK_TYPE;
import static net.corda.plugins.cpk2.CordappUtils.CPK_CORDAPP_NAME;
import static net.corda.plugins.cpk2.CordappUtils.CPK_FILE_EXTENSION;

@DisableCachingByDefault
Expand Down Expand Up @@ -78,4 +82,26 @@ private boolean isCPK(@NotNull FileTreeElement element) {
throw new InvalidUserDataException(e.getMessage(), e);
}
}

public void checkForDuplicateCpkCordappNames() {
Set<String> cpkCordappNames = new HashSet<>();
FileCollection files = getInputs().getFiles();
for (File file : files) {
Path path = file.toPath();
if (path.toString().endsWith(CPK_FILE_SUFFIX)) {
try (JarInputStream cpkStream = new JarInputStream(new BufferedInputStream(Files.newInputStream(path)))) {
String cpkCordappName = cpkStream.getManifest().getMainAttributes().getValue(CPK_CORDAPP_NAME);
if (cpkCordappName != null) {
if (cpkCordappNames.contains(cpkCordappName)) {
throw new InvalidUserDataException("Two CPKs may not share a cpkCordappName. Error in " + cpkCordappName);
} else {
cpkCordappNames.add(cpkCordappName);
}
}
} catch (IOException e) {
throw new InvalidUserDataException(e.getMessage(), e);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public final class CordappUtils {

// These tags are for the CPK file.
static final String CPK_PLATFORM_VERSION = "Corda-CPK-Built-Platform-Version";
static final String CPK_CORDAPP_NAME = "Corda-CPK-Cordapp-Name";
public static final String CPK_CORDAPP_NAME = "Corda-CPK-Cordapp-Name";
static final String CPK_CORDAPP_VERSION = "Corda-CPK-Cordapp-Version";
static final String CPK_CORDAPP_LICENCE = "Corda-CPK-Cordapp-Licence";
static final String CPK_CORDAPP_VENDOR = "Corda-CPK-Cordapp-Vendor";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package net.corda.plugins.cpb2

import net.corda.plugins.cpk2.GradleProject
import net.corda.plugins.cpk2.cordaApiVersion
import net.corda.plugins.cpk2.expectedCordappContractVersion
import org.gradle.testkit.runner.UnexpectedBuildFailure
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
import org.junit.jupiter.api.TestReporter
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.api.io.TempDir
import java.nio.file.Files
import java.nio.file.Path
import java.util.*

@TestInstance(PER_CLASS)
class CpbSharedName {
private companion object {
private const val platformCordappVersion = "2.3.4"
private const val cordappVersion = "1.2.1"
}

private lateinit var externalProject: GradleProject

@Test
fun `Assert 2 CPKs don't share a cordappName`(
@TempDir testDir: Path,
reporter: TestReporter
) {
val mavenRepoDir = Files.createDirectory(testDir.resolve("maven"))
val cpbProjectDir = Files.createDirectory(testDir.resolve("cpb"))
val e = assertThrows<UnexpectedBuildFailure> {
GradleProject(cpbProjectDir, reporter)
.withTestName("cpb-shared-name")
.withSubResource("project-dependency/build.gradle")
.withSubResource("second-project-dependency/build.gradle")
.build(
"-Pmaven_repository_dir=$mavenRepoDir",
"-Pplatform_cordapp_version=$platformCordappVersion",
"-Pcordapp_version=$cordappVersion",
"-Pcordapp_contract_version=$expectedCordappContractVersion"
)
}

val expectedMessage = "Two CPKs may not share a cpkCordappName."
assert(e.message!!.contains(expectedMessage)) {
"Error message does not match expected value. Error message should contain \"$expectedMessage\""
}
}
}
63 changes: 63 additions & 0 deletions cordapp-cpk2/src/test/resources/cpb-shared-name/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
plugins {
id 'net.corda.plugins.cordapp-cpb2'
id 'org.jetbrains.kotlin.jvm'
}

apply from: 'javaTarget.gradle'
apply from: 'kotlin.gradle'

allprojects {
group = 'com.example'
version = cordapp_version

repositories {
maven {
name = 'test-repository'
url = maven_repository_dir
}
}
apply from: "$rootDir/repositories.gradle"
}

cordapp {
targetPlatformVersion = platform_version.toInteger()

contract {
name = 'CorDapp CPB test'
versionId = cordapp_contract_version.toInteger()
licence = 'Test-Licence'
vendor = 'R3'
}
}

configurations {
cpks {
canBeConsumed = false
}
}

dependencies {
cordapp project('project-dependency')
cordapp project('second-project-dependency')

cpks project(path: 'project-dependency', configuration: 'cordaCPK')
cpks project(path: 'second-project-dependency', configuration: 'cordaCPK')
}


def cpkDir = layout.buildDirectory.dir('cpks')
def copyCPKs = tasks.register('copyCPKs', Copy) {
from configurations.cpks
into cpkDir
}

artifacts {
archives(cpkDir) {
builtBy copyCPKs
}
}

cpb {
archiveBaseName = "customName"
archiveVersion = "customVersion"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
plugins {
id 'net.corda.plugins.cordapp-cpk2'
id 'org.jetbrains.kotlin.jvm'
}

apply from: '../javaTarget.gradle'
apply from: '../kotlin.gradle'

cordapp {
targetPlatformVersion = platform_version.toInteger()

contract {
name = 'Project CorDapp'
versionId = cordapp_contract_version.toInteger()
licence = 'Test-Licence'
vendor = 'R3'
cpkCordappName = 'com.example.cordapp-cpb.duplicate'
}
}

tasks.named('jar', Jar) {
archiveBaseName = 'project-cordapp'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
plugins {
id 'net.corda.plugins.cordapp-cpk2'
id 'org.jetbrains.kotlin.jvm'
}

apply from: '../javaTarget.gradle'
apply from: '../kotlin.gradle'

cordapp {
targetPlatformVersion = platform_version.toInteger()

contract {
name = 'Project CorDapp'
versionId = cordapp_contract_version.toInteger()
licence = 'Test-Licence'
vendor = 'R3'
cpkCordappName = 'com.example.cordapp-cpb.duplicate'
}
}

tasks.named('jar', Jar) {
archiveBaseName = 'second-project-cordapp'
}
10 changes: 10 additions & 0 deletions cordapp-cpk2/src/test/resources/cpb-shared-name/settings.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
pluginManagement {
plugins {
id 'org.jetbrains.kotlin.jvm' version kotlin_version
}
}

rootProject.name = 'cpb-shared-name'

include 'project-dependency'
include 'second-project-dependency'
Loading