diff --git a/client/rpc/src/smoke-test/java/net/corda/java/rpc/StandaloneCordaRPCJavaClientTest.java b/client/rpc/src/smoke-test/java/net/corda/java/rpc/StandaloneCordaRPCJavaClientTest.java index 70ae26e1b6..31daccc9c2 100644 --- a/client/rpc/src/smoke-test/java/net/corda/java/rpc/StandaloneCordaRPCJavaClientTest.java +++ b/client/rpc/src/smoke-test/java/net/corda/java/rpc/StandaloneCordaRPCJavaClientTest.java @@ -74,9 +74,9 @@ public class StandaloneCordaRPCJavaClientTest { } private void copyFinanceCordapp() { - Path pluginsDir = (factory.baseDirectory(notaryConfig).resolve("plugins")); + Path cordappsDir = (factory.baseDirectory(notaryConfig).resolve("cordapps")); try { - Files.createDirectories(pluginsDir); + Files.createDirectories(cordappsDir); } catch (IOException ex) { fail("Failed to create directories"); } @@ -84,7 +84,7 @@ public class StandaloneCordaRPCJavaClientTest { paths.forEach(file -> { if (file.toString().contains("corda-finance")) { try { - Files.copy(file, pluginsDir.resolve(file.getFileName())); + Files.copy(file, cordappsDir.resolve(file.getFileName())); } catch (IOException ex) { fail("Failed to copy finance jar"); } diff --git a/client/rpc/src/smoke-test/kotlin/net/corda/kotlin/rpc/StandaloneCordaRPClientTest.kt b/client/rpc/src/smoke-test/kotlin/net/corda/kotlin/rpc/StandaloneCordaRPClientTest.kt index 1d487f762b..d6d305f542 100644 --- a/client/rpc/src/smoke-test/kotlin/net/corda/kotlin/rpc/StandaloneCordaRPClientTest.kt +++ b/client/rpc/src/smoke-test/kotlin/net/corda/kotlin/rpc/StandaloneCordaRPClientTest.kt @@ -89,12 +89,12 @@ class StandaloneCordaRPClientTest { } private fun copyFinanceCordapp() { - val pluginsDir = (factory.baseDirectory(notaryConfig) / "plugins").createDirectories() + val cordappsDir = (factory.baseDirectory(notaryConfig) / "cordapps").createDirectories() // Find the finance jar file for the smoke tests of this module val financeJar = Paths.get("build", "resources", "smokeTest").list { it.filter { "corda-finance" in it.toString() }.toList().single() } - financeJar.copyToDirectory(pluginsDir) + financeJar.copyToDirectory(cordappsDir) } @Test diff --git a/constants.properties b/constants.properties index deebebf5d5..48f942803c 100644 --- a/constants.properties +++ b/constants.properties @@ -1,4 +1,4 @@ -gradlePluginsVersion=2.0.3 +gradlePluginsVersion=2.0.4 kotlinVersion=1.1.50 guavaVersion=21.0 bouncycastleVersion=1.57 diff --git a/docs/source/azure-vm.rst b/docs/source/azure-vm.rst index bc5ae24fa4..7f94f0fdcb 100644 --- a/docs/source/azure-vm.rst +++ b/docs/source/azure-vm.rst @@ -97,7 +97,7 @@ Loading the Yo! CordDapp on your Corda nodes lets you send simple Yo! messages t * **Loading the Yo! CorDapp onto your nodes** -The nodes you will use to send and receive Yo messages require the Yo! CorDapp jar file to be saved to their plugins directory. +The nodes you will use to send and receive Yo messages require the Yo! CorDapp jar file to be saved to their cordapps directory. Connect to one of your Corda nodes (make sure this is not the Notary node) using an SSH client of your choice (e.g. Putty) and log into the virtual machine using the public IP address and your SSH key or username / password combination you defined in Step 1 of the Azure build process. Type the following command: @@ -105,14 +105,14 @@ For Corda nodes running release M10 .. sourcecode:: shell - cd /opt/corda/plugins + cd /opt/corda/cordapps wget http://downloads.corda.net/cordapps/net/corda/yo/0.10.1/yo-0.10.1.jar For Corda nodes running release M11 .. sourcecode:: shell - cd /opt/corda/plugins + cd /opt/corda/cordapps wget http://downloads.corda.net/cordapps/net/corda/yo/0.11.0/yo-0.11.0.jar Now restart Corda and the Corda webserver using the following commands or restart your Corda VM from the Azure portal: diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index 0ff4e44495..e3be980710 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -11,6 +11,8 @@ UNRELEASED * ``FlowLogic`` now exposes a series of function called ``receiveAll(...)`` allowing to join ``receive(...)`` instructions. +* Renamed "plugins" directory on nodes to "cordapps" + * The ``Cordformation`` gradle plugin has been split into ``cordformation`` and ``cordapp``. The former builds and deploys nodes for development and testing, the latter turns a project into a cordapp project that generates JARs in the standard CorDapp format. diff --git a/docs/source/cordapp-build-systems.rst b/docs/source/cordapp-build-systems.rst index 016d741bf2..e20065838f 100644 --- a/docs/source/cordapp-build-systems.rst +++ b/docs/source/cordapp-build-systems.rst @@ -78,11 +78,11 @@ For further information about managing dependencies, see Installing CorDapps ------------------- -At runtime, nodes will load any plugins present in their ``plugins`` folder. Therefore in order to install a cordapp to -a node the cordapp JAR must be added to the ``/plugins/`` folder, where ``node_dir`` is the folder in which the +At runtime, nodes will load any CorDapp JARs present in their ``cordapps`` folder. Therefore in order to install a CorDapp to +a node the CorDapp JAR must be added to the ``/cordapps/`` folder, where ``node_dir`` is the folder in which the node's JAR and configuration files are stored). -The ``deployNodes`` gradle task, if correctly configured, will automatically place your cordapp JAR as well as any +The ``deployNodes`` gradle task, if correctly configured, will automatically place your CorDapp JAR as well as any dependent cordapp JARs specified into the directory automatically. Example diff --git a/docs/source/demobench.rst b/docs/source/demobench.rst index 5382547301..374f12234a 100644 --- a/docs/source/demobench.rst +++ b/docs/source/demobench.rst @@ -37,13 +37,13 @@ Profiles notary/ node.conf - plugins/ + cordapps/ banka/ node.conf - plugins/ + cordapps/ bankb/ node.conf - plugins/ + cordapps/ example-cordapp.jar ... @@ -133,7 +133,7 @@ current working directory of the JVM): corda-webserver.jar explorer/ node-explorer.jar - plugins/ + cordapps/ bank-of-corda.jar .. diff --git a/docs/source/deploying-a-node.rst b/docs/source/deploying-a-node.rst index 4125947fd8..74f8bdac65 100644 --- a/docs/source/deploying-a-node.rst +++ b/docs/source/deploying-a-node.rst @@ -84,7 +84,7 @@ run all the nodes at once. Each node in the ``nodes`` folder has the following s . nodeName ├── corda.jar // The Corda runtime ├── node.conf // The node's configuration - ├── plugins // Any installed CorDapps + ├── cordapps // Any installed CorDapps └── additional-node-infos // Directory containing all the addresses and certificates of the other nodes. .. note:: During the build process each node generates a NodeInfo file which is written in its own root directory, diff --git a/docs/source/hello-world-introduction.rst b/docs/source/hello-world-introduction.rst index 9760d91a6d..25bb4e189d 100644 --- a/docs/source/hello-world-introduction.rst +++ b/docs/source/hello-world-introduction.rst @@ -5,7 +5,7 @@ By this point, :doc:`your dev environment should be set up `, yo :doc:`your first CorDapp `, and you're familiar with Corda's :doc:`key concepts `. What comes next? -If you're a developer, the next step is to write your own CorDapp. Each CorDapp takes the form of a plugin that is +If you're a developer, the next step is to write your own CorDapp. Each CorDapp takes the form of a JAR that is installed on one or more Corda nodes, and gives them the ability to conduct some new process - anything from issuing a debt instrument to making a restaurant booking. diff --git a/docs/source/hello-world-running.rst b/docs/source/hello-world-running.rst index b5bf916e18..72c573b789 100644 --- a/docs/source/hello-world-running.rst +++ b/docs/source/hello-world-running.rst @@ -82,7 +82,7 @@ the three node folders. Each node folder has the following structure: |____dependencies |____node.conf // The node's configuration file |____additional-node-infos/ // Directory containing all the other nodes' addresses and identities - |____plugins + |____cordapps |____java/kotlin-source-0.1.jar // Our IOU CorDapp Let's start the nodes by running the following commands from the root of the project: diff --git a/docs/source/key-concepts-contract-constraints.rst b/docs/source/key-concepts-contract-constraints.rst index 39840924fd..edd4c6694d 100644 --- a/docs/source/key-concepts-contract-constraints.rst +++ b/docs/source/key-concepts-contract-constraints.rst @@ -146,4 +146,4 @@ The driver takes a parameter called ``extraCordappPackagesToScan`` which is a li Full Nodes ********** -When testing against full nodes simply place your CorDapp into the plugins directory of the node. +When testing against full nodes simply place your CorDapp into the cordapps directory of the node. diff --git a/docs/source/key-concepts-node.rst b/docs/source/key-concepts-node.rst index 537d0aebc4..624f5308af 100644 --- a/docs/source/key-concepts-node.rst +++ b/docs/source/key-concepts-node.rst @@ -36,7 +36,7 @@ The core elements of the architecture are: * A network interface for interacting with other nodes * An RPC interface for interacting with the node's owner * A service hub for allowing the node's flows to call upon the node's other services -* A plugin registry for extending the node by installing CorDapps +* A cordapp interface and provider for extending the node by installing CorDapps Persistence layer ----------------- @@ -68,11 +68,11 @@ updates. The key services provided are: * Information about the node itself * The current time, as tracked by the node -The plugin registry -------------------- -The plugin registry is where new CorDapps are installed to extend the behavior of the node. +The CorDapp provider +-------------------- +The CorDapp provider is where new CorDapps are installed to extend the behavior of the node. -The node also has several plugins installed by default to handle common tasks such as: +The node also has several CorDapps installed by default to handle common tasks such as: * Retrieving transactions and attachments from counterparties * Upgrading contracts diff --git a/docs/source/node-services.rst b/docs/source/node-services.rst index 3ab92255b6..d62edd2548 100644 --- a/docs/source/node-services.rst +++ b/docs/source/node-services.rst @@ -320,7 +320,7 @@ does this by tracking update notifications from the ``TransactionStorage`` service and processing relevant updates to delete consumed states and insert new states. The resulting update is then persisted to the database. The ``VaultService`` then exposes query and -event notification APIs to flows and CorDapp plugins to allow them +event notification APIs to flows and CorDapp services to allow them to respond to updates, or query for states meeting various conditions to begin the formation of new transactions consuming them. The equivalent services are also forwarded to RPC clients, so that they may show diff --git a/docs/source/running-a-node.rst b/docs/source/running-a-node.rst index b87378bd29..4373e93a3e 100644 --- a/docs/source/running-a-node.rst +++ b/docs/source/running-a-node.rst @@ -10,7 +10,7 @@ already installed. You run each node by navigating to ```` in a termin java -jar corda.jar -.. warning:: If your working directory is not ```` your plugins and configuration will not be used. +.. warning:: If your working directory is not ```` your cordapps and configuration will not be used. The configuration file and workspace paths can be overridden on the command line. For example: diff --git a/docs/source/tutorial-cordapp.rst b/docs/source/tutorial-cordapp.rst index c61e20f4be..7073a67af3 100644 --- a/docs/source/tutorial-cordapp.rst +++ b/docs/source/tutorial-cordapp.rst @@ -210,9 +210,9 @@ Building the example CorDapp . nodeName ├── corda.jar ├── node.conf - └── plugins + └── cordapps - ``corda.jar`` is the Corda runtime, ``plugins`` contains our node's CorDapps, and the node's configuration is + ``corda.jar`` is the Corda runtime, ``cordapps`` contains our node's CorDapps, and the node's configuration is given by ``node.conf`` Running the example CorDapp diff --git a/gradle-plugins/cordformation/src/main/groovy/net/corda/plugins/Node.groovy b/gradle-plugins/cordformation/src/main/groovy/net/corda/plugins/Node.groovy index f6963541d4..8f6dcea295 100644 --- a/gradle-plugins/cordformation/src/main/groovy/net/corda/plugins/Node.groovy +++ b/gradle-plugins/cordformation/src/main/groovy/net/corda/plugins/Node.groovy @@ -17,7 +17,7 @@ class Node extends CordformNode { static final String WEBJAR_NAME = 'corda-webserver.jar' /** - * Set the list of CorDapps to install to the plugins directory. Each cordapp is a fully qualified Maven + * Set the list of CorDapps to install to the cordapps 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. @@ -104,7 +104,7 @@ class Node extends CordformNode { if (config.hasPath("webAddress")) { installWebserverJar() } - installBuiltPlugin() + installBuiltCordapp() installCordapps() installConfig() appendOptionalConfig() @@ -157,23 +157,23 @@ class Node extends CordformNode { /** * Installs this project's cordapp to this directory. */ - private void installBuiltPlugin() { - def pluginsDir = new File(nodeDir, "plugins") + private void installBuiltCordapp() { + def cordappsDir = new File(nodeDir, "cordapps") project.copy { from project.jar - into pluginsDir + into cordappsDir } } /** - * Installs other cordapps to this node's plugins directory. + * Installs other cordapps to this node's cordapps directory. */ private void installCordapps() { - def pluginsDir = new File(nodeDir, "plugins") + def cordappsDir = new File(nodeDir, "cordapps") def cordapps = getCordappList() project.copy { from cordapps - into pluginsDir + into cordappsDir } } diff --git a/node/src/integration-test/kotlin/net/corda/node/services/AttachmentLoadingTests.kt b/node/src/integration-test/kotlin/net/corda/node/services/AttachmentLoadingTests.kt index 3c15d0aec5..3ea5527202 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/AttachmentLoadingTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/AttachmentLoadingTests.kt @@ -69,7 +69,7 @@ class AttachmentLoadingTests : TestDependencyInjectionBase() { private fun DriverDSLExposedInterface.installIsolatedCordappTo(nodeName: CordaX500Name) { // Copy the app jar to the first node. The second won't have it. - val path = (baseDirectory(nodeName.toString()) / "plugins").createDirectories() / "isolated.jar" + val path = (baseDirectory(nodeName.toString()) / "cordapps").createDirectories() / "isolated.jar" logger.info("Installing isolated jar to $path") isolatedJAR.openStream().buffered().use { input -> Files.newOutputStream(path).buffered().use { output -> diff --git a/node/src/main/java/CordaCaplet.java b/node/src/main/java/CordaCaplet.java index 83e76ae2ba..fa39580fa7 100644 --- a/node/src/main/java/CordaCaplet.java +++ b/node/src/main/java/CordaCaplet.java @@ -24,26 +24,27 @@ public class CordaCaplet extends Capsule { // defined as public static final fields on the Capsule class, therefore referential equality is safe. if (ATTR_APP_CLASS_PATH == attr) { T cp = super.attribute(attr); - return (T) augmentClasspath((List) cp, "plugins"); + + (new File("cordapps")).mkdir(); + augmentClasspath((List) cp, "cordapps"); + augmentClasspath((List) cp, "plugins"); + return cp; } return super.attribute(attr); } // TODO: Make directory configurable via the capsule manifest. // TODO: Add working directory variable to capsules string replacement variables. - private List augmentClasspath(List classpath, String dirName) { + private void augmentClasspath(List classpath, String dirName) { File dir = new File(dirName); - if (!dir.exists()) { - dir.mkdir(); - } - - File[] files = dir.listFiles(); - for (File file : files) { - if (file.isFile() && isJAR(file)) { - classpath.add(file.toPath().toAbsolutePath()); + if (dir.exists()) { + File[] files = dir.listFiles(); + for (File file : files) { + if (file.isFile() && isJAR(file)) { + classpath.add(file.toPath().toAbsolutePath()); + } } } - return classpath; } @Override diff --git a/node/src/main/kotlin/net/corda/node/internal/cordapp/CordappLoader.kt b/node/src/main/kotlin/net/corda/node/internal/cordapp/CordappLoader.kt index 7cdba9ca71..c481bfcc36 100644 --- a/node/src/main/kotlin/net/corda/node/internal/cordapp/CordappLoader.kt +++ b/node/src/main/kotlin/net/corda/node/internal/cordapp/CordappLoader.kt @@ -54,22 +54,30 @@ class CordappLoader private constructor(private val cordappJarPaths: List) companion object { private val logger = loggerFor() + /** + * Default cordapp dir name + */ + val CORDAPPS_DIR_NAME = "cordapps" + /** * Creates a default CordappLoader intended to be used in non-dev or non-test environments. * - * @param baseDir The directory that this node is running in. Will use this to resolve the plugins directory + * @param baseDir The directory that this node is running in. Will use this to resolve the cordapps directory * for classpath scanning. */ - fun createDefault(baseDir: Path) = CordappLoader(getCordappsInDirectory(getPluginsPath(baseDir))) + fun createDefault(baseDir: Path) = CordappLoader(getCordappsInDirectory(getCordappsPath(baseDir))) /** * Create a dev mode CordappLoader for test environments that creates and loads cordapps from the classpath - * and plugins directory. This is intended mostly for use by the driver. + * and cordapps directory. This is intended mostly for use by the driver. + * + * @param baseDir See [createDefault.baseDir] + * @param testPackages See [createWithTestPackages.testPackages] */ @VisibleForTesting fun createDefaultWithTestPackages(configuration: NodeConfiguration, testPackages: List): CordappLoader { check(configuration.devMode) { "Package scanning can only occur in dev mode" } - return CordappLoader(getCordappsInDirectory(getPluginsPath(configuration.baseDirectory)) + testPackages.flatMap(this::createScanPackage)) + return CordappLoader(getCordappsInDirectory(getCordappsPath(configuration.baseDirectory)) + testPackages.flatMap(this::createScanPackage)) } /** @@ -91,7 +99,7 @@ class CordappLoader private constructor(private val cordappJarPaths: List) @VisibleForTesting fun createDevMode(scanJars: List) = CordappLoader(scanJars) - private fun getPluginsPath(baseDir: Path): Path = baseDir / "plugins" + private fun getCordappsPath(baseDir: Path): Path = baseDir / CORDAPPS_DIR_NAME private fun createScanPackage(scanPackage: String): List { val resource = scanPackage.replace('.', '/') @@ -135,11 +143,11 @@ class CordappLoader private constructor(private val cordappJarPaths: List) return generatedCordapps[path]!! } - private fun getCordappsInDirectory(pluginsDir: Path): List { - return if (!pluginsDir.exists()) { + private fun getCordappsInDirectory(cordappsDir: Path): List { + return if (!cordappsDir.exists()) { emptyList() } else { - pluginsDir.list { + cordappsDir.list { it.filter { it.isRegularFile() && it.toString().endsWith(".jar") }.map { it.toUri().toURL() }.toList() } } diff --git a/node/src/smoke-test/kotlin/net/corda/node/CordappSmokeTest.kt b/node/src/smoke-test/kotlin/net/corda/node/CordappSmokeTest.kt index dbb62d3bac..82c48bf82e 100644 --- a/node/src/smoke-test/kotlin/net/corda/node/CordappSmokeTest.kt +++ b/node/src/smoke-test/kotlin/net/corda/node/CordappSmokeTest.kt @@ -11,6 +11,7 @@ import net.corda.core.internal.list import net.corda.core.messaging.startFlow import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.unwrap +import net.corda.node.internal.cordapp.CordappLoader import net.corda.nodeapi.User import net.corda.smoketesting.NodeConfig import net.corda.smoketesting.NodeProcess @@ -39,12 +40,12 @@ class CordappSmokeTest { @Test fun `FlowContent appName returns the filename of the CorDapp jar`() { - val pluginsDir = (factory.baseDirectory(aliceConfig) / "plugins").createDirectories() + val cordappsDir = (factory.baseDirectory(aliceConfig) / CordappLoader.CORDAPPS_DIR_NAME).createDirectories() // Find the jar file for the smoke tests of this module val selfCordapp = Paths.get("build", "libs").list { it.filter { "-smokeTests" in it.toString() }.toList().single() } - selfCordapp.copyToDirectory(pluginsDir) + selfCordapp.copyToDirectory(cordappsDir) factory.create(aliceConfig).use { alice -> alice.connect().use { connectionToAlice -> @@ -59,8 +60,8 @@ class CordappSmokeTest { } @Test - fun `empty plugins directory`() { - (factory.baseDirectory(aliceConfig) / "plugins").createDirectories() + fun `empty cordapps directory`() { + (factory.baseDirectory(aliceConfig) / CordappLoader.CORDAPPS_DIR_NAME).createDirectories() factory.create(aliceConfig).close() } diff --git a/tools/demobench/build.gradle b/tools/demobench/build.gradle index c2d1142cc7..c3626bd72f 100644 --- a/tools/demobench/build.gradle +++ b/tools/demobench/build.gradle @@ -122,12 +122,12 @@ distributions { } from(project(':finance').tasks.jar) { rename 'corda-finance-(.*)', 'corda-finance.jar' - into 'plugins' + into 'cordapps' fileMode = 0444 } from(project(':samples:bank-of-corda-demo').jar) { rename 'bank-of-corda-demo-(.*)', 'bank-of-corda.jar' - into 'plugins' + into 'cordapps' fileMode = 0444 } } @@ -201,7 +201,7 @@ task javapackage(dependsOn: distZip) { fileset(dir: dist_source, type: 'data') { include(name: 'corda/*.jar') - include(name: 'plugins/*.jar') + include(name: 'cordapps/*.jar') include(name: 'explorer/*.jar') } diff --git a/tools/demobench/src/main/kotlin/net/corda/demobench/explorer/Explorer.kt b/tools/demobench/src/main/kotlin/net/corda/demobench/explorer/Explorer.kt index 165388b2b0..286ad1e4c6 100644 --- a/tools/demobench/src/main/kotlin/net/corda/demobench/explorer/Explorer.kt +++ b/tools/demobench/src/main/kotlin/net/corda/demobench/explorer/Explorer.kt @@ -5,6 +5,7 @@ import net.corda.core.internal.div import net.corda.core.internal.list import net.corda.core.utilities.loggerFor import net.corda.demobench.model.JVMConfig +import net.corda.demobench.model.NodeConfig import net.corda.demobench.model.NodeConfigWrapper import net.corda.demobench.readErrorLines import tornadofx.* @@ -82,11 +83,11 @@ class Explorer internal constructor(private val explorerController: ExplorerCont // Note: does not copy dependencies because we should soon be making all apps fat jars and dependencies implicit. // // TODO: Remove this code when serialisation has been upgraded. - val pluginsDir = config.explorerDir / "plugins" - pluginsDir.createDirectories() - config.pluginDir.list { + val cordappsDir = config.explorerDir / NodeConfig.cordappDirName + cordappsDir.createDirectories() + config.cordappsDir.list { it.forEachOrdered { path -> - val destPath = pluginsDir / path.fileName.toString() + val destPath = cordappsDir / path.fileName.toString() try { // Try making a symlink to make things faster and use less disk space. Files.createSymbolicLink(destPath, path) diff --git a/tools/demobench/src/main/kotlin/net/corda/demobench/model/HasPlugins.kt b/tools/demobench/src/main/kotlin/net/corda/demobench/model/HasCordapps.kt similarity index 56% rename from tools/demobench/src/main/kotlin/net/corda/demobench/model/HasPlugins.kt rename to tools/demobench/src/main/kotlin/net/corda/demobench/model/HasCordapps.kt index 52a388b7a7..de0a2607b5 100644 --- a/tools/demobench/src/main/kotlin/net/corda/demobench/model/HasPlugins.kt +++ b/tools/demobench/src/main/kotlin/net/corda/demobench/model/HasCordapps.kt @@ -2,6 +2,6 @@ package net.corda.demobench.model import java.nio.file.Path -interface HasPlugins { - val pluginDir: Path +interface HasCordapps { + val cordappsDir: Path } diff --git a/tools/demobench/src/main/kotlin/net/corda/demobench/model/InstallFactory.kt b/tools/demobench/src/main/kotlin/net/corda/demobench/model/InstallFactory.kt index f34ebfef6d..d2dba4a687 100644 --- a/tools/demobench/src/main/kotlin/net/corda/demobench/model/InstallFactory.kt +++ b/tools/demobench/src/main/kotlin/net/corda/demobench/model/InstallFactory.kt @@ -37,9 +37,9 @@ class InstallFactory : Controller() { * Wraps the configuration information for a Node * which isn't ready to be instantiated yet. */ -class InstallConfig internal constructor(val baseDir: Path, private val config: NodeConfigWrapper) : HasPlugins { +class InstallConfig internal constructor(val baseDir: Path, private val config: NodeConfigWrapper) : HasCordapps { val key = config.key - override val pluginDir: Path = baseDir / "plugins" + override val cordappsDir: Path = baseDir / "cordapps" fun deleteBaseDir(): Boolean = baseDir.toFile().deleteRecursively() fun installTo(installDir: Path) = config.copy(baseDir = installDir) diff --git a/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeConfig.kt b/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeConfig.kt index e536b3bfb4..504fdfab79 100644 --- a/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeConfig.kt +++ b/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeConfig.kt @@ -31,6 +31,7 @@ data class NodeConfig( companion object { val renderOptions: ConfigRenderOptions = ConfigRenderOptions.defaults().setOriginComments(false) val defaultUser = user("guest") + val cordappDirName = "cordapps" } @Suppress("unused") @@ -56,18 +57,18 @@ data class NotaryService(val validating: Boolean) : ExtraService { } // TODO Think of a better name -data class NodeConfigWrapper(val baseDir: Path, val nodeConfig: NodeConfig) : HasPlugins { +data class NodeConfigWrapper(val baseDir: Path, val nodeConfig: NodeConfig) : HasCordapps { val key: String = nodeConfig.myLegalName.organisation.toKey() val nodeDir: Path = baseDir / key val explorerDir: Path = baseDir / "$key-explorer" - override val pluginDir: Path = nodeDir / "plugins" + override val cordappsDir: Path = nodeDir / NodeConfig.cordappDirName var state: NodeState = NodeState.STARTING fun install(cordapps: Collection) { if (cordapps.isEmpty()) return - pluginDir.createDirectories() + cordappsDir.createDirectories() for (cordapp in cordapps) { - cordapp.copyToDirectory(pluginDir, StandardCopyOption.REPLACE_EXISTING) + cordapp.copyToDirectory(cordappsDir, StandardCopyOption.REPLACE_EXISTING) } } } diff --git a/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeController.kt b/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeController.kt index 4e7b6a6cc7..e13f23d3bb 100644 --- a/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeController.kt +++ b/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeController.kt @@ -7,7 +7,7 @@ import net.corda.core.internal.createDirectories import net.corda.core.internal.div import net.corda.core.internal.noneOrSingle import net.corda.core.utilities.NetworkHostAndPort -import net.corda.demobench.plugin.PluginController +import net.corda.demobench.plugin.CordappController import net.corda.demobench.pty.R3Pty import tornadofx.* import java.io.IOException @@ -27,7 +27,7 @@ class NodeController(check: atRuntime = ::checkExists) : Controller() { } private val jvm by inject() - private val pluginController by inject() + private val cordappController by inject() private var baseDir: Path = baseDirFor(ManagementFactory.getRuntimeMXBean().startTime) private val cordaPath: Path = jvm.applicationDir.resolve("corda").resolve("corda.jar") @@ -112,7 +112,7 @@ class NodeController(check: atRuntime = ::checkExists) : Controller() { config.nodeDir.createDirectories() // Install any built-in plugins into the working directory. - pluginController.populate(config) + cordappController.populate(config) // Write this node's configuration file into its working directory. val confFile = config.nodeDir / "node.conf" @@ -164,9 +164,9 @@ class NodeController(check: atRuntime = ::checkExists) : Controller() { fun install(config: InstallConfig): NodeConfigWrapper { val installed = config.installTo(baseDir) - pluginController.userPluginsFor(config).forEach { - installed.pluginDir.createDirectories() - val plugin = it.copyToDirectory(installed.pluginDir) + cordappController.useCordappsFor(config).forEach { + installed.cordappsDir.createDirectories() + val plugin = it.copyToDirectory(installed.cordappsDir) log.info("Installed: $plugin") } diff --git a/tools/demobench/src/main/kotlin/net/corda/demobench/plugin/CordappController.kt b/tools/demobench/src/main/kotlin/net/corda/demobench/plugin/CordappController.kt new file mode 100644 index 0000000000..765824f4e8 --- /dev/null +++ b/tools/demobench/src/main/kotlin/net/corda/demobench/plugin/CordappController.kt @@ -0,0 +1,61 @@ +package net.corda.demobench.plugin + +import net.corda.core.internal.copyToDirectory +import net.corda.core.internal.createDirectories +import net.corda.core.internal.exists +import net.corda.demobench.model.HasCordapps +import net.corda.demobench.model.JVMConfig +import net.corda.demobench.model.NodeConfig +import net.corda.demobench.model.NodeConfigWrapper +import tornadofx.* +import java.io.IOException +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.StandardCopyOption +import java.util.stream.Stream + +class CordappController : Controller() { + + private val jvm by inject() + private val cordappDir: Path = jvm.applicationDir.resolve(NodeConfig.cordappDirName) + private val bankOfCorda: Path = cordappDir.resolve("bank-of-corda.jar") + private val finance: Path = cordappDir.resolve("corda-finance.jar") + + /** + * Install any built-in cordapps that this node requires. + */ + @Throws(IOException::class) + fun populate(config: NodeConfigWrapper) { + if (!config.cordappsDir.exists()) { + config.cordappsDir.createDirectories() + } + if (finance.exists()) { + finance.copyToDirectory(config.cordappsDir, StandardCopyOption.REPLACE_EXISTING) + log.info("Installed 'Finance' cordapp") + } + // Nodes cannot issue cash unless they contain the "Bank of Corda" cordapp. + if (config.nodeConfig.issuableCurrencies.isNotEmpty() && bankOfCorda.exists()) { + bankOfCorda.copyToDirectory(config.cordappsDir, StandardCopyOption.REPLACE_EXISTING) + log.info("Installed 'Bank of Corda' cordapp") + } + } + + /** + * Generates a stream of a node's non-built-in cordapps. + */ + @Throws(IOException::class) + fun useCordappsFor(config: HasCordapps): Stream = walkCordapps(config.cordappsDir) + .filter { !bankOfCorda.endsWith(it.fileName) } + .filter { !finance.endsWith(it.fileName) } + + private fun walkCordapps(cordappsDir: Path): Stream { + return if (Files.isDirectory(cordappsDir)) + Files.walk(cordappsDir, 1).filter(Path::isCordapp) + else + Stream.empty() + } + +} + +fun Path.isCordapp(): Boolean = Files.isReadable(this) && this.fileName.toString().endsWith(".jar") +fun Path.inCordappsDir(): Boolean = (this.parent != null) && this.parent.endsWith("cordapps/") diff --git a/tools/demobench/src/main/kotlin/net/corda/demobench/plugin/PluginController.kt b/tools/demobench/src/main/kotlin/net/corda/demobench/plugin/PluginController.kt deleted file mode 100644 index ac25d72c55..0000000000 --- a/tools/demobench/src/main/kotlin/net/corda/demobench/plugin/PluginController.kt +++ /dev/null @@ -1,58 +0,0 @@ -package net.corda.demobench.plugin - -import net.corda.core.internal.copyToDirectory -import net.corda.core.internal.createDirectories -import net.corda.core.internal.exists -import net.corda.demobench.model.HasPlugins -import net.corda.demobench.model.JVMConfig -import net.corda.demobench.model.NodeConfigWrapper -import tornadofx.* -import java.io.IOException -import java.nio.file.Files -import java.nio.file.Path -import java.nio.file.StandardCopyOption -import java.util.stream.Stream - -class PluginController : Controller() { - - private val jvm by inject() - private val pluginDir: Path = jvm.applicationDir.resolve("plugins") - private val bankOfCorda: Path = pluginDir.resolve("bank-of-corda.jar") - private val finance: Path = pluginDir.resolve("corda-finance.jar") - - /** - * Install any built-in plugins that this node requires. - */ - @Throws(IOException::class) - fun populate(config: NodeConfigWrapper) { - config.pluginDir.createDirectories() - if (finance.exists()) { - finance.copyToDirectory(config.pluginDir, StandardCopyOption.REPLACE_EXISTING) - log.info("Installed 'Finance' plugin") - } - // Nodes cannot issue cash unless they contain the "Bank of Corda" plugin. - if (config.nodeConfig.issuableCurrencies.isNotEmpty() && bankOfCorda.exists()) { - bankOfCorda.copyToDirectory(config.pluginDir, StandardCopyOption.REPLACE_EXISTING) - log.info("Installed 'Bank of Corda' plugin") - } - } - - /** - * Generates a stream of a node's non-built-in plugins. - */ - @Throws(IOException::class) - fun userPluginsFor(config: HasPlugins): Stream = walkPlugins(config.pluginDir) - .filter { !bankOfCorda.endsWith(it.fileName) } - .filter { !finance.endsWith(it.fileName) } - - private fun walkPlugins(pluginDir: Path): Stream { - return if (Files.isDirectory(pluginDir)) - Files.walk(pluginDir, 1).filter(Path::isPlugin) - else - Stream.empty() - } - -} - -fun Path.isPlugin(): Boolean = Files.isReadable(this) && this.fileName.toString().endsWith(".jar") -fun Path.inPluginsDir(): Boolean = (this.parent != null) && this.parent.endsWith("plugins/") diff --git a/tools/demobench/src/main/kotlin/net/corda/demobench/profile/ProfileController.kt b/tools/demobench/src/main/kotlin/net/corda/demobench/profile/ProfileController.kt index c963a1c9ae..9f8a380b38 100644 --- a/tools/demobench/src/main/kotlin/net/corda/demobench/profile/ProfileController.kt +++ b/tools/demobench/src/main/kotlin/net/corda/demobench/profile/ProfileController.kt @@ -6,13 +6,10 @@ import javafx.stage.FileChooser import javafx.stage.FileChooser.ExtensionFilter import net.corda.core.internal.createDirectories import net.corda.core.internal.div -import net.corda.demobench.model.InstallConfig -import net.corda.demobench.model.InstallFactory -import net.corda.demobench.model.JVMConfig -import net.corda.demobench.model.NodeController -import net.corda.demobench.plugin.PluginController -import net.corda.demobench.plugin.inPluginsDir -import net.corda.demobench.plugin.isPlugin +import net.corda.demobench.model.* +import net.corda.demobench.plugin.CordappController +import net.corda.demobench.plugin.inCordappsDir +import net.corda.demobench.plugin.isCordapp import tornadofx.* import java.io.File import java.io.IOException @@ -31,7 +28,7 @@ class ProfileController : Controller() { private val jvm by inject() private val baseDir: Path = jvm.dataHome private val nodeController by inject() - private val pluginController by inject() + private val cordappController by inject() private val installFactory by inject() private val chooser = FileChooser() @@ -64,11 +61,11 @@ class ProfileController : Controller() { val file = Files.write(nodeDir / "node.conf", config.nodeConfig.toText().toByteArray(UTF_8)) log.info("Wrote: $file") - // Write all of the non-built-in plugins. - val pluginDir = Files.createDirectory(nodeDir.resolve("plugins")) - pluginController.userPluginsFor(config).forEach { - val plugin = Files.copy(it, pluginDir.resolve(it.fileName.toString())) - log.info("Wrote: $plugin") + // Write all of the non-built-in cordapps. + val cordappDir = Files.createDirectory(nodeDir.resolve(NodeConfig.cordappDirName)) + cordappController.useCordappsFor(config).forEach { + val cordapp = Files.copy(it, cordappDir.resolve(it.fileName.toString())) + log.info("Wrote: $cordapp") } } } @@ -120,16 +117,16 @@ class ProfileController : Controller() { // Now extract all of the plugins from the ZIP file, // and copy them to a temporary location. StreamSupport.stream(fs.rootDirectories.spliterator(), false) - .flatMap { Files.find(it, 3, BiPredicate { p, attr -> p.inPluginsDir() && p.isPlugin() && attr.isRegularFile }) } - .forEach { plugin -> - val config = nodeIndex[plugin.getName(0).toString()] ?: return@forEach + .flatMap { Files.find(it, 3, BiPredicate { p, attr -> p.inCordappsDir() && p.isCordapp() && attr.isRegularFile }) } + .forEach { cordapp -> + val config = nodeIndex[cordapp.getName(0).toString()] ?: return@forEach try { - val pluginDir = Files.createDirectories(config.pluginDir) - Files.copy(plugin, pluginDir.resolve(plugin.fileName.toString())) - log.info("Loaded: $plugin") + val cordappDir = Files.createDirectories(config.cordappsDir) + Files.copy(cordapp, cordappDir.resolve(cordapp.fileName.toString())) + log.info("Loaded: $cordapp") } catch (e: Exception) { - log.log(Level.SEVERE, "Failed to extract '$plugin': ${e.message}", e) + log.log(Level.SEVERE, "Failed to extract '$cordapp': ${e.message}", e) configs.forEach { c -> c.deleteBaseDir() } throw e } diff --git a/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeConfigTest.kt b/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeConfigTest.kt index e8fb14dff4..0bf02c1ca8 100644 --- a/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeConfigTest.kt +++ b/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeConfigTest.kt @@ -5,6 +5,7 @@ import com.typesafe.config.ConfigValueFactory import net.corda.core.identity.CordaX500Name import net.corda.core.utilities.NetworkHostAndPort import net.corda.node.internal.NetworkMapInfo +import net.corda.node.internal.cordapp.CordappLoader import net.corda.node.services.config.FullNodeConfiguration import net.corda.nodeapi.User import net.corda.nodeapi.config.parseAs diff --git a/tools/explorer/src/main/java/ExplorerCaplet.java b/tools/explorer/src/main/java/ExplorerCaplet.java index 7ab25d09b5..fdeb2821fb 100644 --- a/tools/explorer/src/main/java/ExplorerCaplet.java +++ b/tools/explorer/src/main/java/ExplorerCaplet.java @@ -19,7 +19,7 @@ public class ExplorerCaplet extends Capsule { // defined as public static final fields on the Capsule class, therefore referential equality is safe. if (ATTR_APP_CLASS_PATH == attr) { T cp = super.attribute(attr); - List classpath = augmentClasspath((List) cp, "plugins"); + List classpath = augmentClasspath((List) cp, "cordapps"); return (T) augmentClasspath(classpath, "dependencies"); } return super.attribute(attr);