Merge branch 'master' into feature/CID-878-non_party_flow_sessions

# Conflicts:
#	core/src/test/kotlin/net/corda/core/flows/CollectSignaturesFlowTests.kt
This commit is contained in:
Shams Asari 2019-06-18 13:14:55 +01:00
commit f0f05df9f4
480 changed files with 2856 additions and 19698 deletions

10
.idea/compiler.xml generated
View File

@ -37,6 +37,8 @@
<module name="cliutils_test" target="1.8" /> <module name="cliutils_test" target="1.8" />
<module name="common-configuration-parsing_main" target="1.8" /> <module name="common-configuration-parsing_main" target="1.8" />
<module name="common-configuration-parsing_test" target="1.8" /> <module name="common-configuration-parsing_test" target="1.8" />
<module name="common-logging_main" target="1.8" />
<module name="common-logging_test" target="1.8" />
<module name="common-validation_main" target="1.8" /> <module name="common-validation_main" target="1.8" />
<module name="common-validation_test" target="1.8" /> <module name="common-validation_test" target="1.8" />
<module name="confidential-identities_main" target="1.8" /> <module name="confidential-identities_main" target="1.8" />
@ -177,6 +179,8 @@
<module name="net.corda_buildSrc_test" target="1.8" /> <module name="net.corda_buildSrc_test" target="1.8" />
<module name="net.corda_canonicalizer_main" target="1.8" /> <module name="net.corda_canonicalizer_main" target="1.8" />
<module name="net.corda_canonicalizer_test" target="1.8" /> <module name="net.corda_canonicalizer_test" target="1.8" />
<module name="netparams_main" target="1.8" />
<module name="netparams_test" target="1.8" />
<module name="network-bootstrapper_main" target="1.8" /> <module name="network-bootstrapper_main" target="1.8" />
<module name="network-bootstrapper_test" target="1.8" /> <module name="network-bootstrapper_test" target="1.8" />
<module name="network-verifier-contracts_main" target="1.8" /> <module name="network-verifier-contracts_main" target="1.8" />
@ -189,8 +193,8 @@
<module name="network-visualiser_test" target="1.8" /> <module name="network-visualiser_test" target="1.8" />
<module name="node-api_main" target="1.8" /> <module name="node-api_main" target="1.8" />
<module name="node-api_test" target="1.8" /> <module name="node-api_test" target="1.8" />
<module name="node-capsule_main" target="1.6" /> <module name="node-capsule_main" target="1.8" />
<module name="node-capsule_test" target="1.6" /> <module name="node-capsule_test" target="1.8" />
<module name="node-driver_integrationTest" target="1.8" /> <module name="node-driver_integrationTest" target="1.8" />
<module name="node-driver_main" target="1.8" /> <module name="node-driver_main" target="1.8" />
<module name="node-driver_test" target="1.8" /> <module name="node-driver_test" target="1.8" />
@ -200,6 +204,8 @@
<module name="node_main" target="1.8" /> <module name="node_main" target="1.8" />
<module name="node_smokeTest" target="1.8" /> <module name="node_smokeTest" target="1.8" />
<module name="node_test" target="1.8" /> <module name="node_test" target="1.8" />
<module name="nodeinfo_main" target="1.8" />
<module name="nodeinfo_test" target="1.8" />
<module name="notary-bft-smart_main" target="1.8" /> <module name="notary-bft-smart_main" target="1.8" />
<module name="notary-bft-smart_test" target="1.8" /> <module name="notary-bft-smart_test" target="1.8" />
<module name="notary-demo-contracts_main" target="1.8" /> <module name="notary-demo-contracts_main" target="1.8" />

21
SECURITY.md Normal file
View File

@ -0,0 +1,21 @@
# Security Policy
## Reporting a Vulnerability
Vulnerabilities in Corda can be reported by following the Corda responsible disclosure policy:
https://www.corda.net/participate/security.html
## Security Advisories
Security announcements affecting Corda will be published on the Corda mailing list. People can subscribe to corda-announce@groups.io to receive security updates when they are made available.
## Supported Versions
Security updates are made for the latest version of Corda.
| Version | Supported |
| ------- | ------------------ |
| 4.x | :white_check_mark: |
| 3.x | :x: |
| < 3 | :x: |

View File

@ -15,6 +15,26 @@ buildscript {
ext.quasar_group = 'co.paralleluniverse' ext.quasar_group = 'co.paralleluniverse'
ext.quasar_version = constants.getProperty("quasarVersion") ext.quasar_version = constants.getProperty("quasarVersion")
ext.quasar_exclusions = [
'co.paralleluniverse**',
'groovy**',
'com.esotericsoftware.**',
'jdk**',
'junit**',
'kotlin**',
'net.rubygrapefruit.**',
'org.gradle.**',
'org.apache.**',
'org.jacoco.**',
'org.junit**',
'org.slf4j**',
'worker.org.gradle.**',
'com.nhaarman.mockito_kotlin**',
'org.assertj**',
'org.hamcrest**',
'org.mockito**',
'org.opentest4j**'
]
// gradle-capsule-plugin:1.0.2 contains capsule:1.0.1 by default. // gradle-capsule-plugin:1.0.2 contains capsule:1.0.1 by default.
// We must configure it manually to use the latest capsule version. // We must configure it manually to use the latest capsule version.
@ -22,10 +42,12 @@ buildscript {
ext.asm_version = '5.0.4' ext.asm_version = '5.0.4'
ext.artemis_version = '2.6.2' ext.artemis_version = '2.6.2'
ext.jackson_version = '2.9.8' // upgrade Jackson only when corda is using kotlin 1.3.10
ext.jetty_version = '9.4.7.v20170914' ext.jackson_version = '2.9.5'
ext.jetty_version = '9.4.18.v20190429'
ext.jersey_version = '2.25' ext.jersey_version = '2.25'
ext.assertj_version = '3.8.0' ext.servlet_version = '4.0.1'
ext.assertj_version = '3.12.2'
ext.slf4j_version = '1.7.25' ext.slf4j_version = '1.7.25'
ext.log4j_version = '2.9.1' ext.log4j_version = '2.9.1'
ext.bouncycastle_version = constants.getProperty("bouncycastleVersion") ext.bouncycastle_version = constants.getProperty("bouncycastleVersion")
@ -34,14 +56,22 @@ buildscript {
ext.disruptor_version = constants.getProperty("disruptorVersion") ext.disruptor_version = constants.getProperty("disruptorVersion")
ext.metrics_version = constants.getProperty("metricsVersion") ext.metrics_version = constants.getProperty("metricsVersion")
ext.metrics_new_relic_version = constants.getProperty("metricsNewRelicVersion") ext.metrics_new_relic_version = constants.getProperty("metricsNewRelicVersion")
ext.okhttp_version = '3.5.0' ext.okhttp_version = '3.14.1'
ext.netty_version = '4.1.22.Final' ext.netty_version = '4.1.22.Final'
ext.typesafe_config_version = constants.getProperty("typesafeConfigVersion") ext.typesafe_config_version = constants.getProperty("typesafeConfigVersion")
ext.fileupload_version = '1.3.3' ext.fileupload_version = '1.4'
// Legacy JUnit 4 version
ext.junit_version = '4.12' ext.junit_version = '4.12'
// Need this version to access classpath scanning error handling fix -
// see https://github.com/junit-team/junit5/commit/389de48c2a18c5a93a7203ef424aa47a8a835a74
// Upgrade to 5.5.x when GA release is available.
ext.junit_vintage_version = '5.5.0-RC1'
ext.junit_jupiter_version = '5.5.0-RC1'
ext.junit_platform_version = '1.5.0-RC1'
// TODO Update this to the latest version when hibernate is updated
ext.mockito_version = '2.18.3' ext.mockito_version = '2.18.3'
ext.mockito_kotlin_version = '1.5.0' ext.mockito_kotlin_version = '1.6.0'
ext.hamkrest_version = '1.4.2.2' ext.hamkrest_version = '1.7.0.0'
ext.jopt_simple_version = '5.0.2' ext.jopt_simple_version = '5.0.2'
ext.jansi_version = '1.14' ext.jansi_version = '1.14'
ext.hibernate_version = '5.3.10.Final' ext.hibernate_version = '5.3.10.Final'
@ -50,7 +80,7 @@ buildscript {
ext.rxjava_version = '1.3.8' ext.rxjava_version = '1.3.8'
ext.dokka_version = '0.9.17' ext.dokka_version = '0.9.17'
ext.eddsa_version = '0.2.0' ext.eddsa_version = '0.2.0'
ext.dependency_checker_version = '4.0.0' ext.dependency_checker_version = '4.0.2'
ext.commons_collections_version = '4.1' ext.commons_collections_version = '4.1'
ext.beanutils_version = '1.9.3' ext.beanutils_version = '1.9.3'
ext.crash_version = '810d2b774b85d4938be01b9b65e29e4fddbc450b' ext.crash_version = '810d2b774b85d4938be01b9b65e29e4fddbc450b'
@ -61,8 +91,8 @@ buildscript {
ext.liquibase_version = '3.5.5' ext.liquibase_version = '3.5.5'
ext.artifactory_contextUrl = 'https://ci-artifactory.corda.r3cev.com/artifactory' ext.artifactory_contextUrl = 'https://ci-artifactory.corda.r3cev.com/artifactory'
ext.snake_yaml_version = constants.getProperty('snakeYamlVersion') ext.snake_yaml_version = constants.getProperty('snakeYamlVersion')
ext.docker_compose_rule_version = '0.33.0' ext.docker_compose_rule_version = '0.35.0'
ext.selenium_version = '3.8.1' ext.selenium_version = '3.141.59'
ext.ghostdriver_version = '2.1.0' ext.ghostdriver_version = '2.1.0'
ext.eaagentloader_version = '1.0.3' ext.eaagentloader_version = '1.0.3'
ext.proguard_version = constants.getProperty('proguardVersion') ext.proguard_version = constants.getProperty('proguardVersion')
@ -111,18 +141,16 @@ buildscript {
classpath "net.i2p.crypto:eddsa:$eddsa_version" // Needed for ServiceIdentityGenerator in the build environment. classpath "net.i2p.crypto:eddsa:$eddsa_version" // Needed for ServiceIdentityGenerator in the build environment.
classpath "org.owasp:dependency-check-gradle:${dependency_checker_version}" classpath "org.owasp:dependency-check-gradle:${dependency_checker_version}"
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:$artifactory_plugin_version" classpath "org.jfrog.buildinfo:build-info-extractor-gradle:$artifactory_plugin_version"
// Capsule gradle plugin forked and maintained locally to support Gradle 5.x
// See https://github.com/corda/gradle-capsule-plugin
classpath "us.kirchmeier:gradle-capsule-plugin:1.0.4_r3"
} }
} }
plugins { plugins {
// TODO The capsule plugin requires the newer DSL plugin block.It would be nice if we could unify all the plugins into one style,
// but the DSL has some restrictions e.g can't be used on the allprojects section. So we should revisit this if there are improvements in Gradle.
// Version 1.0.2 of this plugin uses capsule:1.0.1 by default.
id 'us.kirchmeier.capsule' version '1.0.2' apply false
// Add the shadow plugin to the plugins classpath for the entire project. // Add the shadow plugin to the plugins classpath for the entire project.
id 'com.github.johnrengelman.shadow' version '2.0.4' apply false id 'com.github.johnrengelman.shadow' version '2.0.4' apply false
id "com.gradle.build-scan" version "1.16" id "com.gradle.build-scan" version "2.2.1"
} }
ext { ext {
@ -208,6 +236,8 @@ allprojects {
// Prevent the project from creating temporary files outside of the build directory. // Prevent the project from creating temporary files outside of the build directory.
systemProperty 'java.io.tmpdir', buildDir.absolutePath systemProperty 'java.io.tmpdir', buildDir.absolutePath
maxHeapSize = "1g"
if (project.hasProperty('test.parallel') && project.property('test.parallel').toBoolean()) { if (project.hasProperty('test.parallel') && project.property('test.parallel').toBoolean()) {
maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) as int ?: 1 maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) as int ?: 1
} }
@ -366,6 +396,7 @@ bintrayConfig {
'corda-node-api', 'corda-node-api',
'corda-test-common', 'corda-test-common',
'corda-test-utils', 'corda-test-utils',
'corda-test-db',
'corda-jackson', 'corda-jackson',
'corda-webserver-impl', 'corda-webserver-impl',
'corda-webserver', 'corda-webserver',
@ -461,8 +492,10 @@ if (file('corda-docs-only-build').exists() || (System.getenv('CORDA_DOCS_ONLY_BU
} }
} }
wrapper { wrapper {
gradleVersion = "4.10.1" gradleVersion = "5.4.1"
distributionType = Wrapper.DistributionType.ALL distributionType = Wrapper.DistributionType.ALL
} }

View File

@ -18,8 +18,16 @@ dependencies {
testCompile project(':test-utils') testCompile project(':test-utils')
testCompile project(path: ':core', configuration: 'testArtifacts') testCompile project(path: ':core', configuration: 'testArtifacts')
testImplementation "org.junit.jupiter:junit-jupiter-api:${junit_jupiter_version}"
testImplementation "junit:junit:$junit_version"
testRuntimeOnly "org.junit.vintage:junit-vintage-engine:${junit_vintage_version}"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junit_jupiter_version}"
testRuntimeOnly "org.junit.platform:junit-platform-launcher:${junit_platform_version}"
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version" testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
testCompile "junit:junit:$junit_version"
} }
jar { jar {

View File

@ -239,7 +239,8 @@ open class StringToMethodCallParser<in T : Any> @JvmOverloads constructor(
/** Returns a string-to-string map of commands to a string describing available parameter types. */ /** Returns a string-to-string map of commands to a string describing available parameter types. */
val availableCommands: Map<String, String> val availableCommands: Map<String, String>
get() { get() {
return methodMap.entries().map { (name, args) -> return methodMap.entries().map { entry ->
val (name, args) = entry // TODO: Kotlin 1.1
val argStr = if (args.parameterCount == 0) "" else { val argStr = if (args.parameterCount == 0) "" else {
val paramNames = methodParamNames[name]!! val paramNames = methodParamNames[name]!!
val typeNames = args.parameters.map { it.type.simpleName } val typeNames = args.parameters.map { it.type.simpleName }

View File

@ -1,15 +0,0 @@
package net.corda.client.jackson.internal
import com.fasterxml.jackson.databind.Module
/**
* Should be implemented by CorDapps who wish to declare custom serializers.
* Classes of this type will be autodiscovered and registered.
*/
interface CustomShellSerializationFactory {
/**
* The returned [Module] will be registered automatically with the interactive shell.
*/
fun createJacksonModule(): Module
}

View File

@ -697,7 +697,7 @@ class JacksonSupportTest(@Suppress("unused") private val name: String, factory:
} }
private fun JsonNode.assertHasOnlyFields(vararg fieldNames: String): List<JsonNode> { private fun JsonNode.assertHasOnlyFields(vararg fieldNames: String): List<JsonNode> {
assertThat(fieldNames()).containsOnly(*fieldNames) assertThat(fieldNames()).toIterable().containsOnly(*fieldNames)
return fieldNames.map { this[it] } return fieldNames.map { this[it] }
} }

View File

@ -44,7 +44,13 @@ dependencies {
compile "org.apache.activemq:artemis-core-client:${artemis_version}" compile "org.apache.activemq:artemis-core-client:${artemis_version}"
// Unit testing helpers. // Unit testing helpers.
testCompile "junit:junit:$junit_version" testImplementation "org.junit.jupiter:junit-jupiter-api:${junit_jupiter_version}"
testImplementation "junit:junit:$junit_version"
testRuntimeOnly "org.junit.vintage:junit-vintage-engine:${junit_vintage_version}"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junit_jupiter_version}"
testRuntimeOnly "org.junit.platform:junit-platform-launcher:${junit_platform_version}"
testCompile "org.assertj:assertj-core:${assertj_version}" testCompile "org.assertj:assertj-core:${assertj_version}"
testCompile project(':test-utils') testCompile project(':test-utils')

View File

@ -13,8 +13,14 @@ dependencies {
compile project(':finance:workflows') compile project(':finance:workflows')
compile project(':finance:contracts') compile project(':finance:contracts')
testImplementation "org.junit.jupiter:junit-jupiter-api:${junit_jupiter_version}"
testImplementation "junit:junit:$junit_version"
testRuntimeOnly "org.junit.vintage:junit-vintage-engine:${junit_vintage_version}"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junit_jupiter_version}"
testRuntimeOnly "org.junit.platform:junit-platform-launcher:${junit_platform_version}"
// Unit testing helpers. // Unit testing helpers.
testCompile "junit:junit:$junit_version"
testCompile "org.assertj:assertj-core:${assertj_version}" testCompile "org.assertj:assertj-core:${assertj_version}"
testCompile project(':test-utils') testCompile project(':test-utils')

View File

@ -9,10 +9,10 @@ description 'Corda client RPC modules'
//noinspection GroovyAssignabilityCheck //noinspection GroovyAssignabilityCheck
configurations { configurations {
integrationTestCompile.extendsFrom testCompile integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime integrationTestRuntimeOnly.extendsFrom testRuntimeOnly
smokeTestCompile.extendsFrom compile smokeTestCompile.extendsFrom compile
smokeTestRuntime.extendsFrom runtime smokeTestRuntimeOnly.extendsFrom runtimeOnly
} }
compileKotlin { compileKotlin {
@ -74,9 +74,13 @@ dependencies {
// For caches rather than guava // For caches rather than guava
compile "com.github.ben-manes.caffeine:caffeine:$caffeine_version" compile "com.github.ben-manes.caffeine:caffeine:$caffeine_version"
testImplementation "junit:junit:$junit_version"
testRuntimeOnly "org.junit.vintage:junit-vintage-engine:${junit_vintage_version}"
testRuntimeOnly "org.junit.platform:junit-platform-launcher:${junit_platform_version}"
// Unit testing helpers. // Unit testing helpers.
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version" testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
testCompile "junit:junit:$junit_version"
testCompile "org.assertj:assertj-core:${assertj_version}" testCompile "org.assertj:assertj-core:${assertj_version}"
testCompile project(':node-driver') testCompile project(':node-driver')
@ -91,7 +95,9 @@ dependencies {
smokeTestCompile "org.apache.logging.log4j:log4j-core:$log4j_version" smokeTestCompile "org.apache.logging.log4j:log4j-core:$log4j_version"
smokeTestCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version" smokeTestCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
smokeTestCompile "org.assertj:assertj-core:${assertj_version}" smokeTestCompile "org.assertj:assertj-core:${assertj_version}"
smokeTestCompile "junit:junit:$junit_version" smokeTestImplementation "junit:junit:$junit_version"
smokeTestRuntimeOnly "org.junit.vintage:junit-vintage-engine:${junit_vintage_version}"
smokeTestRuntimeOnly "org.junit.platform:junit-platform-launcher:${junit_platform_version}"
} }
task integrationTest(type: Test) { task integrationTest(type: Test) {

View File

@ -21,6 +21,7 @@ import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration
import org.apache.activemq.artemis.api.core.SimpleString import org.apache.activemq.artemis.api.core.SimpleString
import org.junit.After import org.junit.After
import org.junit.Assert.* import org.junit.Assert.*
import org.junit.Ignore
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import rx.Observable import rx.Observable
@ -498,6 +499,7 @@ class RPCStabilityTests {
} }
@Test @Test
@Ignore // TODO: This is ignored because Artemis slow consumers are broken. I'm not deleting it in case we can get the feature fixed.
fun `slow consumers are kicked`() { fun `slow consumers are kicked`() {
rpcDriver { rpcDriver {
val server = startRpcServer(maxBufferedBytesPerClient = 10 * 1024 * 1024, ops = SlowConsumerRPCOpsImpl()).get() val server = startRpcServer(maxBufferedBytesPerClient = 10 * 1024 * 1024, ops = SlowConsumerRPCOpsImpl()).get()
@ -508,7 +510,7 @@ class RPCStabilityTests {
session.createTemporaryQueue(myQueue, ActiveMQDefaultConfiguration.getDefaultRoutingType(), myQueue) session.createTemporaryQueue(myQueue, ActiveMQDefaultConfiguration.getDefaultRoutingType(), myQueue)
val consumer = session.createConsumer(myQueue, null, -1, -1, false) val consumer = session.createConsumer(myQueue, null, -1, -1, false)
consumer.setMessageHandler { consumer.setMessageHandler {
Thread.sleep(50) // 5x slower than the server producer Thread.sleep(5000) // Needs to be slower than one per second to get kicked.
it.acknowledge() it.acknowledge()
} }
val producer = session.createProducer(RPCApi.RPC_SERVER_QUEUE_NAME) val producer = session.createProducer(RPCApi.RPC_SERVER_QUEUE_NAME)
@ -520,7 +522,7 @@ class RPCStabilityTests {
val request = RPCApi.ClientToServer.RpcRequest( val request = RPCApi.ClientToServer.RpcRequest(
clientAddress = SimpleString(myQueue), clientAddress = SimpleString(myQueue),
methodName = SlowConsumerRPCOps::streamAtInterval.name, methodName = SlowConsumerRPCOps::streamAtInterval.name,
serialisedArguments = listOf(10.millis, 123456).serialize(context = SerializationDefaults.RPC_SERVER_CONTEXT), serialisedArguments = listOf(100.millis, 1234).serialize(context = SerializationDefaults.RPC_SERVER_CONTEXT),
replyId = Trace.InvocationId.newInstance(), replyId = Trace.InvocationId.newInstance(),
sessionId = Trace.SessionId.newInstance() sessionId = Trace.SessionId.newInstance()
) )
@ -529,7 +531,7 @@ class RPCStabilityTests {
producer.send(message) producer.send(message)
session.commit() session.commit()
// We are consuming slower than the server is producing, so we should be kicked after a while // We are consuming slower than the server is producing, so we should be kicked after a while if slow consumers are enabled.
pollUntilClientNumber(server, 0) pollUntilClientNumber(server, 0)
} }
} }

View File

@ -23,7 +23,6 @@ import net.corda.serialization.internal.amqp.SerializationFactoryCacheKey
import net.corda.serialization.internal.amqp.SerializerFactory import net.corda.serialization.internal.amqp.SerializerFactory
import java.time.Duration import java.time.Duration
import java.util.ServiceLoader import java.util.ServiceLoader
import java.net.URLClassLoader
/** /**
* This class is essentially just a wrapper for an RPCConnection<CordaRPCOps> and can be treated identically. * This class is essentially just a wrapper for an RPCConnection<CordaRPCOps> and can be treated identically.
@ -300,14 +299,11 @@ class CordaRPCClient private constructor(
try { try {
val cache = Caffeine.newBuilder().maximumSize(128).build<SerializationFactoryCacheKey, SerializerFactory>().asMap() val cache = Caffeine.newBuilder().maximumSize(128).build<SerializationFactoryCacheKey, SerializerFactory>().asMap()
// If the client has provided a classloader, the associated classpath is checked for available custom serializers and serialization whitelists. // If the client has explicitly provided a classloader use this one to scan for custom serializers, otherwise use the current one.
if (classLoader != null) { val serializationClassLoader = this.classLoader ?: this.javaClass.classLoader
val customSerializers = createInstancesOfClassesImplementing(classLoader, SerializationCustomSerializer::class.java) val customSerializers = createInstancesOfClassesImplementing(serializationClassLoader, SerializationCustomSerializer::class.java)
val serializationWhitelists = ServiceLoader.load(SerializationWhitelist::class.java, classLoader).toSet() val serializationWhitelists = ServiceLoader.load(SerializationWhitelist::class.java, serializationClassLoader).toSet()
AMQPClientSerializationScheme.initialiseSerialization(classLoader, customSerializers, serializationWhitelists, cache) AMQPClientSerializationScheme.initialiseSerialization(serializationClassLoader, customSerializers, serializationWhitelists, cache)
} else {
AMQPClientSerializationScheme.initialiseSerialization(classLoader, serializerFactoriesForContexts = cache)
}
} catch (e: IllegalStateException) { } catch (e: IllegalStateException) {
// Race e.g. two of these constructed in parallel, ignore. // Race e.g. two of these constructed in parallel, ignore.
} }

View File

@ -10,9 +10,15 @@ dependencies {
compile group: "com.typesafe", name: "config", version: typesafe_config_version compile group: "com.typesafe", name: "config", version: typesafe_config_version
compile project(":common-validation") compile project(":common-validation")
testImplementation "org.junit.jupiter:junit-jupiter-api:${junit_jupiter_version}"
testImplementation "junit:junit:$junit_version"
testRuntimeOnly "org.junit.vintage:junit-vintage-engine:${junit_vintage_version}"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junit_jupiter_version}"
testRuntimeOnly "org.junit.platform:junit-platform-launcher:${junit_platform_version}"
testCompile group: "org.jetbrains.kotlin", name: "kotlin-test", version: kotlin_version testCompile group: "org.jetbrains.kotlin", name: "kotlin-test", version: kotlin_version
testCompile group: "junit", name: "junit", version: junit_version
testCompile group: "org.assertj", name: "assertj-core", version: assertj_version testCompile group: "org.assertj", name: "assertj-core", version: assertj_version
} }

View File

@ -1,5 +1,6 @@
apply plugin: 'kotlin' import org.apache.tools.ant.filters.ReplaceTokens
apply plugin: 'kotlin'
apply plugin: 'net.corda.plugins.publish-utils' apply plugin: 'net.corda.plugins.publish-utils'
apply plugin: 'com.jfrog.artifactory' apply plugin: 'com.jfrog.artifactory'
@ -8,15 +9,23 @@ dependencies {
compile group: "org.jetbrains.kotlin", name: "kotlin-reflect", version: kotlin_version compile group: "org.jetbrains.kotlin", name: "kotlin-reflect", version: kotlin_version
compile group: "com.typesafe", name: "config", version: typesafe_config_version compile group: "com.typesafe", name: "config", version: typesafe_config_version
compile "org.apache.logging.log4j:log4j-slf4j-impl:$log4j_version"
// Log4J: logging framework
compile "org.apache.logging.log4j:log4j-core:$log4j_version"
compile "com.jcabi:jcabi-manifests:$jcabi_manifests_version" compile "com.jcabi:jcabi-manifests:$jcabi_manifests_version"
testCompile project(":test-utils") testCompile project(":test-utils")
} }
task generateSource(type: Copy) {
from 'src/main/template'
filter(ReplaceTokens, tokens: [corda_release_version: corda_release_version])
into 'src/main'
}
compileKotlin.dependsOn generateSource
jar { jar {
baseName 'corda-common-logging' baseName 'corda-common-logging'
} }

View File

@ -0,0 +1,11 @@
@file:JvmName("Constants")
package net.corda.common.logging
/**
* constants in this file are generated by gradle
* to change this file, edit src/main/template/kotlin/net/corda/common/logging/Constants.kt
* the generated file does not need to be committed to source control (originally added to source control for ease of use)
*/
internal const val CURRENT_MAJOR_RELEASE = "5.0-SNAPSHOT"

View File

@ -5,7 +5,6 @@ import com.jcabi.manifests.Manifests
class CordaVersion { class CordaVersion {
companion object { companion object {
private const val UNKNOWN = "Unknown" private const val UNKNOWN = "Unknown"
const val current_major_release = "4.0-SNAPSHOT"
const val platformEditionCode = "OS" const val platformEditionCode = "OS"
private fun manifestValue(name: String): String? = if (Manifests.exists(name)) Manifests.read(name) else null private fun manifestValue(name: String): String? = if (Manifests.exists(name)) Manifests.read(name) else null
@ -15,7 +14,7 @@ class CordaVersion {
val vendor: String by lazy { manifestValue("Corda-Vendor") ?: UNKNOWN } val vendor: String by lazy { manifestValue("Corda-Vendor") ?: UNKNOWN }
val platformVersion: Int by lazy { manifestValue("Corda-Platform-Version")?.toInt() ?: 1 } val platformVersion: Int by lazy { manifestValue("Corda-Platform-Version")?.toInt() ?: 1 }
internal val semanticVersion: String by lazy { if(releaseVersion == UNKNOWN) current_major_release else releaseVersion } internal val semanticVersion: String by lazy { if(releaseVersion == UNKNOWN) CURRENT_MAJOR_RELEASE else releaseVersion }
} }
fun getVersion(): Array<String> { fun getVersion(): Array<String> {

View File

@ -0,0 +1,11 @@
@file:JvmName("Constants")
package net.corda.common.logging
/**
* constants in this file are generated by gradle
* to change this file, edit src/main/template/kotlin/net/corda/common/logging/Constants.kt
* the generated file does not need to be committed to source control (originally added to source control for ease of use)
*/
internal const val CURRENT_MAJOR_RELEASE = "@corda_release_version@"

View File

@ -12,7 +12,12 @@ dependencies {
cordaCompile project(':core') cordaCompile project(':core')
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version" testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
testCompile "junit:junit:$junit_version" testImplementation "org.junit.jupiter:junit-jupiter-api:${junit_jupiter_version}"
testImplementation "junit:junit:$junit_version"
testRuntimeOnly "org.junit.vintage:junit-vintage-engine:${junit_vintage_version}"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junit_jupiter_version}"
testRuntimeOnly "org.junit.platform:junit-platform-launcher:${junit_platform_version}"
// Guava: Google test library (collections test suite) // Guava: Google test library (collections test suite)
testCompile "com.google.guava:guava-testlib:$guava_version" testCompile "com.google.guava:guava-testlib:$guava_version"
@ -26,8 +31,6 @@ dependencies {
jar { jar {
baseName 'corda-confidential-identities' baseName 'corda-confidential-identities'
preserveFileTimestamps = false
reproducibleFileOrder = true
} }
publish { publish {

View File

@ -3,7 +3,7 @@ package net.corda.confidential
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import com.natpryce.hamkrest.MatchResult import com.natpryce.hamkrest.MatchResult
import com.natpryce.hamkrest.Matcher import com.natpryce.hamkrest.Matcher
import com.natpryce.hamkrest.assertion.assert import com.natpryce.hamkrest.assertion.assertThat
import com.natpryce.hamkrest.equalTo import com.natpryce.hamkrest.equalTo
import net.corda.core.crypto.DigitalSignature import net.corda.core.crypto.DigitalSignature
import net.corda.core.flows.FlowLogic import net.corda.core.flows.FlowLogic
@ -18,7 +18,10 @@ import net.corda.testing.core.*
import net.corda.testing.internal.matchers.allOf import net.corda.testing.internal.matchers.allOf
import net.corda.testing.internal.matchers.flow.willReturn import net.corda.testing.internal.matchers.flow.willReturn
import net.corda.testing.internal.matchers.hasOnlyEntries import net.corda.testing.internal.matchers.hasOnlyEntries
import net.corda.testing.node.internal.* import net.corda.testing.node.internal.InternalMockNetwork
import net.corda.testing.node.internal.TestStartedNode
import net.corda.testing.node.internal.enclosedCordapp
import net.corda.testing.node.internal.startFlow
import org.assertj.core.api.Assertions.assertThatThrownBy import org.assertj.core.api.Assertions.assertThatThrownBy
import org.junit.AfterClass import org.junit.AfterClass
import org.junit.Test import org.junit.Test
@ -45,7 +48,7 @@ class SwapIdentitiesFlowTests {
@Test @Test
fun `issue key`() { fun `issue key`() {
assert.that( assertThat(
aliceNode.services.startFlow(SwapIdentitiesInitiator(bob)), aliceNode.services.startFlow(SwapIdentitiesInitiator(bob)),
willReturn( willReturn(
hasOnlyEntries( hasOnlyEntries(

View File

@ -3,7 +3,7 @@
# their own projects. So don't get fancy with syntax! # their own projects. So don't get fancy with syntax!
cordaVersion=5.0-SNAPSHOT cordaVersion=5.0-SNAPSHOT
gradlePluginsVersion=4.0.42 gradlePluginsVersion=5.0.1
kotlinVersion=1.2.71 kotlinVersion=1.2.71
java8MinUpdateVersion=171 java8MinUpdateVersion=171
# ***************************************************************# # ***************************************************************#

View File

@ -12,10 +12,13 @@ dependencies {
transitive = false transitive = false
} }
testCompile "org.apache.logging.log4j:log4j-slf4j-impl:$log4j_version" testImplementation "org.slf4j:slf4j-api:$slf4j_version"
testRuntimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:$log4j_version"
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version" testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
testCompile "org.assertj:assertj-core:$assertj_version" testCompile "org.assertj:assertj-core:$assertj_version"
testCompile "junit:junit:$junit_version" testImplementation "junit:junit:$junit_version"
testRuntimeOnly "org.junit.vintage:junit-vintage-engine:${junit_vintage_version}"
testRuntimeOnly "org.junit.platform:junit-platform-launcher:${junit_platform_version}"
} }
// This module has no artifact and only contains tests. // This module has no artifact and only contains tests.

View File

@ -12,7 +12,11 @@ dependencies {
testCompile "org.jetbrains.kotlin:kotlin-stdlib-jdk8" testCompile "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
testCompile "org.jetbrains.kotlin:kotlin-reflect" testCompile "org.jetbrains.kotlin:kotlin-reflect"
testCompile "junit:junit:$junit_version"
testImplementation "junit:junit:$junit_version"
testRuntimeOnly "org.junit.vintage:junit-vintage-engine:${junit_vintage_version}"
testRuntimeOnly "org.junit.platform:junit-platform-launcher:${junit_platform_version}"
} }
jar.enabled = false jar.enabled = false

View File

@ -21,6 +21,7 @@ dependencies {
// Compile against the deterministic artifacts to ensure that we use only the deterministic API subset. // Compile against the deterministic artifacts to ensure that we use only the deterministic API subset.
compileOnly configurations.deterministicArtifacts compileOnly configurations.deterministicArtifacts
api "junit:junit:$junit_version" api "junit:junit:$junit_version"
runtimeOnly "org.junit.vintage:junit-vintage-engine:${junit_vintage_version}"
} }
jar { jar {

View File

@ -1,6 +1,5 @@
package net.corda.deterministic.verifier package net.corda.deterministic.verifier
import net.corda.core.serialization.ClassWhitelist
import net.corda.core.serialization.SerializationContext import net.corda.core.serialization.SerializationContext
import net.corda.core.serialization.SerializationContext.UseCase.P2P import net.corda.core.serialization.SerializationContext.UseCase.P2P
import net.corda.core.serialization.SerializationCustomSerializer import net.corda.core.serialization.SerializationCustomSerializer

View File

@ -11,10 +11,10 @@ evaluationDependsOn(':node:capsule')
configurations { configurations {
integrationTestCompile.extendsFrom testCompile integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime integrationTestRuntimeOnly.extendsFrom testRuntimeOnly
smokeTestCompile.extendsFrom compile smokeTestCompile.extendsFrom compile
smokeTestRuntime.extendsFrom runtime smokeTestRuntimeOnly.extendsFrom runtimeOnly
} }
sourceSets { sourceSets {
@ -54,7 +54,13 @@ processSmokeTestResources {
} }
dependencies { dependencies {
testCompile "junit:junit:$junit_version"
testImplementation "org.junit.jupiter:junit-jupiter-api:${junit_jupiter_version}"
testImplementation "junit:junit:$junit_version"
testRuntimeOnly "org.junit.vintage:junit-vintage-engine:${junit_vintage_version}"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junit_jupiter_version}"
testRuntimeOnly "org.junit.platform:junit-platform-launcher:${junit_platform_version}"
testCompile "commons-fileupload:commons-fileupload:$fileupload_version" testCompile "commons-fileupload:commons-fileupload:$fileupload_version"
// Guava: Google test library (collections test suite) // Guava: Google test library (collections test suite)
@ -87,9 +93,15 @@ dependencies {
compile "com.github.ben-manes.caffeine:caffeine:$caffeine_version" compile "com.github.ben-manes.caffeine:caffeine:$caffeine_version"
// Smoke tests do NOT have any Node code on the classpath! // Smoke tests do NOT have any Node code on the classpath!
smokeTestImplementation "org.junit.jupiter:junit-jupiter-api:${junit_jupiter_version}"
smokeTestImplementation "junit:junit:$junit_version"
smokeTestRuntimeOnly "org.junit.vintage:junit-vintage-engine:${junit_vintage_version}"
smokeTestRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junit_jupiter_version}"
smokeTestRuntimeOnly "org.junit.platform:junit-platform-launcher:${junit_platform_version}"
smokeTestCompile project(':smoke-test-utils') smokeTestCompile project(':smoke-test-utils')
smokeTestCompile "org.assertj:assertj-core:${assertj_version}" smokeTestCompile "org.assertj:assertj-core:${assertj_version}"
smokeTestCompile "junit:junit:$junit_version"
// RxJava: observable streams of events. // RxJava: observable streams of events.
compile "io.reactivex:rxjava:$rxjava_version" compile "io.reactivex:rxjava:$rxjava_version"
@ -97,7 +109,8 @@ dependencies {
// Apache JEXL: An embeddable expression evaluation library. // Apache JEXL: An embeddable expression evaluation library.
// This may be temporary until we experiment with other ways to do on-the-fly contract specialisation via an API. // This may be temporary until we experiment with other ways to do on-the-fly contract specialisation via an API.
compile "org.apache.commons:commons-jexl3:3.0" compile "org.apache.commons:commons-jexl3:3.0"
compile 'commons-lang:commons-lang:2.6'
compile "org.apache.commons:commons-lang3:3.9"
// Java ed25519 implementation. See https://github.com/str4d/ed25519-java/ // Java ed25519 implementation. See https://github.com/str4d/ed25519-java/
compile "net.i2p.crypto:eddsa:$eddsa_version" compile "net.i2p.crypto:eddsa:$eddsa_version"
@ -128,7 +141,12 @@ jar {
} }
configurations { configurations {
testArtifacts.extendsFrom testRuntime testArtifacts.extendsFrom testRuntimeClasspath
}
tasks.withType(Test) {
// fork a new test process for every test class
forkEvery = 10
} }
task testJar(type: Jar) { task testJar(type: Jar) {
@ -152,6 +170,35 @@ task smokeTest(type: Test) {
classpath = sourceSets.smokeTest.runtimeClasspath classpath = sourceSets.smokeTest.runtimeClasspath
} }
// quasar exclusions upon agent code instrumentation at run-time
quasar {
excludePackages.addAll(
"antlr**",
"com.codahale**",
"com.fasterxml.**",
"com.github.benmanes.caffeine.**",
"com.google.**",
"com.lmax.**",
"com.zaxxer.**",
"net.bytebuddy**",
"io.github.classgraph**",
"io.netty*",
"liquibase**",
"net.i2p.crypto.**",
"nonapi.io.github.classgraph.**",
"org.apiguardian.**",
"org.bouncycastle**",
"org.codehaus.**",
"org.h2**",
"org.hibernate**",
"org.jboss.**",
"org.objenesis**",
"org.w3c.**",
"org.xml**",
"org.yaml**",
"rx**")
}
artifacts { artifacts {
testArtifacts testJar testArtifacts testJar
} }

View File

@ -1,5 +1,7 @@
package net.corda.core.contracts package net.corda.core.contracts
import net.corda.core.DeleteForDJVM
import net.corda.core.KeepForDJVM
import net.corda.core.node.ServiceHub import net.corda.core.node.ServiceHub
import net.corda.core.node.services.Vault import net.corda.core.node.services.Vault
import net.corda.core.node.services.queryBy import net.corda.core.node.services.queryBy
@ -14,6 +16,7 @@ import net.corda.core.transactions.LedgerTransaction
* [StaticPointer]s are for use with any type of [ContractState]. * [StaticPointer]s are for use with any type of [ContractState].
*/ */
@CordaSerializable @CordaSerializable
@KeepForDJVM
sealed class StatePointer<T : ContractState> { sealed class StatePointer<T : ContractState> {
/** /**
* An identifier for the [ContractState] that this [StatePointer] points to. * An identifier for the [ContractState] that this [StatePointer] points to.
@ -31,6 +34,7 @@ sealed class StatePointer<T : ContractState> {
* *
* @param services a [ServiceHub] implementation is required to resolve the pointer. * @param services a [ServiceHub] implementation is required to resolve the pointer.
*/ */
@DeleteForDJVM
abstract fun resolve(services: ServiceHub): StateAndRef<T> abstract fun resolve(services: ServiceHub): StateAndRef<T>
/** /**
@ -49,12 +53,14 @@ sealed class StatePointer<T : ContractState> {
* - The [ContractState] may not be known by the node performing the look-up in which case the [resolve] method will * - The [ContractState] may not be known by the node performing the look-up in which case the [resolve] method will
* throw a [TransactionResolutionException] * throw a [TransactionResolutionException]
*/ */
@KeepForDJVM
class StaticPointer<T : ContractState>(override val pointer: StateRef, override val type: Class<T>) : StatePointer<T>() { class StaticPointer<T : ContractState>(override val pointer: StateRef, override val type: Class<T>) : StatePointer<T>() {
/** /**
* Resolves a [StaticPointer] to a [StateAndRef] via a [StateRef] look-up. * Resolves a [StaticPointer] to a [StateAndRef] via a [StateRef] look-up.
*/ */
@Throws(TransactionResolutionException::class) @Throws(TransactionResolutionException::class)
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@DeleteForDJVM
override fun resolve(services: ServiceHub): StateAndRef<T> { override fun resolve(services: ServiceHub): StateAndRef<T> {
val transactionState = services.loadState(pointer) as TransactionState<T> val transactionState = services.loadState(pointer) as TransactionState<T>
val castState: T = type.cast(transactionState.data) val castState: T = type.cast(transactionState.data)
@ -92,6 +98,7 @@ class StaticPointer<T : ContractState>(override val pointer: StateRef, override
* then the transaction with such a reference state cannot be committed to the ledger until the most up-to-date version * then the transaction with such a reference state cannot be committed to the ledger until the most up-to-date version
* of the [LinearState] is available. See reference states documentation on docs.corda.net for more info. * of the [LinearState] is available. See reference states documentation on docs.corda.net for more info.
*/ */
@KeepForDJVM
class LinearPointer<T : LinearState>(override val pointer: UniqueIdentifier, override val type: Class<T>) : StatePointer<T>() { class LinearPointer<T : LinearState>(override val pointer: UniqueIdentifier, override val type: Class<T>) : StatePointer<T>() {
/** /**
* Resolves a [LinearPointer] using the [UniqueIdentifier] contained in the [pointer] property. Returns a * Resolves a [LinearPointer] using the [UniqueIdentifier] contained in the [pointer] property. Returns a
@ -100,6 +107,7 @@ class LinearPointer<T : LinearState>(override val pointer: UniqueIdentifier, ove
* @param services a [ServiceHub] implementation is required to perform a vault query. * @param services a [ServiceHub] implementation is required to perform a vault query.
*/ */
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@DeleteForDJVM
override fun resolve(services: ServiceHub): StateAndRef<T> { override fun resolve(services: ServiceHub): StateAndRef<T> {
// Return the latest version of the linear state. // Return the latest version of the linear state.
// This query will only ever return one or zero states. // This query will only ever return one or zero states.

View File

@ -266,7 +266,6 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
/** /**
* Thrown when multiple attachments provide the same file when building the AttachmentsClassloader for a transaction. * Thrown when multiple attachments provide the same file when building the AttachmentsClassloader for a transaction.
*/ */
@CordaSerializable
@KeepForDJVM @KeepForDJVM
class OverlappingAttachmentsException(txId: SecureHash, val path: String) : TransactionVerificationException(txId, "Multiple attachments define a file at $path.", null) class OverlappingAttachmentsException(txId: SecureHash, val path: String) : TransactionVerificationException(txId, "Multiple attachments define a file at $path.", null)
@ -275,20 +274,17 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
* the [txId] will always be [SecureHash.zeroHash] because package ownership is an error with a particular attachment, * the [txId] will always be [SecureHash.zeroHash] because package ownership is an error with a particular attachment,
* and because attachment classloaders are reused this is independent of any particular transaction. * and because attachment classloaders are reused this is independent of any particular transaction.
*/ */
@CordaSerializable
class PackageOwnershipException(txId: SecureHash, @Suppress("unused") val attachmentHash: AttachmentId, @Suppress("unused") val invalidClassName: String, val packageName: String) : TransactionVerificationException(txId, class PackageOwnershipException(txId: SecureHash, @Suppress("unused") val attachmentHash: AttachmentId, @Suppress("unused") val invalidClassName: String, val packageName: String) : TransactionVerificationException(txId,
"""The attachment JAR: $attachmentHash containing the class: $invalidClassName is not signed by the owner of package $packageName specified in the network parameters. """The attachment JAR: $attachmentHash containing the class: $invalidClassName is not signed by the owner of package $packageName specified in the network parameters.
Please check the source of this attachment and if it is malicious contact your zone operator to report this incident. Please check the source of this attachment and if it is malicious contact your zone operator to report this incident.
For details see: https://docs.corda.net/network-map.html#network-parameters""".trimIndent(), null) For details see: https://docs.corda.net/network-map.html#network-parameters""".trimIndent(), null)
@CordaSerializable
class InvalidAttachmentException(txId: SecureHash, @Suppress("unused") val attachmentHash: AttachmentId) : TransactionVerificationException(txId, class InvalidAttachmentException(txId: SecureHash, @Suppress("unused") val attachmentHash: AttachmentId) : TransactionVerificationException(txId,
"The attachment $attachmentHash is not a valid ZIP or JAR file.".trimIndent(), null) "The attachment $attachmentHash is not a valid ZIP or JAR file.".trimIndent(), null)
// TODO: Make this descend from TransactionVerificationException so that untrusted attachments cause flows to be hospitalized. // TODO: Make this descend from TransactionVerificationException so that untrusted attachments cause flows to be hospitalized.
/** Thrown during classloading upon encountering an untrusted attachment (eg. not in the [TRUSTED_UPLOADERS] list) */ /** Thrown during classloading upon encountering an untrusted attachment (eg. not in the [TRUSTED_UPLOADERS] list) */
@KeepForDJVM @KeepForDJVM
@CordaSerializable
class UntrustedAttachmentsException(val txId: SecureHash, val ids: List<SecureHash>) : class UntrustedAttachmentsException(val txId: SecureHash, val ids: List<SecureHash>) :
CordaException("Attempting to load untrusted transaction attachments: $ids. " + CordaException("Attempting to load untrusted transaction attachments: $ids. " +
"At this time these are not loadable because the DJVM sandbox has not yet been integrated. " + "At this time these are not loadable because the DJVM sandbox has not yet been integrated. " +

View File

@ -4,7 +4,7 @@ package net.corda.core.crypto.internal
import net.corda.core.DeleteForDJVM import net.corda.core.DeleteForDJVM
import net.corda.core.crypto.newSecureRandom import net.corda.core.crypto.newSecureRandom
import org.apache.commons.lang.SystemUtils import org.apache.commons.lang3.SystemUtils
import java.security.Provider import java.security.Provider
import java.security.SecureRandom import java.security.SecureRandom
import java.security.SecureRandomSpi import java.security.SecureRandomSpi

View File

@ -83,12 +83,12 @@ data class CordaX500Name(val commonName: String?,
@JvmStatic @JvmStatic
fun build(principal: X500Principal): CordaX500Name { fun build(principal: X500Principal): CordaX500Name {
val attrsMap = principal.toAttributesMap(supportedAttributes) val attrsMap = principal.toAttributesMap(supportedAttributes)
val CN = attrsMap[BCStyle.CN]?.toString() val CN = attrsMap[BCStyle.CN]
val OU = attrsMap[BCStyle.OU]?.toString() val OU = attrsMap[BCStyle.OU]
val O = requireNotNull(attrsMap[BCStyle.O]?.toString()) { "Corda X.500 names must include an O attribute" } val O = requireNotNull(attrsMap[BCStyle.O]) { "Corda X.500 names must include an O attribute" }
val L = requireNotNull(attrsMap[BCStyle.L]?.toString()) { "Corda X.500 names must include an L attribute" } val L = requireNotNull(attrsMap[BCStyle.L]) { "Corda X.500 names must include an L attribute" }
val ST = attrsMap[BCStyle.ST]?.toString() val ST = attrsMap[BCStyle.ST]
val C = requireNotNull(attrsMap[BCStyle.C]?.toString()) { "Corda X.500 names must include an C attribute" } val C = requireNotNull(attrsMap[BCStyle.C]) { "Corda X.500 names must include an C attribute" }
return CordaX500Name(CN, OU, O, L, ST, C) return CordaX500Name(CN, OU, O, L, ST, C)
} }

View File

@ -2,6 +2,7 @@ package net.corda.core.internal
import net.corda.core.contracts.ContractState import net.corda.core.contracts.ContractState
import net.corda.core.contracts.StatePointer import net.corda.core.contracts.StatePointer
import org.apache.commons.lang3.reflect.FieldUtils
import java.lang.reflect.Field import java.lang.reflect.Field
import java.util.* import java.util.*
@ -25,20 +26,9 @@ class StatePointerSearch(val state: ContractState) {
// Queue of fields to search. // Queue of fields to search.
private val fieldQueue = ArrayDeque<FieldWithObject>().apply { addAllFields(state) } private val fieldQueue = ArrayDeque<FieldWithObject>().apply { addAllFields(state) }
// Get fields of class and all super-classes.
private fun getAllFields(clazz: Class<*>): List<Field> {
val fields = mutableListOf<Field>()
var currentClazz = clazz
while (currentClazz.superclass != null) {
fields.addAll(currentClazz.declaredFields)
currentClazz = currentClazz.superclass
}
return fields
}
// Helper for adding all fields to the queue. // Helper for adding all fields to the queue.
private fun ArrayDeque<FieldWithObject>.addAllFields(obj: Any) { private fun ArrayDeque<FieldWithObject>.addAllFields(obj: Any) {
val fields = getAllFields(obj::class.java) val fields = FieldUtils.getAllFieldsList(obj::class.java)
val fieldsWithObjects = fields.mapNotNull { field -> val fieldsWithObjects = fields.mapNotNull { field ->
// Ignore classes which have not been loaded. // Ignore classes which have not been loaded.

View File

@ -41,14 +41,14 @@ fun X500Principal.toX500Name(): X500Name = X500Name.getInstance(this.encoded)
* @throws IllegalArgumentException if this principal consists of duplicated attributes or the attribute is not supported. * @throws IllegalArgumentException if this principal consists of duplicated attributes or the attribute is not supported.
* *
*/ */
fun X500Principal.toAttributesMap(supportedAttributes: Set<ASN1ObjectIdentifier> = emptySet()): Map<ASN1ObjectIdentifier, ASN1Encodable> { fun X500Principal.toAttributesMap(supportedAttributes: Set<ASN1ObjectIdentifier> = emptySet()): Map<ASN1ObjectIdentifier, String> {
val x500Name = this.toX500Name() val x500Name = this.toX500Name()
val attrsMap: Map<ASN1ObjectIdentifier, ASN1Encodable> = x500Name.rdNs val attrsMap: Map<ASN1ObjectIdentifier, String> = x500Name.rdNs
.flatMap { it.typesAndValues.asList() } .flatMap { it.typesAndValues.asList() }
.groupBy(AttributeTypeAndValue::getType, AttributeTypeAndValue::getValue) .groupBy(AttributeTypeAndValue::getType, AttributeTypeAndValue::getValue)
.mapValues { .mapValues {
require(it.value.size == 1) { "Duplicate attribute ${it.key}" } require(it.value.size == 1) { "Duplicate attribute ${it.key}" }
it.value[0] it.value[0].toString()
} }
if (supportedAttributes.isNotEmpty()) { if (supportedAttributes.isNotEmpty()) {
(attrsMap.keys - supportedAttributes).let { unsupported -> (attrsMap.keys - supportedAttributes).let { unsupported ->

View File

@ -19,6 +19,7 @@ import java.io.IOException
import java.io.InputStream import java.io.InputStream
import java.net.* import java.net.*
import java.util.* import java.util.*
import java.util.jar.JarInputStream
/** /**
* A custom ClassLoader that knows how to load classes from a set of attachments. The attachments themselves only * A custom ClassLoader that knows how to load classes from a set of attachments. The attachments themselves only
@ -139,7 +140,7 @@ class AttachmentsClassLoader(attachments: List<Attachment>,
attachment.openAsJAR().use { jar -> attachment.openAsJAR().use { jar ->
while (true) { while (true) {
val entry = jar.nextJarEntry ?: return false val entry = jar.nextJarEntry ?: return false
if(entry.name.endsWith(".class", ignoreCase = true)) return true if (entry.name.endsWith(".class", ignoreCase = true)) return true
} }
} }
return false return false
@ -190,7 +191,7 @@ class AttachmentsClassLoader(attachments: List<Attachment>,
// attacks on externally connected systems that only consider type names, we allow people to formally // attacks on externally connected systems that only consider type names, we allow people to formally
// claim their parts of the Java package namespace via registration with the zone operator. // claim their parts of the Java package namespace via registration with the zone operator.
val classLoaderEntries = mutableMapOf<String, Attachment>() val classLoaderEntries = mutableMapOf<String, SecureHash.SHA256>()
for (attachment in attachments) { for (attachment in attachments) {
// We may have been given an attachment loaded from the database in which case, important info like // We may have been given an attachment loaded from the database in which case, important info like
// signers is already calculated. // signers is already calculated.
@ -251,21 +252,26 @@ class AttachmentsClassLoader(attachments: List<Attachment>,
// Some files don't need overlap checking because they don't affect the way the code runs. // Some files don't need overlap checking because they don't affect the way the code runs.
if (!shouldCheckForNoOverlap(path, targetPlatformVersion)) continue if (!shouldCheckForNoOverlap(path, targetPlatformVersion)) continue
// If 2 entries have the same content hash, it means the same file is present in both attachments, so that is ok. // This calculates the hash of the current entry because the JarInputStream returns only the current entry.
if (path in classLoaderEntries.keys) { fun entryHash() = ByteArrayOutputStream().use {
val contentHash = readAttachment(attachment, path).sha256() jar.copyTo(it)
val originalAttachment = classLoaderEntries[path]!! it.toByteArray()
val originalContentHash = readAttachment(originalAttachment, path).sha256() }.sha256()
if (contentHash == originalContentHash) {
log.debug { "Duplicate entry $path has same content hash $contentHash" } // If 2 entries are identical, it means the same file is present in both attachments, so that is ok.
continue val currentHash = entryHash()
} else { val previousFileHash = classLoaderEntries[path]
when {
previousFileHash == null -> {
log.debug { "Adding new entry for $path" }
classLoaderEntries[path] = currentHash
}
currentHash == previousFileHash -> log.debug { "Duplicate entry $path has same content hash $currentHash" }
else -> {
log.debug { "Content hash differs for $path" } log.debug { "Content hash differs for $path" }
throw OverlappingAttachmentsException(sampleTxId, path) throw OverlappingAttachmentsException(sampleTxId, path)
} }
} }
log.debug { "Adding new entry for $path" }
classLoaderEntries[path] = attachment
} }
} }
log.debug { "${classLoaderEntries.size} classloaded entries for $attachment" } log.debug { "${classLoaderEntries.size} classloaded entries for $attachment" }

View File

@ -1,6 +1,6 @@
package net.corda.core.crypto package net.corda.core.crypto
import org.apache.commons.lang.ArrayUtils.EMPTY_BYTE_ARRAY import org.apache.commons.lang3.ArrayUtils.EMPTY_BYTE_ARRAY
import org.junit.Test import org.junit.Test
import java.math.BigInteger import java.math.BigInteger
import java.util.* import java.util.*

View File

@ -15,7 +15,7 @@ import net.i2p.crypto.eddsa.math.GroupElement
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec
import org.apache.commons.lang.ArrayUtils.EMPTY_BYTE_ARRAY import org.apache.commons.lang3.ArrayUtils.EMPTY_BYTE_ARRAY
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo import org.bouncycastle.asn1.pkcs.PrivateKeyInfo
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey

View File

@ -2,7 +2,7 @@ package net.corda.core.flows
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import com.natpryce.hamkrest.* import com.natpryce.hamkrest.*
import com.natpryce.hamkrest.assertion.assert import com.natpryce.hamkrest.assertion.assertThat
import net.corda.core.contracts.Attachment import net.corda.core.contracts.Attachment
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.flows.mixins.WithMockNet import net.corda.core.flows.mixins.WithMockNet
@ -48,18 +48,18 @@ class AttachmentTests : WithMockNet {
val id = aliceNode.importAttachment(fakeAttachment("file1.txt", "Some useful content")) val id = aliceNode.importAttachment(fakeAttachment("file1.txt", "Some useful content"))
// Get node one to run a flow to fetch it and insert it. // Get node one to run a flow to fetch it and insert it.
assert.that( assertThat(
bobNode.startAttachmentFlow(id, alice), bobNode.startAttachmentFlow(id, alice),
willReturn(noAttachments())) willReturn(noAttachments()))
// Verify it was inserted into node one's store. // Verify it was inserted into node one's store.
val attachment = bobNode.getAttachmentWithId(id) val attachment = bobNode.getAttachmentWithId(id)
assert.that(attachment, hashesTo(id)) assertThat(attachment, hashesTo(id))
// Shut down node zero and ensure node one can still resolve the attachment. // Shut down node zero and ensure node one can still resolve the attachment.
aliceNode.dispose() aliceNode.dispose()
assert.that( assertThat(
bobNode.startAttachmentFlow(id, alice), bobNode.startAttachmentFlow(id, alice),
willReturn(soleAttachment(attachment))) willReturn(soleAttachment(attachment)))
} }
@ -69,7 +69,7 @@ class AttachmentTests : WithMockNet {
val hash: SecureHash = SecureHash.randomSHA256() val hash: SecureHash = SecureHash.randomSHA256()
// Get node one to fetch a non-existent attachment. // Get node one to fetch a non-existent attachment.
assert.that( assertThat(
bobNode.startAttachmentFlow(hash, alice), bobNode.startAttachmentFlow(hash, alice),
willThrow(withRequestedHash(hash))) willThrow(withRequestedHash(hash)))
} }
@ -97,7 +97,7 @@ class AttachmentTests : WithMockNet {
badAliceNode.updateAttachment(corruptAttachment) badAliceNode.updateAttachment(corruptAttachment)
// Get n1 to fetch the attachment. Should receive corrupted bytes. // Get n1 to fetch the attachment. Should receive corrupted bytes.
assert.that( assertThat(
bobNode.startAttachmentFlow(id, badAlice), bobNode.startAttachmentFlow(id, badAlice),
willThrow<FetchDataFlow.DownloadedVsRequestedDataMismatch>() willThrow<FetchDataFlow.DownloadedVsRequestedDataMismatch>()
) )

View File

@ -1,7 +1,7 @@
package net.corda.core.flows package net.corda.core.flows
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import com.natpryce.hamkrest.assertion.assert import com.natpryce.hamkrest.assertion.assertThat
import net.corda.core.contracts.Command import net.corda.core.contracts.Command
import net.corda.core.contracts.StateAndContract import net.corda.core.contracts.StateAndContract
import net.corda.core.contracts.requireThat import net.corda.core.contracts.requireThat
@ -55,7 +55,7 @@ class CollectSignaturesFlowTests : WithContracts {
val bConfidentialIdentity = bobNode.createConfidentialIdentity(bob) val bConfidentialIdentity = bobNode.createConfidentialIdentity(bob)
aliceNode.verifyAndRegister(bConfidentialIdentity) aliceNode.verifyAndRegister(bConfidentialIdentity)
assert.that( assertThat(
aliceNode.startTestFlow(alice, bConfidentialIdentity.party, charlie), aliceNode.startTestFlow(alice, bConfidentialIdentity.party, charlie),
willReturn(requiredSignatures(3)) willReturn(requiredSignatures(3))
) )
@ -113,7 +113,7 @@ class CollectSignaturesFlowTests : WithContracts {
fun `no need to collect any signatures`() { fun `no need to collect any signatures`() {
val ptx = aliceNode.signDummyContract(alice.ref(1)) val ptx = aliceNode.signDummyContract(alice.ref(1))
assert.that( assertThat(
aliceNode.collectSignatures(ptx), aliceNode.collectSignatures(ptx),
willReturn(requiredSignatures(1)) willReturn(requiredSignatures(1))
) )
@ -123,7 +123,7 @@ class CollectSignaturesFlowTests : WithContracts {
fun `fails when not signed by initiator`() { fun `fails when not signed by initiator`() {
val ptx = miniCorpServices.signDummyContract(alice.ref(1)) val ptx = miniCorpServices.signDummyContract(alice.ref(1))
assert.that( assertThat(
aliceNode.collectSignatures(ptx), aliceNode.collectSignatures(ptx),
willThrow(errorMessage("The Initiator of CollectSignaturesFlow must have signed the transaction."))) willThrow(errorMessage("The Initiator of CollectSignaturesFlow must have signed the transaction.")))
} }
@ -137,7 +137,7 @@ class CollectSignaturesFlowTests : WithContracts {
bob.ref(3)) bob.ref(3))
val signedByBoth = bobNode.addSignatureTo(signedByA) val signedByBoth = bobNode.addSignatureTo(signedByA)
assert.that( assertThat(
aliceNode.collectSignatures(signedByBoth), aliceNode.collectSignatures(signedByBoth),
willReturn(requiredSignatures(2)) willReturn(requiredSignatures(2))
) )

View File

@ -2,7 +2,7 @@ package net.corda.core.flows
import com.natpryce.hamkrest.and import com.natpryce.hamkrest.and
import com.natpryce.hamkrest.anything import com.natpryce.hamkrest.anything
import com.natpryce.hamkrest.assertion.assert import com.natpryce.hamkrest.assertion.assertThat
import com.natpryce.hamkrest.has import com.natpryce.hamkrest.has
import com.natpryce.hamkrest.isA import com.natpryce.hamkrest.isA
import net.corda.core.CordaRuntimeException import net.corda.core.CordaRuntimeException
@ -52,30 +52,30 @@ class ContractUpgradeFlowRPCTest : WithContracts, WithFinality {
// Create, sign and finalise dummy contract. // Create, sign and finalise dummy contract.
val signedByA = aliceNode.signDummyContract(alice.ref(1), 0, bob.ref(1)) val signedByA = aliceNode.signDummyContract(alice.ref(1), 0, bob.ref(1))
val stx = bobNode.addSignatureTo(signedByA) val stx = bobNode.addSignatureTo(signedByA)
assert.that(rpcA.finalise(stx, bob), willReturn()) assertThat(rpcA.finalise(stx, bob), willReturn())
val atx = aliceNode.getValidatedTransaction(stx) val atx = aliceNode.getValidatedTransaction(stx)
val btx = bobNode.getValidatedTransaction(stx) val btx = bobNode.getValidatedTransaction(stx)
// Cannot upgrade contract without prior authorisation from counterparty // Cannot upgrade contract without prior authorisation from counterparty
assert.that( assertThat(
rpcA.initiateDummyContractUpgrade(atx), rpcA.initiateDummyContractUpgrade(atx),
willThrow<CordaRuntimeException>()) willThrow<CordaRuntimeException>())
// Party B authorises the contract state upgrade, and immediately deauthorises the same. // Party B authorises the contract state upgrade, and immediately deauthorises the same.
assert.that(rpcB.authoriseDummyContractUpgrade(btx), willReturn()) assertThat(rpcB.authoriseDummyContractUpgrade(btx), willReturn())
assert.that(rpcB.deauthoriseContractUpgrade(btx), willReturn()) assertThat(rpcB.deauthoriseContractUpgrade(btx), willReturn())
// Cannot upgrade contract if counterparty has deauthorised a previously-given authority // Cannot upgrade contract if counterparty has deauthorised a previously-given authority
assert.that( assertThat(
rpcA.initiateDummyContractUpgrade(atx), rpcA.initiateDummyContractUpgrade(atx),
willThrow<CordaRuntimeException>()) willThrow<CordaRuntimeException>())
// Party B authorise the contract state upgrade. // Party B authorise the contract state upgrade.
assert.that(rpcB.authoriseDummyContractUpgrade(btx), willReturn()) assertThat(rpcB.authoriseDummyContractUpgrade(btx), willReturn())
// Party A initiates contract upgrade flow, expected to succeed this time. // Party A initiates contract upgrade flow, expected to succeed this time.
assert.that( assertThat(
rpcA.initiateDummyContractUpgrade(atx), rpcA.initiateDummyContractUpgrade(atx),
willReturn( willReturn(
aliceNode.hasDummyContractUpgradeTransaction() aliceNode.hasDummyContractUpgradeTransaction()

View File

@ -1,7 +1,7 @@
package net.corda.core.flows package net.corda.core.flows
import com.natpryce.hamkrest.* import com.natpryce.hamkrest.*
import com.natpryce.hamkrest.assertion.assert import com.natpryce.hamkrest.assertion.assertThat
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.flows.mixins.WithContracts import net.corda.core.flows.mixins.WithContracts
import net.corda.core.flows.mixins.WithFinality import net.corda.core.flows.mixins.WithFinality
@ -59,24 +59,24 @@ class ContractUpgradeFlowTest : WithContracts, WithFinality {
val bobTx = bobNode.getValidatedTransaction(stx) val bobTx = bobNode.getValidatedTransaction(stx)
// The request is expected to be rejected because party B hasn't authorised the upgrade yet. // The request is expected to be rejected because party B hasn't authorised the upgrade yet.
assert.that( assertThat(
aliceNode.initiateContractUpgrade(aliceTx, DummyContractV2::class), aliceNode.initiateContractUpgrade(aliceTx, DummyContractV2::class),
willThrow<UnexpectedFlowEndException>()) willThrow<UnexpectedFlowEndException>())
// Party B authorises the contract state upgrade, and immediately de-authorises the same. // Party B authorises the contract state upgrade, and immediately de-authorises the same.
assert.that(bobNode.authoriseContractUpgrade(bobTx, DummyContractV2::class), willReturn()) assertThat(bobNode.authoriseContractUpgrade(bobTx, DummyContractV2::class), willReturn())
assert.that(bobNode.deauthoriseContractUpgrade(bobTx), willReturn()) assertThat(bobNode.deauthoriseContractUpgrade(bobTx), willReturn())
// The request is expected to be rejected because party B has subsequently de-authorised a previously authorised upgrade. // The request is expected to be rejected because party B has subsequently de-authorised a previously authorised upgrade.
assert.that( assertThat(
aliceNode.initiateContractUpgrade(aliceTx, DummyContractV2::class), aliceNode.initiateContractUpgrade(aliceTx, DummyContractV2::class),
willThrow<UnexpectedFlowEndException>()) willThrow<UnexpectedFlowEndException>())
// Party B authorises the contract state upgrade. // Party B authorises the contract state upgrade.
assert.that(bobNode.authoriseContractUpgrade(bobTx, DummyContractV2::class), willReturn()) assertThat(bobNode.authoriseContractUpgrade(bobTx, DummyContractV2::class), willReturn())
// Party A initiates contract upgrade flow, expected to succeed this time. // Party A initiates contract upgrade flow, expected to succeed this time.
assert.that( assertThat(
aliceNode.initiateContractUpgrade(aliceTx, DummyContractV2::class), aliceNode.initiateContractUpgrade(aliceTx, DummyContractV2::class),
willReturn( willReturn(
aliceNode.hasContractUpgradeTransaction<DummyContract.State, DummyContractV2.State>() aliceNode.hasContractUpgradeTransaction<DummyContract.State, DummyContractV2.State>()
@ -86,10 +86,10 @@ class ContractUpgradeFlowTest : WithContracts, WithFinality {
// We now test that the upgraded state can be upgraded further, to V3. // We now test that the upgraded state can be upgraded further, to V3.
// Party B authorises the contract state upgrade. // Party B authorises the contract state upgrade.
assert.that(bobNode.authoriseContractUpgrade(upgradedState, DummyContractV3::class), willReturn()) assertThat(bobNode.authoriseContractUpgrade(upgradedState, DummyContractV3::class), willReturn())
// Party A initiates contract upgrade flow which is expected to succeed. // Party A initiates contract upgrade flow which is expected to succeed.
assert.that( assertThat(
aliceNode.initiateContractUpgrade(upgradedState, DummyContractV3::class), aliceNode.initiateContractUpgrade(upgradedState, DummyContractV3::class),
willReturn( willReturn(
aliceNode.hasContractUpgradeTransaction<DummyContractV2.State, DummyContractV3.State>() aliceNode.hasContractUpgradeTransaction<DummyContractV2.State, DummyContractV3.State>()
@ -125,14 +125,14 @@ class ContractUpgradeFlowTest : WithContracts, WithFinality {
val stateAndRef = cashFlowResult.stx.tx.outRef<Cash.State>(0) val stateAndRef = cashFlowResult.stx.tx.outRef<Cash.State>(0)
// The un-upgraded state is Cash.State // The un-upgraded state is Cash.State
assert.that(aliceNode.getBaseStateFromVault(), hasContractState(isA<Cash.State>(anything))) assertThat(aliceNode.getBaseStateFromVault(), hasContractState(isA<Cash.State>(anything)))
// Starts contract upgrade flow. // Starts contract upgrade flow.
assert.that(aliceNode.initiateContractUpgrade(stateAndRef, CashV2::class), willReturn()) assertThat(aliceNode.initiateContractUpgrade(stateAndRef, CashV2::class), willReturn())
// Get contract state from the vault. // Get contract state from the vault.
val upgradedState = aliceNode.getCashStateFromVault() val upgradedState = aliceNode.getCashStateFromVault()
assert.that(upgradedState, assertThat(upgradedState,
hasIssuedAmount(Amount(1000000, USD) `issued by` (alice.ref(1))) hasIssuedAmount(Amount(1000000, USD) `issued by` (alice.ref(1)))
and belongsTo(anonymisedRecipient)) and belongsTo(anonymisedRecipient))
@ -146,8 +146,8 @@ class ContractUpgradeFlowTest : WithContracts, WithFinality {
addCommand(CashV2.Move(), alice.owningKey) addCommand(CashV2.Move(), alice.owningKey)
} }
assert.that(aliceNode.finalise(spendUpgradedTx), willReturn()) assertThat(aliceNode.finalise(spendUpgradedTx), willReturn())
assert.that(aliceNode.getCashStateFromVault(), hasContractState(equalTo(movedState))) assertThat(aliceNode.getCashStateFromVault(), hasContractState(equalTo(movedState)))
} }
class CashV2 : UpgradedContractWithLegacyConstraint<Cash.State, CashV2.State> { class CashV2 : UpgradedContractWithLegacyConstraint<Cash.State, CashV2.State> {

View File

@ -1,7 +1,7 @@
package net.corda.core.flows package net.corda.core.flows
import com.natpryce.hamkrest.and import com.natpryce.hamkrest.and
import com.natpryce.hamkrest.assertion.assert import com.natpryce.hamkrest.assertion.assertThat
import net.corda.core.flows.mixins.WithFinality import net.corda.core.flows.mixins.WithFinality
import net.corda.core.flows.mixins.WithFinality.FinalityInvoker import net.corda.core.flows.mixins.WithFinality.FinalityInvoker
import net.corda.core.identity.Party import net.corda.core.identity.Party
@ -17,7 +17,6 @@ import net.corda.testing.internal.matchers.flow.willReturn
import net.corda.testing.internal.matchers.flow.willThrow import net.corda.testing.internal.matchers.flow.willThrow
import net.corda.testing.node.internal.* import net.corda.testing.node.internal.*
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatIllegalArgumentException
import org.junit.After import org.junit.After
import org.junit.Test import org.junit.Test
@ -40,7 +39,7 @@ class FinalityFlowTests : WithFinality {
val bob = createBob() val bob = createBob()
val stx = aliceNode.issuesCashTo(bob) val stx = aliceNode.issuesCashTo(bob)
assert.that( assertThat(
aliceNode.finalise(stx, bob.info.singleIdentity()), aliceNode.finalise(stx, bob.info.singleIdentity()),
willReturn( willReturn(
requiredSignatures(1) requiredSignatures(1)
@ -52,7 +51,7 @@ class FinalityFlowTests : WithFinality {
// Charlie isn't part of this network, so node A won't recognise them // Charlie isn't part of this network, so node A won't recognise them
val stx = aliceNode.issuesCashTo(CHARLIE) val stx = aliceNode.issuesCashTo(CHARLIE)
assert.that( assertThat(
aliceNode.finalise(stx), aliceNode.finalise(stx),
willThrow<IllegalArgumentException>()) willThrow<IllegalArgumentException>())
} }

View File

@ -1,7 +1,7 @@
package net.corda.core.flows package net.corda.core.flows
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import com.natpryce.hamkrest.assertion.assert import com.natpryce.hamkrest.assertion.assertThat
import net.corda.core.flows.mixins.WithMockNet import net.corda.core.flows.mixins.WithMockNet
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.utilities.UntrustworthyData import net.corda.core.utilities.UntrustworthyData
@ -10,11 +10,10 @@ import net.corda.testing.core.singleIdentity
import net.corda.testing.internal.matchers.flow.willReturn import net.corda.testing.internal.matchers.flow.willReturn
import net.corda.testing.node.internal.InternalMockNetwork import net.corda.testing.node.internal.InternalMockNetwork
import net.corda.testing.node.internal.TestStartedNode import net.corda.testing.node.internal.TestStartedNode
import org.assertj.core.api.Assertions.assertThat
import org.junit.AfterClass import org.junit.AfterClass
import org.junit.Test import org.junit.Test
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.test.assertEquals
class ReceiveMultipleFlowTests : WithMockNet { class ReceiveMultipleFlowTests : WithMockNet {
companion object { companion object {
@ -52,13 +51,13 @@ class ReceiveMultipleFlowTests : WithMockNet {
// this is a closure, meaning you can access variables outside its scope e.g., `answer`. // this is a closure, meaning you can access variables outside its scope e.g., `answer`.
val receivedMessage = session.receive<String>().unwrap { it } val receivedMessage = session.receive<String>().unwrap { it }
logger.info("Got message from counterParty: $receivedMessage.") logger.info("Got message from counterParty: $receivedMessage.")
assertThat(receivedMessage).isEqualTo(message) assertEquals(message, receivedMessage)
session.send(answer) session.send(answer)
} }
} as FlowLogic<Unit> } as FlowLogic<Unit>
} }
assert.that( assertThat(
nodes[0].startFlowAndRunNetwork(initiatingFlow), nodes[0].startFlowAndRunNetwork(initiatingFlow),
willReturn(answer as Any)) willReturn(answer as Any))
} }
@ -70,7 +69,7 @@ class ReceiveMultipleFlowTests : WithMockNet {
val stringValue = "Thriller" val stringValue = "Thriller"
nodes[2].registerAnswer(AlgorithmDefinition::class, stringValue) nodes[2].registerAnswer(AlgorithmDefinition::class, stringValue)
assert.that( assertThat(
nodes[0].startFlowAndRunNetwork(ParallelAlgorithmMap(nodes[1].info.singleIdentity(), nodes[2].info.singleIdentity())), nodes[0].startFlowAndRunNetwork(ParallelAlgorithmMap(nodes[1].info.singleIdentity(), nodes[2].info.singleIdentity())),
willReturn(doubleValue * stringValue.length)) willReturn(doubleValue * stringValue.length))
} }
@ -82,7 +81,7 @@ class ReceiveMultipleFlowTests : WithMockNet {
val value2 = 6.0 val value2 = 6.0
nodes[2].registerAnswer(ParallelAlgorithmList::class, value2) nodes[2].registerAnswer(ParallelAlgorithmList::class, value2)
assert.that( assertThat(
nodes[0].startFlowAndRunNetwork(ParallelAlgorithmList(nodes[1].info.singleIdentity(), nodes[2].info.singleIdentity())), nodes[0].startFlowAndRunNetwork(ParallelAlgorithmList(nodes[1].info.singleIdentity(), nodes[2].info.singleIdentity())),
willReturn(listOf(value1, value2))) willReturn(listOf(value1, value2)))
} }

View File

@ -107,8 +107,8 @@ class AttachmentsClassLoaderTests {
@Test @Test
fun `Test valid overlapping file condition`() { fun `Test valid overlapping file condition`() {
val att1 = importAttachment(fakeAttachment("file1.txt", "same data").inputStream(), "app", "file1.jar") val att1 = importAttachment(fakeAttachment("file1.txt", "same data", "file2.txt", "same other data" ).inputStream(), "app", "file1.jar")
val att2 = importAttachment(fakeAttachment("file1.txt", "same data").inputStream(), "app", "file2.jar") val att2 = importAttachment(fakeAttachment("file1.txt", "same data", "file3.txt", "same totally different").inputStream(), "app", "file2.jar")
val cl = make(arrayOf(att1, att2).map { storage.openAttachment(it)!! }) val cl = make(arrayOf(att1, att2).map { storage.openAttachment(it)!! })
val txt = IOUtils.toString(cl.getResourceAsStream("file1.txt"), Charsets.UTF_8.name()) val txt = IOUtils.toString(cl.getResourceAsStream("file1.txt"), Charsets.UTF_8.name())

View File

@ -1,7 +1,7 @@
package net.corda.core.utilities package net.corda.core.utilities
import net.corda.core.crypto.AddressFormatException import net.corda.core.crypto.AddressFormatException
import org.apache.commons.lang.ArrayUtils.EMPTY_BYTE_ARRAY import org.apache.commons.lang3.ArrayUtils.EMPTY_BYTE_ARRAY
import org.junit.Test import org.junit.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.fail import kotlin.test.fail

13
djvm/.gitignore vendored
View File

@ -1,13 +0,0 @@
# DJVM-specific files
**/tmp/
*.log
*.log.gz
# IntelliJ
*.iml
*.ipr
*.iws
.idea/
**/out/

View File

@ -1,120 +0,0 @@
buildscript {
ext {
corda_djvm_version = '5.0-SNAPSHOT'
artifactory_contextUrl = 'https://ci-artifactory.corda.r3cev.com/artifactory'
}
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
plugins {
id 'net.corda.plugins.publish-utils' version '4.0.42' apply false
id 'com.github.johnrengelman.shadow' version '5.0.0' apply false
id 'com.jfrog.artifactory' version '4.7.3' apply false
id 'com.jfrog.bintray' version '1.4' apply false
id 'com.gradle.build-scan' version '2.2.1'
}
import static org.gradle.api.JavaVersion.*
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
subprojects {
group 'net.corda'
version corda_djvm_version
repositories {
mavenCentral()
jcenter()
}
tasks.withType(JavaCompile) {
sourceCompatibility = VERSION_1_8
targetCompatibility = VERSION_1_8
options.encoding = 'UTF-8'
}
tasks.withType(KotlinCompile) {
kotlinOptions {
languageVersion = '1.2'
apiVersion = '1.2'
jvmTarget = VERSION_1_8
javaParameters = true // Useful for reflection.
freeCompilerArgs = ['-Xjvm-default=enable']
}
}
tasks.withType(Jar) { task ->
manifest {
attributes('Corda-Vendor': 'Corda Open Source')
attributes('Automatic-Module-Name': "net.corda.${task.project.name.replaceAll('-', '.')}")
}
}
tasks.withType(Test) {
// Prevent the project from creating temporary files outside of the build directory.
systemProperty 'java.io.tmpdir', buildDir.absolutePath
}
}
apply plugin: 'net.corda.plugins.publish-utils'
apply plugin: 'com.jfrog.artifactory'
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 = [
'corda-djvm',
'corda-djvm-cli'
]
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 = artifactory_contextUrl
repository {
repoKey = 'corda-dev'
username = System.getenv('CORDA_ARTIFACTORY_USERNAME')
password = System.getenv('CORDA_ARTIFACTORY_PASSWORD')
}
defaults {
// The root project has applied 'publish-utils' but has nothing to publish.
if (project != rootProject) {
publications(project.extensions.publish.name())
}
}
}
}
wrapper {
gradleVersion = "5.2.1"
distributionType = Wrapper.DistributionType.ALL
}
buildScan {
termsOfServiceUrl = 'https://gradle.com/terms-of-service'
termsOfServiceAgree = 'yes'
}

View File

@ -1,87 +0,0 @@
plugins {
id 'org.jetbrains.kotlin.jvm'
id 'com.github.johnrengelman.shadow'
id 'net.corda.plugins.publish-utils'
id 'com.jfrog.artifactory'
id 'idea'
}
description 'Corda deterministic JVM sandbox'
repositories {
maven {
url "$artifactory_contextUrl/corda-dev"
}
}
configurations {
testImplementation.extendsFrom shadow
jdkRt.resolutionStrategy {
// Always check the repository for a newer SNAPSHOT.
cacheChangingModulesFor 0, 'seconds'
}
}
dependencies {
shadow "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
shadow "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
shadow "org.slf4j:slf4j-api:$slf4j_version"
// ASM: byte code manipulation library
implementation "org.ow2.asm:asm:$asm_version"
implementation "org.ow2.asm:asm-commons:$asm_version"
// ClassGraph: classpath scanning
shadow "io.github.classgraph:classgraph:$class_graph_version"
// Test utilities
testImplementation "junit:junit:$junit_version"
testImplementation "org.assertj:assertj-core:$assertj_version"
testImplementation "org.apache.logging.log4j:log4j-slf4j-impl:$log4j_version"
jdkRt "net.corda:deterministic-rt:latest.integration"
}
jar.enabled = false
shadowJar {
baseName 'corda-djvm'
classifier ''
relocate 'org.objectweb.asm', 'djvm.org.objectweb.asm'
// These particular classes are only needed to "bootstrap"
// the compilation of the other sandbox classes. At runtime,
// we will generate better versions from deterministic-rt.jar.
exclude 'sandbox/java/lang/Appendable.class'
exclude 'sandbox/java/lang/CharSequence.class'
exclude 'sandbox/java/lang/Character\$Subset.class'
exclude 'sandbox/java/lang/Character\$Unicode*.class'
exclude 'sandbox/java/lang/Comparable.class'
exclude 'sandbox/java/lang/Enum.class'
exclude 'sandbox/java/lang/Iterable.class'
exclude 'sandbox/java/lang/StackTraceElement.class'
exclude 'sandbox/java/lang/StringBuffer.class'
exclude 'sandbox/java/lang/StringBuilder.class'
exclude 'sandbox/java/nio/**'
exclude 'sandbox/java/util/**'
}
assemble.dependsOn shadowJar
tasks.withType(Test) {
systemProperty 'deterministic-rt.path', configurations.jdkRt.asPath
}
artifacts {
publish shadowJar
}
publish {
dependenciesFrom configurations.shadow
name shadowJar.baseName
}
idea {
module {
downloadJavadoc = true
downloadSources = true
}
}

View File

@ -1,64 +0,0 @@
plugins {
id 'org.jetbrains.kotlin.jvm'
id 'com.github.johnrengelman.shadow'
id 'net.corda.plugins.publish-utils'
id 'com.jfrog.artifactory'
}
description 'Corda deterministic JVM sandbox command-line tool'
ext {
djvmName = 'corda-djvm-cli'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation "org.jetbrains.kotlin:kotlin-reflect"
implementation "org.apache.logging.log4j:log4j-slf4j-impl:$log4j_version"
implementation "org.apache.logging.log4j:log4j-core:$log4j_version"
implementation "com.jcabi:jcabi-manifests:$jcabi_manifests_version"
implementation "info.picocli:picocli:$picocli_version"
implementation project(path: ':djvm', configuration: 'shadow')
}
jar.enabled = false
shadowJar {
baseName djvmName
classifier ''
manifest {
attributes(
'Automatic-Module-Name': 'net.corda.djvm.cli',
'Main-Class': 'net.corda.djvm.tools.cli.Program',
'Build-Date': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
'Class-Path': 'tmp/'
)
}
}
task shadowZip(type: Zip) {
archiveBaseName = djvmName
archiveClassifier = ''
from(shadowJar) {
rename "$djvmName-(.*).jar", "${djvmName}.jar"
}
from('src/shell/') {
fileMode = 0755
}
zip64 true
}
assemble.dependsOn shadowZip
artifacts {
publish shadowZip
}
publish {
dependenciesFrom configurations.shadow
publishSources = false
publishJavadoc = false
name shadowZip.baseName
}

View File

@ -1,39 +0,0 @@
package net.corda.djvm.tools.cli
import picocli.CommandLine.Command
import picocli.CommandLine.Parameters
import java.nio.file.Path
@Command(
name = "build",
description = ["Build one or more Java source files, each implementing the sandbox runnable interface " +
"required for execution in the deterministic sandbox."]
)
@Suppress("KDocMissingDocumentation")
class BuildCommand : CommandBase() {
@Parameters
var files: Array<Path> = emptyArray()
override fun validateArguments() = files.isNotEmpty()
override fun handleCommand(): Boolean {
val codePath = createCodePath()
val files = files.getFileNames { codePath.resolve(it) }
printVerbose("Compiling ${files.joinToString(", ")}...")
ProcessBuilder("javac", "-cp", "tmp:$jarPath", *files).apply {
inheritIO()
environment().putAll(System.getenv())
start().apply {
waitFor()
return (exitValue() == 0).apply {
if (this) {
printInfo("Build succeeded")
}
}
}
}
return true
}
}

View File

@ -1,34 +0,0 @@
package net.corda.djvm.tools.cli
import net.corda.djvm.source.ClassSource
import picocli.CommandLine.Command
import picocli.CommandLine.Parameters
@Command(
name = "check",
description = ["Statically validate that a class or set of classes (and their dependencies) do not violate any " +
"constraints posed by the deterministic sandbox environment."]
)
@Suppress("KDocMissingDocumentation")
class CheckCommand : ClassCommand() {
override val filters: Array<String>
get() = classes
@Parameters(description = ["The partial or fully qualified names of the Java classes to analyse and validate."])
var classes: Array<String> = emptyArray()
override fun printSuccess(classes: List<Class<*>>) {
for (clazz in classes.sortedBy { it.name }) {
printVerbose("Class ${clazz.name} validated")
}
printVerbose()
}
override fun processClasses(classes: List<Class<*>>) {
val sources = classes.map { ClassSource.fromClassName(it.name) }
val summary = executor.validate(*sources.toTypedArray())
printMessages(summary.messages, summary.classOrigins)
}
}

View File

@ -1,204 +0,0 @@
package net.corda.djvm.tools.cli
import net.corda.djvm.SandboxConfiguration
import net.corda.djvm.analysis.AnalysisConfiguration
import net.corda.djvm.analysis.Whitelist
import net.corda.djvm.execution.*
import net.corda.djvm.references.ClassModule
import net.corda.djvm.source.ClassSource
import net.corda.djvm.source.SourceClassLoader
import net.corda.djvm.utilities.Discovery
import djvm.org.objectweb.asm.ClassReader
import picocli.CommandLine.Option
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
@Suppress("KDocMissingDocumentation", "MemberVisibilityCanBePrivate")
abstract class ClassCommand : CommandBase() {
@Option(
names = ["-p", "--profile"],
description = ["The execution profile to use (DEFAULT, UNLIMITED, DISABLE_BRANCHING or DISABLE_THROWS)."]
)
var profile: ExecutionProfile = ExecutionProfile.DEFAULT
@Option(names = ["--ignore-rules"], description = ["Disable all rules pertaining to the sandbox."])
var ignoreRules: Boolean = false
@Option(names = ["--ignore-emitters"], description = ["Disable all emitters defined for the sandbox."])
var ignoreEmitters: Boolean = false
@Option(names = ["--ignore-definition-providers"], description = ["Disable all definition providers."])
var ignoreDefinitionProviders: Boolean = false
@Option(names = ["-c", "--classpath"], description = ["Additions to the default class path."], split = ":")
var classPath: Array<Path> = emptyArray()
@Option(names = ["--disable-tracing"], description = ["Disable tracing in the sandbox."])
var disableTracing: Boolean = false
@Option(names = ["--analyze-annotations"], description = ["Analyze all annotations even if they are not " +
"explicitly referenced."])
var analyzeAnnotations: Boolean = false
@Option(
names = ["--prefix-filters"],
description = ["Only record messages matching one of the provided prefixes."],
split = ":"
)
var prefixFilters: Array<String> = emptyArray()
abstract val filters: Array<String>
private val classModule = ClassModule()
private lateinit var classLoader: ClassLoader
protected var executor = SandboxExecutor<Any, Any>(SandboxConfiguration.DEFAULT)
abstract fun processClasses(classes: List<Class<*>>)
open fun printSuccess(classes: List<Class<*>>) {}
override fun validateArguments() = filters.isNotEmpty()
override fun handleCommand(): Boolean {
val configuration = getConfiguration(Whitelist.MINIMAL)
classLoader = SourceClassLoader(getClasspath(), configuration.analysisConfiguration.classResolver)
createExecutor(configuration)
val classes = discoverClasses(filters).onEmpty {
throw Exception("Could not find any classes matching ${filters.joinToString(" ")} on the " +
"system class path")
}
return try {
processClasses(classes)
printSuccess(classes)
true
} catch (exception: Throwable) {
printException(exception)
if (exception is SandboxException) {
printCosts(exception.executionSummary.costs)
}
false
}
}
protected fun printCosts(costs: CostSummary) {
if (disableTracing) {
return
}
printInfo("Runtime Cost Summary:")
printInfo(" - allocations = @|yellow ${costs.allocations}|@")
printInfo(" - invocations = @|yellow ${costs.invocations}|@")
printInfo(" - jumps = @|yellow ${costs.jumps}|@")
printInfo(" - throws = @|yellow ${costs.throws}|@")
printInfo()
}
private fun discoverClasses(filters: Array<String>): List<Class<*>> {
return findDiscoverableRunnables(filters) + findReferencedClasses(filters) + findClassesInJars(filters)
}
private fun findDiscoverableRunnables(filters: Array<String>): List<Class<*>> {
val classes = find<java.util.function.Function<*,*>>()
val applicableFilters = filters
.filter { !isJarFile(it) && !isFullClassName(it) }
val filteredClasses = applicableFilters
.flatMap { filter ->
classes.filter { clazz ->
clazz.name.contains(filter, true)
}
}
if (applicableFilters.isNotEmpty() && filteredClasses.isEmpty()) {
throw Exception("Could not find any classes implementing ${java.util.function.Function::class.java.simpleName} " +
"whose name matches '${applicableFilters.joinToString(" ")}'")
}
if (applicableFilters.isNotEmpty()) {
printVerbose("Class path: $userClassPath")
printVerbose("Discovered runnables on the class path:")
for (clazz in classes) {
printVerbose(" - ${clazz.name}")
}
printVerbose()
}
return filteredClasses
}
private fun findReferencedClasses(filters: Array<String>): List<Class<*>> {
return filters.filter { !isJarFile(it) && isFullClassName(it) }.map {
val className = classModule.getFormattedClassName(it)
printVerbose("Looking up class $className...")
lookUpClass(className)
}
}
private fun findClassesInJars(filters: Array<String>): List<Class<*>> {
return filters.filter { isJarFile(it) }.flatMap { jarFile ->
mutableListOf<Class<*>>().apply {
ClassSource.fromPath(Paths.get(jarFile)).getStreamIterator().forEach {
val reader = ClassReader(it)
val className = classModule.getFormattedClassName(reader.className)
printVerbose("Looking up class $className in $jarFile...")
this.add(lookUpClass(className))
}
}
}
}
private fun lookUpClass(className: String): Class<*> {
return try {
classLoader.loadClass(className)
} catch (exception: NoClassDefFoundError) {
val reference = exception.message?.let {
"referenced class ${classModule.getFormattedClassName(it)} in "
} ?: ""
throw Exception("Unable to load ${reference}type $className (is it present on the class path?)")
} catch (exception: TypeNotPresentException) {
val reference = exception.typeName() ?: ""
throw Exception("Type $reference not present in class $className")
} catch (exception: Throwable) {
throw Exception("Unable to load type $className (is it present on the class path?)")
}
}
private fun isJarFile(filter: String) = Files.exists(Paths.get(filter)) && filter.endsWith(".jar", true)
private fun isFullClassName(filter: String) = filter.count { it == '.' } > 0
private fun getClasspath() =
classPath.toList() + filters.filter { it.endsWith(".jar", true) }.map { Paths.get(it) }
private fun getConfiguration(whitelist: Whitelist): SandboxConfiguration {
return SandboxConfiguration.of(
profile = profile,
rules = if (ignoreRules) { emptyList() } else { Discovery.find() },
emitters = ignoreEmitters.emptyListIfTrueOtherwiseNull(),
definitionProviders = if (ignoreDefinitionProviders) { emptyList() } else { Discovery.find() },
enableTracing = !disableTracing,
analysisConfiguration = AnalysisConfiguration.createRoot(
whitelist = whitelist,
minimumSeverityLevel = level,
analyzeAnnotations = analyzeAnnotations,
prefixFilters = prefixFilters.toList(),
sourceClassLoaderFactory = { classResolver, bootstrapClassLoader ->
SourceClassLoader(getClasspath(), classResolver, bootstrapClassLoader)
}
)
)
}
private fun createExecutor(configuration: SandboxConfiguration) {
executor = SandboxExecutor(configuration)
}
private fun <T> Boolean.emptyListIfTrueOtherwiseNull(): List<T>? = when (this) {
true -> emptyList()
false -> null
}
}

View File

@ -1,279 +0,0 @@
package net.corda.djvm.tools.cli
import net.corda.djvm.analysis.Whitelist
import net.corda.djvm.execution.SandboxException
import net.corda.djvm.messages.MessageCollection
import net.corda.djvm.messages.Severity
import net.corda.djvm.references.ClassReference
import net.corda.djvm.references.EntityReference
import net.corda.djvm.references.MemberReference
import net.corda.djvm.rewiring.SandboxClassLoadingException
import org.apache.logging.log4j.Level
import org.apache.logging.log4j.core.config.Configurator
import picocli.CommandLine
import picocli.CommandLine.Help.Ansi
import picocli.CommandLine.Option
import java.nio.file.Path
import java.util.concurrent.Callable
@Suppress("KDocMissingDocumentation")
abstract class CommandBase : Callable<Boolean> {
@Option(
names = ["-l", "--level"],
description = ["The minimum severity level to log (TRACE, DEBUG, INFO, WARNING or ERROR."],
converter = [SeverityConverter::class]
)
protected var level: Severity = Severity.WARNING
@Option(
names = ["-q", "--quiet"],
description = ["Only print important messages to standard output."]
)
private var quiet: Boolean = false
@Option(
names = ["-v", "--verbose"],
description = ["Enable verbose logging."]
)
private var verbose: Boolean = false
@Option(
names = ["--debug"],
description = ["Print full stack traces upon error."]
)
private var debug: Boolean = false
@Option(
names = ["--colors"],
description = ["Use colors when printing to terminal."]
)
private var useColors: Boolean = false
@Option(
names = ["--no-colors"],
description = ["Do not use colors when printing to terminal."]
)
private var useNoColors: Boolean = false
@Option(
names = ["--compact"],
description = ["Print compact errors and warnings."]
)
private var compact: Boolean = false
@Option(
names = ["--print-origins"],
description = ["Print origins for errors and warnings."]
)
private var printOrigins: Boolean = false
private val ansi: Ansi
get() = when {
useNoColors -> Ansi.OFF
useColors -> Ansi.ON
else -> Ansi.AUTO
}
class SeverityConverter : CommandLine.ITypeConverter<Severity> {
override fun convert(value: String): Severity {
return try {
when (value.toUpperCase()) {
"INFO" -> Severity.INFORMATIONAL
else -> Severity.valueOf(value.toUpperCase())
}
} catch (exception: Exception) {
val candidates = Severity.values().filter { it.name.startsWith(value, true) }
if (candidates.size == 1) {
candidates.first()
} else {
println("ERROR: Must be one of ${Severity.values().joinToString(", ") { it.name }}")
Severity.INFORMATIONAL
}
}
}
}
override fun call(): Boolean {
if (!validateArguments()) {
CommandLine.usage(this, System.err)
return false
}
if (verbose && quiet) {
printError("Error: Cannot set verbose and quiet modes at the same time")
return false
}
configureLogging()
return try {
handleCommand()
} catch (exception: Throwable) {
printException(exception)
false
}
}
private fun configureLogging() {
val logLevel = when(level) {
Severity.ERROR -> Level.ERROR
Severity.WARNING -> Level.WARN
Severity.INFORMATIONAL -> Level.INFO
Severity.DEBUG -> Level.DEBUG
Severity.TRACE -> Level.TRACE
}
Configurator.setRootLevel(logLevel)
}
protected fun printException(exception: Throwable) = when (exception) {
is SandboxClassLoadingException -> {
printMessages(exception.messages, exception.classOrigins)
printError()
}
is SandboxException -> {
val cause = exception.cause
when (cause) {
is SandboxClassLoadingException -> {
printMessages(cause.messages, cause.classOrigins)
printError()
}
else -> {
if (debug) {
exception.exception.printStackTrace(System.err)
} else {
printError("Error: ${errorMessage(exception.exception)}")
}
printError()
}
}
}
else -> {
if (debug) {
exception.printStackTrace(System.err)
} else {
printError("Error: ${errorMessage(exception)}")
printError()
}
}
}
private fun errorMessage(exception: Throwable): String {
return when (exception) {
is StackOverflowError -> "Stack overflow"
is OutOfMemoryError -> "Out of memory"
is ThreadDeath -> "Thread death"
else -> {
val message = exception.message
when {
message.isNullOrBlank() -> exception.javaClass.simpleName
else -> message!!
}
}
}
}
protected fun printMessages(messages: MessageCollection, origins: Map<String, Set<EntityReference>> = emptyMap()) {
val sortedMessages = messages.sorted()
val errorCount = messages.errorCount.countOf("error")
val warningCount = messages.warningCount.countOf("warning")
printInfo("Found $errorCount and $warningCount")
if (!compact) {
printInfo()
}
var first = true
for (message in sortedMessages) {
val severityColor = message.severity.color ?: "blue"
val location = message.location.format().let {
when {
it.isNotBlank() -> "in $it: "
else -> it
}
}
if (compact) {
printError(" - @|$severityColor ${message.severity}|@ $location${message.message}.")
} else {
if (!first) {
printError()
}
printError(" - @|$severityColor ${message.severity}|@ $location\n ${message.message}.")
}
if (printOrigins) {
val classOrigins = origins[message.location.className.replace("/", ".")] ?: emptySet()
for (classOrigin in classOrigins.groupBy({ it.className }, { it })) {
val count = classOrigin.value.count()
val reference = when (count) {
1 -> classOrigin.value.first()
else -> ClassReference(classOrigin.value.first().className)
}
when (reference) {
is ClassReference ->
printError(" - Reference from ${reference.className}")
is MemberReference ->
printError(" - Reference from ${reference.className}.${reference.memberName}()")
}
}
printError()
}
first = false
}
}
protected open fun handleCommand(): Boolean {
return false
}
protected open fun validateArguments(): Boolean {
return false
}
protected fun printInfo(message: String = "") {
if (!quiet) {
println(ansi.Text(message).toString())
}
}
protected fun printVerbose(message: String = "") {
if (verbose) {
println(ansi.Text(message).toString())
}
}
protected fun printError(message: String = "") {
System.err.println(ansi.Text(message).toString())
}
protected fun printResult(result: Any?) {
printInfo("Execution successful")
printInfo(" - result = $result")
printInfo()
}
protected fun whitelistFromPath(whitelist: Path?): Whitelist {
return whitelist?.let {
if ("$it" == "NONE") {
Whitelist.EMPTY
} else if ("$it" == "ALL") {
Whitelist.EVERYTHING
} else if ("$it" == "LANG") {
Whitelist.MINIMAL
} else {
try {
Whitelist.fromFile(file = it)
} catch (exception: Throwable) {
throw Exception("Failed to load whitelist '$it'", exception)
}
}
} ?: Whitelist.MINIMAL
}
private fun Int.countOf(suffix: String): String {
return this.let {
when (it) {
0 -> "no ${suffix}s"
1 -> "@|yellow 1|@ $suffix"
else -> "@|yellow $it|@ ${suffix}s"
}
}
}
}

View File

@ -1,29 +0,0 @@
package net.corda.djvm.tools.cli
import picocli.CommandLine
import picocli.CommandLine.Command
@Command(
name = "djvm",
versionProvider = VersionProvider::class,
description = ["JVM for running programs in a deterministic sandbox."],
mixinStandardHelpOptions = true,
subcommands = [
BuildCommand::class,
CheckCommand::class,
InspectionCommand::class,
NewCommand::class,
RunCommand::class,
ShowCommand::class,
TreeCommand::class
]
)
@Suppress("KDocMissingDocumentation")
class Commands : CommandBase() {
fun run(args: Array<String>) = when (CommandLine.call(this, System.err, *args)) {
true -> 0
else -> 1
}
}

View File

@ -1,88 +0,0 @@
package net.corda.djvm.tools.cli
import net.corda.djvm.source.ClassSource
import picocli.CommandLine.Command
import picocli.CommandLine.Parameters
import java.nio.file.Files
@Command(
name = "inspect",
description = ["Inspect the transformations that are being applied to classes before they get loaded into " +
"the sandbox."]
)
@Suppress("KDocMissingDocumentation")
class InspectionCommand : ClassCommand() {
override val filters: Array<String>
get() = classes
@Parameters(description = ["The partial or fully qualified names of the Java classes to inspect."])
var classes: Array<String> = emptyArray()
override fun processClasses(classes: List<Class<*>>) {
val sources = classes.map { ClassSource.fromClassName(it.name) }
val (_, messages) = executor.validate(*sources.toTypedArray())
if (messages.isNotEmpty()) {
for (message in messages.sorted()) {
printInfo(" - $message")
}
printInfo()
}
for (classSource in sources) {
val loadedClass = executor.load(classSource)
val sourceClass = createCodePath().resolve("${loadedClass.type.simpleName}.class")
val originalClass = Files.createTempFile("sandbox-", ".java")
val transformedClass = Files.createTempFile("sandbox-", ".java")
printInfo("Class: ${loadedClass.name}")
printVerbose(" - Size of the original byte code: ${Files.size(sourceClass)}")
printVerbose(" - Size of the transformed byte code: ${loadedClass.byteCode.bytes.size}")
printVerbose(" - Original class: $originalClass")
printVerbose(" - Transformed class: $transformedClass")
printInfo()
// Generate byte code dump of the original class
ProcessBuilder("javap", "-c", sourceClass.toString()).apply {
redirectOutput(originalClass.toFile())
environment().putAll(System.getenv())
start().apply {
waitFor()
exitValue()
}
}
// Generate byte code dump of the transformed class
Files.createTempFile("sandbox-", ".class").apply {
Files.write(this, loadedClass.byteCode.bytes)
ProcessBuilder("javap", "-c", this.toString()).apply {
redirectOutput(transformedClass.toFile())
environment().putAll(System.getenv())
start().apply {
waitFor()
exitValue()
}
}
Files.delete(this)
}
// Generate and display the difference between the original and the transformed class
ProcessBuilder(
"git", "diff", originalClass.toString(), transformedClass.toString()
).apply {
inheritIO()
environment().putAll(System.getenv())
start().apply {
waitFor()
exitValue()
}
}
printInfo()
Files.deleteIfExists(originalClass)
Files.deleteIfExists(transformedClass)
}
}
}

View File

@ -1,72 +0,0 @@
package net.corda.djvm.tools.cli
import picocli.CommandLine.*
import java.nio.file.Files
import java.nio.file.Path
@Command(
name = "new",
description = ["Create one or more new Java classes implementing the sandbox runnable interface that is " +
"required for execution in the deterministic sandbox. Each Java file is created using a template, " +
"with class name derived from the provided file name."
],
showDefaultValues = true
)
@Suppress("KDocMissingDocumentation")
class NewCommand : CommandBase() {
@Parameters(description = ["The names of the Java source files that will be created."])
var files: Array<Path> = emptyArray()
@Option(names = ["-f", "--force"], description = ["Forcefully overwrite files if they already exist."])
var force: Boolean = false
@Option(names = ["--from"], description = ["The input type to use for the constructed runnable."])
var fromType: String = "Object"
@Option(names = ["--to"], description = ["The output type to use for the constructed runnable."])
var toType: String = "Object"
@Option(names = ["--return"], description = ["The default return value for the constructed runnable."])
var returnValue: String = "null"
override fun validateArguments() = files.isNotEmpty()
override fun handleCommand(): Boolean {
val codePath = createCodePath()
val files = files.getFiles { codePath.resolve(it) }
for (file in files) {
try {
printVerbose("Creating file '$file'...")
Files.newBufferedWriter(file, *openOptions(force)).use {
it.append(TEMPLATE
.replace("[NAME]", file.baseName)
.replace("[FROM]", fromType)
.replace("[TO]", toType)
.replace("[RETURN]", returnValue))
}
} catch (exception: Throwable) {
throw Exception("Failed to create file '$file'", exception)
}
}
return true
}
companion object {
val TEMPLATE = """
|package net.corda.sandbox;
|
|import java.util.function.Function;
|
|public class [NAME] implements Function<[FROM], [TO]> {
| @Override
| public [TO] apply([FROM] input) {
| return [RETURN];
| }
|}
""".trimMargin()
}
}

View File

@ -1,12 +0,0 @@
@file:JvmName("Program")
package net.corda.djvm.tools.cli
import kotlin.system.exitProcess
/**
* The entry point of the deterministic sandbox tool.
*/
fun main(args: Array<String>) {
exitProcess(Commands().run(args))
}

View File

@ -1,36 +0,0 @@
package net.corda.djvm.tools.cli
import net.corda.djvm.source.ClassSource
import picocli.CommandLine.Command
import picocli.CommandLine.Parameters
@Command(
name = "run",
description = ["Execute runnable in sandbox."],
showDefaultValues = true
)
@Suppress("KDocMissingDocumentation")
class RunCommand : ClassCommand() {
override val filters: Array<String>
get() = classes
@Parameters(description = ["The partial or fully qualified names of the Java classes to run."])
var classes: Array<String> = emptyArray()
override fun processClasses(classes: List<Class<*>>) {
val interfaceName = java.util.function.Function::class.java.simpleName
for (clazz in classes) {
if (!clazz.interfaces.any { it.simpleName == interfaceName }) {
printError("Class is not an instance of $interfaceName; ${clazz.name}")
return
}
printInfo("Running class ${clazz.name}...")
executor.run(ClassSource.fromClassName(clazz.name), Any()).apply {
printResult(result)
printCosts(costs)
}
}
}
}

View File

@ -1,56 +0,0 @@
package net.corda.djvm.tools.cli
import net.corda.djvm.source.ClassSource
import picocli.CommandLine.Command
import picocli.CommandLine.Parameters
import java.nio.file.Files
@Command(
name = "show",
description = ["Show the transformed version of a class as it is prepared for execution in the deterministic " +
"sandbox."]
)
@Suppress("KDocMissingDocumentation")
class ShowCommand : ClassCommand() {
override val filters: Array<String>
get() = classes
@Parameters(description = ["The partial or fully qualified names of the Java classes to inspect."])
var classes: Array<String> = emptyArray()
override fun processClasses(classes: List<Class<*>>) {
val sources = classes.map { ClassSource.fromClassName(it.name) }
val (_, messages) = executor.validate(*sources.toTypedArray())
if (messages.isNotEmpty()) {
for (message in messages.sorted()) {
printInfo(" - $message")
}
printInfo()
}
for (classSource in sources) {
val loadedClass = executor.load(classSource)
printInfo("Class: ${loadedClass.name}")
printVerbose(" - Byte code size: ${loadedClass.byteCode.bytes.size}")
printVerbose(" - Has been modified: ${loadedClass.byteCode.isModified}")
printInfo()
Files.createTempFile("sandbox-", ".class").apply {
Files.write(this, loadedClass.byteCode.bytes)
ProcessBuilder("javap", "-c", this.toString()).apply {
inheritIO()
environment().putAll(System.getenv())
start().apply {
waitFor()
exitValue()
}
}
Files.delete(this)
}
printInfo()
}
}
}

View File

@ -1,33 +0,0 @@
package net.corda.djvm.tools.cli
import picocli.CommandLine.Command
import java.nio.file.Files
@Command(
name = "tree",
description = ["Show the hierarchy of the classes that have been created with the 'new' command."]
)
@Suppress("KDocMissingDocumentation")
class TreeCommand : CommandBase() {
override fun validateArguments() = true
override fun handleCommand(): Boolean {
val path = workingDirectory.resolve("tmp")
if (!Files.exists(path)) {
printError("No classes have been created so far. Run `djvm new` to get started.")
return false
}
ProcessBuilder("find", ".", "-type", "f").apply {
inheritIO()
environment().putAll(System.getenv())
directory(path.toFile())
start().apply {
waitFor()
exitValue()
}
}
return true
}
}

View File

@ -1,102 +0,0 @@
@file:JvmName("Utilities")
package net.corda.djvm.tools.cli
import io.github.classgraph.ClassGraph
import java.lang.reflect.Modifier.isAbstract
import java.lang.reflect.Modifier.isStatic
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.nio.file.StandardOpenOption
/**
* Get the expanded file name of each path in the provided array.
*/
fun Array<Path>?.getFiles(map: (Path) -> Path = { it }) = (this ?: emptyArray()).map {
val pathString = it.toString()
val path = map(it)
when {
'/' in pathString || '\\' in pathString ->
throw Exception("Please provide a pathless file name")
pathString.endsWith(".java", true) -> path
else -> Paths.get("$path.java")
}
}
/**
* Get the string representation of each expanded file name in the provided array.
*/
fun Array<Path>?.getFileNames(map: (Path) -> Path = { it }) = this.getFiles(map).map {
it.toString()
}.toTypedArray()
/**
* Execute inlined action if the collection is empty.
*/
inline fun <T> List<T>.onEmpty(action: () -> Unit): List<T> {
if (!this.any()) {
action()
}
return this
}
/**
* Execute inlined action if the array is empty.
*/
inline fun <reified T> Array<T>?.onEmpty(action: () -> Unit): Array<T> {
return (this ?: emptyArray()).toList().onEmpty(action).toTypedArray()
}
/**
* Derive the set of [StandardOpenOption]'s to use for a file operation.
*/
fun openOptions(force: Boolean) = if (force) {
arrayOf(StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)
} else {
arrayOf(StandardOpenOption.CREATE_NEW)
}
/**
* Get the path of where any generated code will be placed. Create the directory if it does not exist.
*/
fun createCodePath(): Path {
return Paths.get("tmp", "net", "corda", "sandbox").let {
Files.createDirectories(it)
}
}
/**
* Return the base name of a file (i.e., its name without extension)
*/
val Path.baseName: String
get() = this.fileName.toString()
.replaceAfterLast('.', "")
.removeSuffix(".")
/**
* The path of the executing JAR.
*/
val jarPath: String = object {}.javaClass.protectionDomain.codeSource.location.toURI().path
/**
* The path of the current working directory.
*/
val workingDirectory: Path = Paths.get(System.getProperty("user.dir"))
/**
* The class path for the current execution context.
*/
val userClassPath: String = System.getProperty("java.class.path")
/**
* Get a reference of each concrete class that implements interface or class [T].
*/
inline fun <reified T> find(scanSpec: String = "net/corda/sandbox"): List<Class<*>> {
return ClassGraph()
.whitelistPaths(scanSpec)
.enableAllInfo()
.scan()
.use { it.getClassesImplementing(T::class.java.name).loadClasses(T::class.java) }
.filter { !isAbstract(it.modifiers) && !isStatic(it.modifiers) }
}

View File

@ -1,14 +0,0 @@
package net.corda.djvm.tools.cli
import com.jcabi.manifests.Manifests
import picocli.CommandLine.IVersionProvider
/**
* Get the version number to use for the tool.
*/
@Suppress("KDocMissingDocumentation")
class VersionProvider : IVersionProvider {
override fun getVersion(): Array<String> = arrayOf(
Manifests.read("Corda-Release-Version")
)
}

View File

@ -1,39 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info">
<ThresholdFilter level="trace"/>
<Appenders>
<!-- Will generate up to 10 log files for a given day. During every rollover it will delete
those that are older than 60 days, but keep the most recent 10 GB -->
<RollingFile name="RollingFile-Appender"
fileName="djvm.log"
filePattern="djvm.%date{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="%date{ISO8601}{UTC}Z [%-5level] %c - %msg%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<DefaultRolloverStrategy min="1" max="10">
<Delete basePath="" maxDepth="1">
<IfFileName glob="djvm*.log.gz"/>
<IfLastModified age="60d">
<IfAny>
<IfAccumulatedFileSize exceeds="10 GB"/>
</IfAny>
</IfLastModified>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="RollingFile-Appender"/>
</Root>
</Loggers>
</Configuration>

View File

@ -1,16 +0,0 @@
#!/usr/bin/env bash
SCRIPT_DIR=$(dirname $(readlink -f ${BASH_SOURCE[0]}))
CLASSPATH="${CLASSPATH:-}"
DEBUG=`echo "${DEBUG:-0}" | sed 's/^[Nn][Oo]*$/0/g'`
DEBUG_PORT=5005
DEBUG_AGENT=""
if [ "$DEBUG" != 0 ]; then
echo "Opening remote debugging session on port $DEBUG_PORT"
DEBUG_AGENT="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=$DEBUG_PORT"
fi
exec java $DEBUG_AGENT -cp "$CLASSPATH:.:tmp:$SCRIPT_DIR/corda-djvm-cli.jar" net.corda.djvm.tools.cli.Program "$@"

View File

@ -1,15 +0,0 @@
@ECHO off
SETLOCAL ENABLEEXTENSIONS
IF NOT DEFINED CLASSPATH (SET CLASSPATH=)
IF DEFINED DEBUG (
SET DEBUG_PORT=5005
SET DEBUG_AGENT=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=%DEBUG_PORT%
ECHO Opening remote debugging session on port %DEBUG_PORT%
) ELSE (
SET DEBUG_AGENT=
)
CALL java %DEBUG_AGENT% -cp "%CLASSPATH%;.;tmp;%~dp0\corda-djvm-cli.jar" net.corda.djvm.tools.cli.Program %*

View File

@ -1,7 +0,0 @@
#!/usr/bin/env bash
SCRIPT_DIR=$(dirname $(readlink -f ${BASH_SOURCE[0]}))
# Generate auto-completion file for Bash and ZSH
java -cp ${SCRIPT_DIR}/corda-djvm-cli.jar \
picocli.AutoComplete -n djvm net.corda.djvm.tools.cli.Commands -f

View File

@ -1 +0,0 @@
djvm_completion

View File

@ -1,19 +0,0 @@
#!/usr/bin/env bash
file="${BASH_SOURCE[0]}"
linked_file="$(test -L "$file" && readlink "$file" || echo "$file")"
base_dir="$(cd "$(dirname "$linked_file")/../" && pwd)"
djvm_cli_jar=$(ls -1 $base_dir/cli/build/libs/corda-djvm-cli-*.jar)
CLASSPATH="${CLASSPATH:-}"
DEBUG=`echo "${DEBUG:-0}" | sed 's/^[Nn][Oo]*$/0/g'`
DEBUG_PORT=5005
DEBUG_AGENT=""
if [ "$DEBUG" != 0 ]; then
echo "Opening remote debugging session on port $DEBUG_PORT"
DEBUG_AGENT="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=$DEBUG_PORT"
fi
java $DEBUG_AGENT -cp "$CLASSPATH:.:tmp:$djvm_cli_jar" net.corda.djvm.tools.cli.Program "$@"

View File

@ -1,24 +0,0 @@
#!/usr/bin/env bash
file="${BASH_SOURCE[0]}"
base_dir="$(cd "$(dirname "$file")/" && pwd)"
# Build DJVM module and CLI
cd "$base_dir/.."
if !(../gradlew shadowJar); then
echo "Failed to build DJVM"
exit 1
fi
djvm_cli_jar=$(ls -1 $base_dir/../cli/build/libs/corda-djvm-cli-*.jar)
# Generate auto-completion file for Bash and ZSH
cd "$base_dir"
if !(java -cp $djvm_cli_jar \
picocli.AutoComplete -n djvm net.corda.djvm.tools.cli.Commands -f); then
echo "Failed to generate auto-completion file"
exit 1
fi
# Create a symbolic link to the `djvm` utility
sudo ln -sf "$base_dir/djvm" /usr/local/bin/djvm

View File

@ -1,19 +0,0 @@
package sandbox.java.lang;
import java.io.IOException;
/**
* This is a dummy class that implements just enough of {@link java.lang.Appendable}
* to keep {@link sandbox.java.lang.StringBuilder}, {@link sandbox.java.lang.StringBuffer}
* and {@link sandbox.java.lang.String} honest.
* Note that it does not extend {@link java.lang.Appendable}.
*/
public interface Appendable {
Appendable append(CharSequence csq, int start, int end) throws IOException;
Appendable append(CharSequence csq) throws IOException;
Appendable append(char c) throws IOException;
}

View File

@ -1,100 +0,0 @@
package sandbox.java.lang;
import org.jetbrains.annotations.NotNull;
import java.io.Serializable;
@SuppressWarnings({"unused", "WeakerAccess"})
public final class Boolean extends Object implements Comparable<Boolean>, Serializable {
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
@SuppressWarnings("unchecked")
public static final Class<Boolean> TYPE = (Class) java.lang.Boolean.TYPE;
private final boolean value;
public Boolean(boolean value) {
this.value = value;
}
public Boolean(String s) {
this(parseBoolean(s));
}
@Override
public boolean equals(java.lang.Object other) {
return (other instanceof Boolean) && ((Boolean) other).value == value;
}
@Override
public int hashCode() {
return hashCode(value);
}
public static int hashCode(boolean value) {
return java.lang.Boolean.hashCode(value);
}
public boolean booleanValue() {
return value;
}
@Override
@NotNull
public java.lang.String toString() {
return java.lang.Boolean.toString(value);
}
@Override
@NotNull
public String toDJVMString() {
return toString(value);
}
public static String toString(boolean b) {
return String.valueOf(b);
}
@Override
@NotNull
java.lang.Boolean fromDJVM() {
return value;
}
@Override
public int compareTo(@NotNull Boolean other) {
return compare(value, other.value);
}
public static int compare(boolean x, boolean y) {
return java.lang.Boolean.compare(x, y);
}
public static boolean parseBoolean(String s) {
return java.lang.Boolean.parseBoolean(String.fromDJVM(s));
}
public static Boolean valueOf(boolean b) {
return b ? TRUE : FALSE;
}
public static Boolean valueOf(String s) {
return valueOf(parseBoolean(s));
}
public static boolean logicalAnd(boolean a, boolean b) {
return java.lang.Boolean.logicalAnd(a, b);
}
public static boolean logicalOr(boolean a, boolean b) {
return java.lang.Boolean.logicalOr(a, b);
}
public static boolean logicalXor(boolean a, boolean b) {
return java.lang.Boolean.logicalXor(a, b);
}
public static Boolean toDJVM(java.lang.Boolean b) { return (b == null) ? null : new Boolean(b); }
}

View File

@ -1,129 +0,0 @@
package sandbox.java.lang;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings({"unused", "WeakerAccess"})
public final class Byte extends Number implements Comparable<Byte> {
public static final byte MIN_VALUE = java.lang.Byte.MIN_VALUE;
public static final byte MAX_VALUE = java.lang.Byte.MAX_VALUE;
public static final int BYTES = java.lang.Byte.BYTES;
public static final int SIZE = java.lang.Byte.SIZE;
@SuppressWarnings("unchecked")
public static final Class<Byte> TYPE = (Class) java.lang.Byte.TYPE;
private final byte value;
public Byte(byte value) {
this.value = value;
}
public Byte(String s) throws NumberFormatException {
this.value = parseByte(s);
}
@Override
public byte byteValue() {
return value;
}
@Override
public short shortValue() {
return (short) value;
}
@Override
public int intValue() {
return (int) value;
}
@Override
public long longValue() {
return (long) value;
}
@Override
public float floatValue() {
return (float) value;
}
@Override
public double doubleValue() {
return (double) value;
}
@Override
public int hashCode() {
return hashCode(value);
}
public static int hashCode(byte b) {
return java.lang.Byte.hashCode(b);
}
@Override
public boolean equals(java.lang.Object other) {
return (other instanceof Byte) && ((Byte) other).value == value;
}
@Override
@NotNull
public java.lang.String toString() {
return java.lang.Byte.toString(value);
}
@Override
@NotNull
java.lang.Byte fromDJVM() {
return value;
}
@Override
public int compareTo(@NotNull Byte other) {
return compare(this.value, other.value);
}
public static int compare(byte x, byte y) {
return java.lang.Byte.compare(x, y);
}
public static String toString(byte b) {
return Integer.toString(b);
}
public static Byte valueOf(byte b) {
return new Byte(b);
}
public static byte parseByte(String s, int radix) throws NumberFormatException {
return java.lang.Byte.parseByte(String.fromDJVM(s), radix);
}
public static byte parseByte(String s) throws NumberFormatException {
return java.lang.Byte.parseByte(String.fromDJVM(s));
}
public static Byte valueOf(String s, int radix) throws NumberFormatException {
return toDJVM(java.lang.Byte.valueOf(String.fromDJVM(s), radix));
}
public static Byte valueOf(String s) throws NumberFormatException {
return toDJVM(java.lang.Byte.valueOf(String.fromDJVM(s)));
}
public static Byte decode(String s) throws NumberFormatException {
return toDJVM(java.lang.Byte.decode(String.fromDJVM(s)));
}
public static int toUnsignedInt(byte b) {
return java.lang.Byte.toUnsignedInt(b);
}
public static long toUnsignedLong(byte b) {
return java.lang.Byte.toUnsignedLong(b);
}
public static Byte toDJVM(java.lang.Byte b) {
return (b == null) ? null : valueOf(b);
}
}

View File

@ -1,21 +0,0 @@
package sandbox.java.lang;
import org.jetbrains.annotations.NotNull;
/**
* This is a dummy class that implements just enough of {@link java.lang.CharSequence}
* to allow us to compile {@link sandbox.java.lang.String}.
*/
public interface CharSequence extends java.lang.CharSequence {
@Override
CharSequence subSequence(int start, int end);
@NotNull
String toDJVMString();
@Override
@NotNull
java.lang.String toString();
}

View File

@ -1,481 +0,0 @@
package sandbox.java.lang;
import org.jetbrains.annotations.NotNull;
import java.io.Serializable;
@SuppressWarnings({"unused", "WeakerAccess"})
public final class Character extends Object implements Comparable<Character>, Serializable {
public static final int MIN_RADIX = java.lang.Character.MIN_RADIX;
public static final int MAX_RADIX = java.lang.Character.MAX_RADIX;
public static final char MIN_VALUE = java.lang.Character.MIN_VALUE;
public static final char MAX_VALUE = java.lang.Character.MAX_VALUE;
@SuppressWarnings("unchecked")
public static final Class<Character> TYPE = (Class) java.lang.Character.TYPE;
public static final byte UNASSIGNED = java.lang.Character.UNASSIGNED;
public static final byte UPPERCASE_LETTER = java.lang.Character.UPPERCASE_LETTER;
public static final byte LOWERCASE_LETTER = java.lang.Character.LOWERCASE_LETTER;
public static final byte TITLECASE_LETTER = java.lang.Character.TITLECASE_LETTER;
public static final byte MODIFIER_LETTER = java.lang.Character.MODIFIER_LETTER;
public static final byte OTHER_LETTER = java.lang.Character.OTHER_LETTER;
public static final byte NON_SPACING_MARK = java.lang.Character.NON_SPACING_MARK;
public static final byte ENCLOSING_MARK = java.lang.Character.ENCLOSING_MARK;
public static final byte COMBINING_SPACING_MARK = java.lang.Character.COMBINING_SPACING_MARK;
public static final byte DECIMAL_DIGIT_NUMBER = java.lang.Character.DECIMAL_DIGIT_NUMBER;
public static final byte LETTER_NUMBER = java.lang.Character.LETTER_NUMBER;
public static final byte OTHER_NUMBER = java.lang.Character.OTHER_NUMBER;
public static final byte SPACE_SEPARATOR = java.lang.Character.SPACE_SEPARATOR;
public static final byte LINE_SEPARATOR = java.lang.Character.LINE_SEPARATOR;
public static final byte PARAGRAPH_SEPARATOR = java.lang.Character.PARAGRAPH_SEPARATOR;
public static final byte CONTROL = java.lang.Character.CONTROL;
public static final byte FORMAT = java.lang.Character.FORMAT;
public static final byte PRIVATE_USE = java.lang.Character.PRIVATE_USE;
public static final byte SURROGATE = java.lang.Character.SURROGATE;
public static final byte DASH_PUNCTUATION = java.lang.Character.DASH_PUNCTUATION;
public static final byte START_PUNCTUATION = java.lang.Character.START_PUNCTUATION;
public static final byte END_PUNCTUATION = java.lang.Character.END_PUNCTUATION;
public static final byte CONNECTOR_PUNCTUATION = java.lang.Character.CONNECTOR_PUNCTUATION;
public static final byte OTHER_PUNCTUATION = java.lang.Character.OTHER_PUNCTUATION;
public static final byte MATH_SYMBOL = java.lang.Character.MATH_SYMBOL;
public static final byte CURRENCY_SYMBOL = java.lang.Character.CURRENCY_SYMBOL;
public static final byte MODIFIER_SYMBOL = java.lang.Character.MODIFIER_SYMBOL;
public static final byte OTHER_SYMBOL = java.lang.Character.OTHER_SYMBOL;
public static final byte INITIAL_QUOTE_PUNCTUATION = java.lang.Character.INITIAL_QUOTE_PUNCTUATION;
public static final byte FINAL_QUOTE_PUNCTUATION = java.lang.Character.FINAL_QUOTE_PUNCTUATION;
public static final byte DIRECTIONALITY_UNDEFINED = java.lang.Character.DIRECTIONALITY_UNDEFINED;
public static final byte DIRECTIONALITY_LEFT_TO_RIGHT = java.lang.Character.DIRECTIONALITY_LEFT_TO_RIGHT;
public static final byte DIRECTIONALITY_RIGHT_TO_LEFT = java.lang.Character.DIRECTIONALITY_RIGHT_TO_LEFT;
public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC = java.lang.Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC;
public static final byte DIRECTIONALITY_EUROPEAN_NUMBER = java.lang.Character.DIRECTIONALITY_EUROPEAN_NUMBER;
public static final byte DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR = java.lang.Character.DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR;
public static final byte DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR = java.lang.Character.DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR;
public static final byte DIRECTIONALITY_ARABIC_NUMBER = java.lang.Character.DIRECTIONALITY_ARABIC_NUMBER;
public static final byte DIRECTIONALITY_COMMON_NUMBER_SEPARATOR = java.lang.Character.DIRECTIONALITY_COMMON_NUMBER_SEPARATOR;
public static final byte DIRECTIONALITY_NONSPACING_MARK = java.lang.Character.DIRECTIONALITY_NONSPACING_MARK;
public static final byte DIRECTIONALITY_BOUNDARY_NEUTRAL = java.lang.Character.DIRECTIONALITY_BOUNDARY_NEUTRAL;
public static final byte DIRECTIONALITY_PARAGRAPH_SEPARATOR = java.lang.Character.DIRECTIONALITY_PARAGRAPH_SEPARATOR;
public static final byte DIRECTIONALITY_SEGMENT_SEPARATOR = java.lang.Character.DIRECTIONALITY_SEGMENT_SEPARATOR;
public static final byte DIRECTIONALITY_WHITESPACE = java.lang.Character.DIRECTIONALITY_WHITESPACE;
public static final byte DIRECTIONALITY_OTHER_NEUTRALS = java.lang.Character.DIRECTIONALITY_OTHER_NEUTRALS;
public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING = java.lang.Character.DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING;
public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE = java.lang.Character.DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE;
public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING = java.lang.Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING;
public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE = java.lang.Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE;
public static final byte DIRECTIONALITY_POP_DIRECTIONAL_FORMAT = java.lang.Character.DIRECTIONALITY_POP_DIRECTIONAL_FORMAT;
public static final char MIN_HIGH_SURROGATE = java.lang.Character.MIN_HIGH_SURROGATE;
public static final char MAX_HIGH_SURROGATE = java.lang.Character.MAX_HIGH_SURROGATE;
public static final char MIN_LOW_SURROGATE = java.lang.Character.MIN_LOW_SURROGATE;
public static final char MAX_LOW_SURROGATE = java.lang.Character.MAX_LOW_SURROGATE;
public static final char MIN_SURROGATE = java.lang.Character.MIN_SURROGATE;
public static final char MAX_SURROGATE = java.lang.Character.MAX_SURROGATE;
public static final int MIN_SUPPLEMENTARY_CODE_POINT = java.lang.Character.MIN_SUPPLEMENTARY_CODE_POINT;
public static final int MIN_CODE_POINT = java.lang.Character.MIN_CODE_POINT;
public static final int MAX_CODE_POINT = java.lang.Character.MAX_CODE_POINT;
public static final int BYTES = java.lang.Character.BYTES;
public static final int SIZE = java.lang.Character.SIZE;
private final char value;
public Character(char c) {
this.value = c;
}
public char charValue() {
return this.value;
}
@Override
public int hashCode() {
return hashCode(this.value);
}
public static int hashCode(char value) {
return java.lang.Character.hashCode(value);
}
@Override
public boolean equals(java.lang.Object other) {
return (other instanceof Character) && ((Character) other).value == value;
}
@Override
@NotNull
public java.lang.String toString() {
return java.lang.Character.toString(value);
}
@Override
@NotNull
public String toDJVMString() {
return toString(value);
}
@Override
@NotNull
java.lang.Character fromDJVM() {
return value;
}
@Override
public int compareTo(@NotNull Character var1) {
return compare(this.value, var1.value);
}
public static int compare(char x, char y) {
return java.lang.Character.compare(x, y);
}
public static String toString(char c) {
return String.toDJVM(java.lang.Character.toString(c));
}
public static Character valueOf(char c) {
return (c <= 127) ? Cache.cache[(int)c] : new Character(c);
}
public static boolean isValidCodePoint(int codePoint) {
return java.lang.Character.isValidCodePoint(codePoint);
}
public static boolean isBmpCodePoint(int codePoint) {
return java.lang.Character.isBmpCodePoint(codePoint);
}
public static boolean isSupplementaryCodePoint(int codePoint) {
return java.lang.Character.isSupplementaryCodePoint(codePoint);
}
public static boolean isHighSurrogate(char ch) {
return java.lang.Character.isHighSurrogate(ch);
}
public static boolean isLowSurrogate(char ch) {
return java.lang.Character.isLowSurrogate(ch);
}
public static boolean isSurrogate(char ch) {
return java.lang.Character.isSurrogate(ch);
}
public static boolean isSurrogatePair(char high, char low) {
return java.lang.Character.isSurrogatePair(high, low);
}
public static int charCount(int codePoint) {
return java.lang.Character.charCount(codePoint);
}
public static int toCodePoint(char high, char low) {
return java.lang.Character.toCodePoint(high, low);
}
public static int codePointAt(CharSequence seq, int index) {
return java.lang.Character.codePointAt(seq, index);
}
public static int codePointAt(char[] a, int index) {
return java.lang.Character.codePointAt(a, index);
}
public static int codePointAt(char[] a, int index, int limit) {
return java.lang.Character.codePointAt(a, index, limit);
}
public static int codePointBefore(CharSequence seq, int index) {
return java.lang.Character.codePointBefore(seq, index);
}
public static int codePointBefore(char[] a, int index) {
return java.lang.Character.codePointBefore(a, index);
}
public static int codePointBefore(char[] a, int index, int limit) {
return java.lang.Character.codePointBefore(a, index, limit);
}
public static char highSurrogate(int codePoint) {
return java.lang.Character.highSurrogate(codePoint);
}
public static char lowSurrogate(int codePoint) {
return java.lang.Character.lowSurrogate(codePoint);
}
public static int toChars(int codePoint, char[] dst, int dstIndex) {
return java.lang.Character.toChars(codePoint, dst, dstIndex);
}
public static char[] toChars(int codePoint) {
return java.lang.Character.toChars(codePoint);
}
public static int codePointCount(CharSequence seq, int beginIndex, int endIndex) {
return java.lang.Character.codePointCount(seq, beginIndex, endIndex);
}
public static int codePointCount(char[] a, int offset, int count) {
return java.lang.Character.codePointCount(a, offset, count);
}
public static int offsetByCodePoints(CharSequence seq, int index, int codePointOffset) {
return java.lang.Character.offsetByCodePoints(seq, index, codePointOffset);
}
public static int offsetByCodePoints(char[] a, int start, int count, int index, int codePointOffset) {
return java.lang.Character.offsetByCodePoints(a, start, count, index, codePointOffset);
}
public static boolean isLowerCase(char ch) {
return java.lang.Character.isLowerCase(ch);
}
public static boolean isLowerCase(int codePoint) {
return java.lang.Character.isLowerCase(codePoint);
}
public static boolean isUpperCase(char ch) {
return java.lang.Character.isUpperCase(ch);
}
public static boolean isUpperCase(int codePoint) {
return java.lang.Character.isUpperCase(codePoint);
}
public static boolean isTitleCase(char ch) {
return java.lang.Character.isTitleCase(ch);
}
public static boolean isTitleCase(int codePoint) {
return java.lang.Character.isTitleCase(codePoint);
}
public static boolean isDigit(char ch) {
return java.lang.Character.isDigit(ch);
}
public static boolean isDigit(int codePoint) {
return java.lang.Character.isDigit(codePoint);
}
public static boolean isDefined(char ch) {
return java.lang.Character.isDefined(ch);
}
public static boolean isDefined(int codePoint) {
return java.lang.Character.isDefined(codePoint);
}
public static boolean isLetter(char ch) {
return java.lang.Character.isLetter(ch);
}
public static boolean isLetter(int codePoint) {
return java.lang.Character.isLetter(codePoint);
}
public static boolean isLetterOrDigit(char ch) {
return java.lang.Character.isLetterOrDigit(ch);
}
public static boolean isLetterOrDigit(int codePoint) {
return java.lang.Character.isLetterOrDigit(codePoint);
}
@Deprecated
public static boolean isJavaLetter(char ch) {
return java.lang.Character.isJavaLetter(ch);
}
@Deprecated
public static boolean isJavaLetterOrDigit(char ch) {
return java.lang.Character.isJavaLetterOrDigit(ch);
}
public static boolean isAlphabetic(int codePoint) {
return java.lang.Character.isAlphabetic(codePoint);
}
public static boolean isIdeographic(int codePoint) {
return java.lang.Character.isIdeographic(codePoint);
}
public static boolean isJavaIdentifierStart(char ch) {
return java.lang.Character.isJavaIdentifierStart(ch);
}
public static boolean isJavaIdentifierStart(int codePoint) {
return java.lang.Character.isJavaIdentifierStart(codePoint);
}
public static boolean isJavaIdentifierPart(char ch) {
return java.lang.Character.isJavaIdentifierPart(ch);
}
public static boolean isJavaIdentifierPart(int codePoint) {
return java.lang.Character.isJavaIdentifierPart(codePoint);
}
public static boolean isUnicodeIdentifierStart(char ch) {
return java.lang.Character.isUnicodeIdentifierStart(ch);
}
public static boolean isUnicodeIdentifierStart(int codePoint) {
return java.lang.Character.isUnicodeIdentifierStart(codePoint);
}
public static boolean isUnicodeIdentifierPart(char ch) {
return java.lang.Character.isUnicodeIdentifierPart(ch);
}
public static boolean isUnicodeIdentifierPart(int codePoint) {
return java.lang.Character.isUnicodeIdentifierPart(codePoint);
}
public static boolean isIdentifierIgnorable(char ch) {
return java.lang.Character.isIdentifierIgnorable(ch);
}
public static boolean isIdentifierIgnorable(int codePoint) {
return java.lang.Character.isIdentifierIgnorable(codePoint);
}
public static char toLowerCase(char ch) {
return java.lang.Character.toLowerCase(ch);
}
public static int toLowerCase(int codePoint) {
return java.lang.Character.toLowerCase(codePoint);
}
public static char toUpperCase(char ch) {
return java.lang.Character.toUpperCase(ch);
}
public static int toUpperCase(int codePoint) {
return java.lang.Character.toUpperCase(codePoint);
}
public static char toTitleCase(char ch) {
return java.lang.Character.toTitleCase(ch);
}
public static int toTitleCase(int codePoint) {
return java.lang.Character.toTitleCase(codePoint);
}
public static int digit(char ch, int radix) {
return java.lang.Character.digit(ch, radix);
}
public static int digit(int codePoint, int radix) {
return java.lang.Character.digit(codePoint, radix);
}
public static int getNumericValue(char ch) {
return java.lang.Character.getNumericValue(ch);
}
public static int getNumericValue(int codePoint) {
return java.lang.Character.getNumericValue(codePoint);
}
@Deprecated
public static boolean isSpace(char ch) {
return java.lang.Character.isSpace(ch);
}
public static boolean isSpaceChar(char ch) {
return java.lang.Character.isSpaceChar(ch);
}
public static boolean isSpaceChar(int codePoint) {
return java.lang.Character.isSpaceChar(codePoint);
}
public static boolean isWhitespace(char ch) {
return java.lang.Character.isWhitespace(ch);
}
public static boolean isWhitespace(int codePoint) {
return java.lang.Character.isWhitespace(codePoint);
}
public static boolean isISOControl(char ch) {
return java.lang.Character.isISOControl(ch);
}
public static boolean isISOControl(int codePoint) {
return java.lang.Character.isISOControl(codePoint);
}
public static int getType(char ch) {
return java.lang.Character.getType(ch);
}
public static int getType(int codePoint) {
return java.lang.Character.getType(codePoint);
}
public static char forDigit(int digit, int radix) {
return java.lang.Character.forDigit(digit, radix);
}
public static byte getDirectionality(char ch) {
return java.lang.Character.getDirectionality(ch);
}
public static byte getDirectionality(int codePoint) {
return java.lang.Character.getDirectionality(codePoint);
}
public static boolean isMirrored(char ch) {
return java.lang.Character.isMirrored(ch);
}
public static boolean isMirrored(int codePoint) {
return java.lang.Character.isMirrored(codePoint);
}
public static String getName(int codePoint) {
return String.toDJVM(java.lang.Character.getName(codePoint));
}
public static Character toDJVM(java.lang.Character c) {
return (c == null) ? null : valueOf(c);
}
// These three nested classes are placeholders to ensure that
// the Character class bytecode is generated correctly. The
// real classes will be loaded from the from the bootstrap jar
// and then mapped into the sandbox.* namespace.
public static final class UnicodeScript extends Enum<UnicodeScript> {
private UnicodeScript(String name, int index) {
super(name, index);
}
@Override
public int compareTo(@NotNull UnicodeScript other) {
throw new UnsupportedOperationException("Bootstrap implementation");
}
}
public static final class UnicodeBlock extends Subset {}
public static class Subset extends Object {}
/**
* Keep pre-allocated instances of the first 128 characters
* on the basis that these will be used most frequently.
*/
private static class Cache {
private static final Character[] cache = new Character[128];
static {
for (int c = 0; c < cache.length; ++c) {
cache[c] = new Character((char) c);
}
}
private Cache() {}
}
}

View File

@ -1,8 +0,0 @@
package sandbox.java.lang;
/**
* This is a dummy class that implements just enough of {@link java.lang.Comparable}
* to allow us to compile {@link sandbox.java.lang.String}.
*/
public interface Comparable<T> extends java.lang.Comparable<T> {
}

View File

@ -1,37 +0,0 @@
package sandbox.java.lang;
import org.jetbrains.annotations.NotNull;
/**
* Pinned exceptions inherit from {@link java.lang.Throwable}, but we
* still need to be able to pass them through the sandbox's
* exception handlers. In which case we will wrap them inside
* one of these.
*
* Exceptions wrapped inside one of these cannot be caught.
*
* Also used for passing exceptions through finally blocks without
* any expensive unwrapping to {@link sandbox.java.lang.Throwable}
* based types.
*/
final class DJVMThrowableWrapper extends Throwable {
private final java.lang.Throwable throwable;
DJVMThrowableWrapper(java.lang.Throwable t) {
throwable = t;
}
/**
* Prevent this wrapper from creating its own stack trace.
*/
@Override
public final Throwable fillInStackTrace() {
return this;
}
@Override
@NotNull
final java.lang.Throwable fromDJVM() {
return throwable;
}
}

View File

@ -1,163 +0,0 @@
package sandbox.java.lang;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings({"unused", "WeakerAccess"})
public final class Double extends Number implements Comparable<Double> {
public static final double POSITIVE_INFINITY = java.lang.Double.POSITIVE_INFINITY;
public static final double NEGATIVE_INFINITY = java.lang.Double.NEGATIVE_INFINITY;
public static final double NaN = java.lang.Double.NaN;
public static final double MAX_VALUE = java.lang.Double.MAX_VALUE;
public static final double MIN_NORMAL = java.lang.Double.MIN_NORMAL;
public static final double MIN_VALUE = java.lang.Double.MIN_VALUE;
public static final int MAX_EXPONENT = java.lang.Double.MAX_EXPONENT;
public static final int MIN_EXPONENT = java.lang.Double.MIN_EXPONENT;
public static final int BYTES = java.lang.Double.BYTES;
public static final int SIZE = java.lang.Double.SIZE;
@SuppressWarnings("unchecked")
public static final Class<Double> TYPE = (Class) java.lang.Double.TYPE;
private final double value;
public Double(double value) {
this.value = value;
}
public Double(String s) throws NumberFormatException {
this.value = parseDouble(s);
}
@Override
public double doubleValue() {
return value;
}
@Override
public float floatValue() {
return (float)value;
}
@Override
public long longValue() {
return (long)value;
}
@Override
public int intValue() {
return (int)value;
}
@Override
public short shortValue() {
return (short)value;
}
@Override
public byte byteValue() {
return (byte)value;
}
public boolean isNaN() {
return java.lang.Double.isNaN(value);
}
public boolean isInfinite() {
return isInfinite(this.value);
}
@Override
public boolean equals(java.lang.Object other) {
return (other instanceof Double) && doubleToLongBits(((Double)other).value) == doubleToLongBits(value);
}
@Override
public int hashCode() {
return hashCode(value);
}
public static int hashCode(double d) {
return java.lang.Double.hashCode(d);
}
@Override
@NotNull
public java.lang.String toString() {
return java.lang.Double.toString(value);
}
@Override
@NotNull
java.lang.Double fromDJVM() {
return value;
}
@Override
public int compareTo(@NotNull Double other) {
return compare(this.value, other.value);
}
public static String toString(double d) {
return String.toDJVM(java.lang.Double.toString(d));
}
public static String toHexString(double d) {
return String.toDJVM(java.lang.Double.toHexString(d));
}
public static Double valueOf(String s) throws NumberFormatException {
return toDJVM(java.lang.Double.valueOf(String.fromDJVM(s)));
}
public static Double valueOf(double d) {
return new Double(d);
}
public static double parseDouble(String s) throws NumberFormatException {
return java.lang.Double.parseDouble(String.fromDJVM(s));
}
public static boolean isNaN(double d) {
return java.lang.Double.isNaN(d);
}
public static boolean isInfinite(double d) {
return java.lang.Double.isInfinite(d);
}
public static boolean isFinite(double d) {
return java.lang.Double.isFinite(d);
}
public static long doubleToLongBits(double d) {
return java.lang.Double.doubleToLongBits(d);
}
public static long doubleToRawLongBits(double d) {
return java.lang.Double.doubleToRawLongBits(d);
}
public static double longBitsToDouble(long bits) {
return java.lang.Double.longBitsToDouble(bits);
}
public static int compare(double d1, double d2) {
return java.lang.Double.compare(d1, d2);
}
public static double sum(double a, double b) {
return java.lang.Double.sum(a, b);
}
public static double max(double a, double b) {
return java.lang.Double.max(a, b);
}
public static double min(double a, double b) {
return java.lang.Double.min(a, b);
}
public static Double toDJVM(java.lang.Double d) {
return (d == null) ? null : valueOf(d);
}
}

View File

@ -1,35 +0,0 @@
package sandbox.java.lang;
import org.jetbrains.annotations.NotNull;
import java.io.Serializable;
/**
* This is a dummy class. We will load the actual Enum class at run-time.
*/
@SuppressWarnings({"unused", "WeakerAccess"})
public abstract class Enum<E extends Enum<E>> extends Object implements Comparable<E>, Serializable {
private final String name;
private final int ordinal;
protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}
public String name() {
return name;
}
public int ordinal() {
return ordinal;
}
@Override
@NotNull
final java.lang.Enum<?> fromDJVM() {
throw new UnsupportedOperationException("Dummy implementation");
}
}

View File

@ -1,163 +0,0 @@
package sandbox.java.lang;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings({"unused", "WeakerAccess"})
public final class Float extends Number implements Comparable<Float> {
public static final float POSITIVE_INFINITY = java.lang.Float.POSITIVE_INFINITY;
public static final float NEGATIVE_INFINITY = java.lang.Float.NEGATIVE_INFINITY;
public static final float NaN = java.lang.Float.NaN;
public static final float MAX_VALUE = java.lang.Float.MAX_VALUE;
public static final float MIN_NORMAL = java.lang.Float.MIN_NORMAL;
public static final float MIN_VALUE = java.lang.Float.MIN_VALUE;
public static final int MAX_EXPONENT = java.lang.Float.MAX_EXPONENT;
public static final int MIN_EXPONENT = java.lang.Float.MIN_EXPONENT;
public static final int BYTES = java.lang.Float.BYTES;
public static final int SIZE = java.lang.Float.SIZE;
@SuppressWarnings("unchecked")
public static final Class<Float> TYPE = (Class) java.lang.Float.TYPE;
private final float value;
public Float(float value) {
this.value = value;
}
public Float(String s) throws NumberFormatException {
this.value = parseFloat(s);
}
@Override
public int hashCode() {
return hashCode(value);
}
public static int hashCode(float f) {
return java.lang.Float.hashCode(f);
}
@Override
public boolean equals(java.lang.Object other) {
return other instanceof Float && floatToIntBits(((Float)other).value) == floatToIntBits(this.value);
}
@Override
@NotNull
public java.lang.String toString() {
return java.lang.Float.toString(value);
}
@Override
@NotNull
java.lang.Float fromDJVM() {
return value;
}
@Override
public double doubleValue() {
return (double)value;
}
@Override
public float floatValue() {
return value;
}
@Override
public long longValue() {
return (long)value;
}
@Override
public int intValue() {
return (int)value;
}
@Override
public short shortValue() {
return (short)value;
}
@Override
public byte byteValue() {
return (byte)value;
}
@Override
public int compareTo(@NotNull Float other) {
return compare(this.value, other.value);
}
public boolean isNaN() {
return isNaN(value);
}
public boolean isInfinite() {
return isInfinite(value);
}
public static String toString(float f) {
return String.valueOf(f);
}
public static String toHexString(float f) {
return String.toDJVM(java.lang.Float.toHexString(f));
}
public static Float valueOf(String s) throws NumberFormatException {
return toDJVM(java.lang.Float.valueOf(String.fromDJVM(s)));
}
public static Float valueOf(float f) {
return new Float(f);
}
public static float parseFloat(String s) throws NumberFormatException {
return java.lang.Float.parseFloat(String.fromDJVM(s));
}
public static boolean isNaN(float f) {
return java.lang.Float.isNaN(f);
}
public static boolean isInfinite(float f) {
return java.lang.Float.isInfinite(f);
}
public static boolean isFinite(float f) {
return java.lang.Float.isFinite(f);
}
public static int floatToIntBits(float f) {
return java.lang.Float.floatToIntBits(f);
}
public static int floatToRawIntBits(float f) {
return java.lang.Float.floatToIntBits(f);
}
public static float intBitsToFloat(int bits) {
return java.lang.Float.intBitsToFloat(bits);
}
public static int compare(float f1, float f2) {
return java.lang.Float.compare(f1, f2);
}
public static float sum(float a, float b) {
return java.lang.Float.sum(a, b);
}
public static float max(float a, float b) {
return java.lang.Float.max(a, b);
}
public static float min(float a, float b) {
return java.lang.Float.min(a, b);
}
public static Float toDJVM(java.lang.Float f) {
return (f == null) ? null : valueOf(f);
}
}

View File

@ -1,241 +0,0 @@
package sandbox.java.lang;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings({"unused", "WeakerAccess"})
public final class Integer extends Number implements Comparable<Integer> {
public static final int MIN_VALUE = java.lang.Integer.MIN_VALUE;
public static final int MAX_VALUE = java.lang.Integer.MAX_VALUE;
public static final int BYTES = java.lang.Integer.BYTES;
public static final int SIZE = java.lang.Integer.SIZE;
static final int[] SIZE_TABLE = new int[] { 9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, MAX_VALUE };
@SuppressWarnings("unchecked")
public static final Class<Integer> TYPE = (Class) java.lang.Integer.TYPE;
private final int value;
public Integer(int value) {
this.value = value;
}
public Integer(String s) throws NumberFormatException {
this.value = parseInt(s, 10);
}
@Override
public int hashCode() {
return Integer.hashCode(value);
}
public static int hashCode(int i) {
return java.lang.Integer.hashCode(i);
}
@Override
public boolean equals(java.lang.Object other) {
return (other instanceof Integer) && (value == ((Integer) other).value);
}
@Override
public int intValue() {
return value;
}
@Override
public long longValue() {
return value;
}
@Override
public short shortValue() {
return (short) value;
}
@Override
public byte byteValue() {
return (byte) value;
}
@Override
public float floatValue() {
return (float) value;
}
@Override
public double doubleValue() {
return (double) value;
}
@Override
public int compareTo(@NotNull Integer other) {
return compare(this.value, other.value);
}
@Override
@NotNull
public java.lang.String toString() {
return java.lang.Integer.toString(value);
}
@Override
@NotNull
java.lang.Integer fromDJVM() {
return value;
}
public static String toString(int i, int radix) {
return String.toDJVM(java.lang.Integer.toString(i, radix));
}
public static String toUnsignedString(int i, int radix) {
return String.toDJVM(java.lang.Integer.toUnsignedString(i, radix));
}
public static String toHexString(int i) {
return String.toDJVM(java.lang.Integer.toHexString(i));
}
public static String toOctalString(int i) {
return String.toDJVM(java.lang.Integer.toOctalString(i));
}
public static String toBinaryString(int i) {
return String.toDJVM(java.lang.Integer.toBinaryString(i));
}
public static String toString(int i) {
return String.toDJVM(java.lang.Integer.toString(i));
}
public static String toUnsignedString(int i) {
return String.toDJVM(java.lang.Integer.toUnsignedString(i));
}
public static int parseInt(String s, int radix) throws NumberFormatException {
return java.lang.Integer.parseInt(String.fromDJVM(s), radix);
}
public static int parseInt(String s) throws NumberFormatException {
return java.lang.Integer.parseInt(String.fromDJVM(s));
}
public static int parseUnsignedInt(String s, int radix) throws NumberFormatException {
return java.lang.Integer.parseUnsignedInt(String.fromDJVM(s), radix);
}
public static int parseUnsignedInt(String s) throws NumberFormatException {
return java.lang.Integer.parseUnsignedInt(String.fromDJVM(s));
}
public static Integer valueOf(String s, int radix) throws NumberFormatException {
return toDJVM(java.lang.Integer.valueOf(String.fromDJVM(s), radix));
}
public static Integer valueOf(String s) throws NumberFormatException {
return toDJVM(java.lang.Integer.valueOf(String.fromDJVM(s)));
}
public static Integer valueOf(int i) {
return new Integer(i);
}
public static Integer decode(String nm) throws NumberFormatException {
return new Integer(java.lang.Integer.decode(String.fromDJVM(nm)));
}
public static int compare(int x, int y) {
return java.lang.Integer.compare(x, y);
}
public static int compareUnsigned(int x, int y) {
return java.lang.Integer.compareUnsigned(x, y);
}
public static long toUnsignedLong(int x) {
return java.lang.Integer.toUnsignedLong(x);
}
public static int divideUnsigned(int dividend, int divisor) {
return java.lang.Integer.divideUnsigned(dividend, divisor);
}
public static int remainderUnsigned(int dividend, int divisor) {
return java.lang.Integer.remainderUnsigned(dividend, divisor);
}
public static int highestOneBit(int i) {
return java.lang.Integer.highestOneBit(i);
}
public static int lowestOneBit(int i) {
return java.lang.Integer.lowestOneBit(i);
}
public static int numberOfLeadingZeros(int i) {
return java.lang.Integer.numberOfLeadingZeros(i);
}
public static int numberOfTrailingZeros(int i) {
return java.lang.Integer.numberOfTrailingZeros(i);
}
public static int bitCount(int i) {
return java.lang.Integer.bitCount(i);
}
public static int rotateLeft(int i, int distance) {
return java.lang.Integer.rotateLeft(i, distance);
}
public static int rotateRight(int i, int distance) {
return java.lang.Integer.rotateRight(i, distance);
}
public static int reverse(int i) {
return java.lang.Integer.reverse(i);
}
public static int signum(int i) {
return java.lang.Integer.signum(i);
}
public static int reverseBytes(int i) {
return java.lang.Integer.reverseBytes(i);
}
public static int sum(int a, int b) {
return java.lang.Integer.sum(a, b);
}
public static int max(int a, int b) {
return java.lang.Integer.max(a, b);
}
public static int min(int a, int b) {
return java.lang.Integer.min(a, b);
}
public static Integer toDJVM(java.lang.Integer i) {
return (i == null) ? null : valueOf(i);
}
static int stringSize(final int number) {
int i = 0;
while (number > SIZE_TABLE[i]) {
++i;
}
return i + 1;
}
static void getChars(final int number, int index, char[] buffer) {
java.lang.String s = java.lang.Integer.toString(number);
int length = s.length();
while (length > 0) {
buffer[--index] = s.charAt(--length);
}
}
}

View File

@ -1,15 +0,0 @@
package sandbox.java.lang;
import org.jetbrains.annotations.NotNull;
import java.util.Iterator;
/**
* This is a dummy class that implements just enough of {@link java.lang.Iterable}
* to allow us to compile {@link sandbox.java.lang.String}.
*/
public interface Iterable<T> extends java.lang.Iterable<T> {
@Override
@NotNull
Iterator<T> iterator();
}

View File

@ -1,239 +0,0 @@
package sandbox.java.lang;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings({"unused", "WeakerAccess"})
public final class Long extends Number implements Comparable<Long> {
public static final long MIN_VALUE = java.lang.Long.MIN_VALUE;
public static final long MAX_VALUE = java.lang.Long.MAX_VALUE;
public static final int BYTES = java.lang.Long.BYTES;
public static final int SIZE = java.lang.Long.SIZE;
@SuppressWarnings("unchecked")
public static final Class<Long> TYPE = (Class) java.lang.Long.TYPE;
private final long value;
public Long(long value) {
this.value = value;
}
public Long(String s) throws NumberFormatException {
this.value = parseLong(s, 10);
}
@Override
public int hashCode() {
return hashCode(value);
}
@Override
public boolean equals(java.lang.Object other) {
return (other instanceof Long) && ((Long) other).longValue() == value;
}
public static int hashCode(long l) {
return java.lang.Long.hashCode(l);
}
@Override
public int intValue() {
return (int) value;
}
@Override
public long longValue() {
return value;
}
@Override
public short shortValue() {
return (short) value;
}
@Override
public byte byteValue() {
return (byte) value;
}
@Override
public float floatValue() {
return (float) value;
}
@Override
public double doubleValue() {
return (double) value;
}
@Override
public int compareTo(@NotNull Long other) {
return compare(value, other.value);
}
public static int compare(long x, long y) {
return java.lang.Long.compare(x, y);
}
@Override
@NotNull
java.lang.Long fromDJVM() {
return value;
}
@Override
@NotNull
public java.lang.String toString() {
return java.lang.Long.toString(value);
}
public static String toString(long l) {
return String.toDJVM(java.lang.Long.toString(l));
}
public static String toString(long l, int radix) {
return String.toDJVM(java.lang.Long.toString(l, radix));
}
public static String toUnsignedString(long l, int radix) {
return String.toDJVM(java.lang.Long.toUnsignedString(l, radix));
}
public static String toUnsignedString(long l) {
return String.toDJVM(java.lang.Long.toUnsignedString(l));
}
public static String toHexString(long l) {
return String.toDJVM(java.lang.Long.toHexString(l));
}
public static String toOctalString(long l) {
return String.toDJVM(java.lang.Long.toOctalString(l));
}
public static String toBinaryString(long l) {
return String.toDJVM(java.lang.Long.toBinaryString(l));
}
public static long parseLong(String s, int radix) throws NumberFormatException {
return java.lang.Long.parseLong(String.fromDJVM(s), radix);
}
public static long parseLong(String s) throws NumberFormatException {
return java.lang.Long.parseLong(String.fromDJVM(s));
}
public static long parseUnsignedLong(String s, int radix) throws NumberFormatException {
return java.lang.Long.parseUnsignedLong(String.fromDJVM(s), radix);
}
public static long parseUnsignedLong(String s) throws NumberFormatException {
return java.lang.Long.parseUnsignedLong(String.fromDJVM(s));
}
public static Long valueOf(String s, int radix) throws NumberFormatException {
return toDJVM(java.lang.Long.valueOf(String.fromDJVM(s), radix));
}
public static Long valueOf(String s) throws NumberFormatException {
return toDJVM(java.lang.Long.valueOf(String.fromDJVM(s)));
}
public static Long valueOf(long l) {
return new Long(l);
}
public static Long decode(String s) throws NumberFormatException {
return toDJVM(java.lang.Long.decode(String.fromDJVM(s)));
}
public static int compareUnsigned(long x, long y) {
return java.lang.Long.compareUnsigned(x, y);
}
public static long divideUnsigned(long dividend, long divisor) {
return java.lang.Long.divideUnsigned(dividend, divisor);
}
public static long remainderUnsigned(long dividend, long divisor) {
return java.lang.Long.remainderUnsigned(dividend, divisor);
}
public static long highestOneBit(long l) {
return java.lang.Long.highestOneBit(l);
}
public static long lowestOneBit(long l) {
return java.lang.Long.lowestOneBit(l);
}
public static int numberOfLeadingZeros(long l) {
return java.lang.Long.numberOfLeadingZeros(l);
}
public static int numberOfTrailingZeros(long l) {
return java.lang.Long.numberOfTrailingZeros(l);
}
public static int bitCount(long l) {
return java.lang.Long.bitCount(l);
}
public static long rotateLeft(long i, int distance) {
return java.lang.Long.rotateLeft(i, distance);
}
public static long rotateRight(long i, int distance) {
return java.lang.Long.rotateRight(i, distance);
}
public static long reverse(long l) {
return java.lang.Long.reverse(l);
}
public static int signum(long l) {
return java.lang.Long.signum(l);
}
public static long reverseBytes(long l) {
return java.lang.Long.reverseBytes(l);
}
public static long sum(long a, long b) {
return java.lang.Long.sum(a, b);
}
public static long max(long a, long b) {
return java.lang.Long.max(a, b);
}
public static long min(long a, long b) {
return java.lang.Long.min(a, b);
}
public static Long toDJVM(java.lang.Long l) {
return (l == null) ? null : valueOf(l);
}
static int stringSize(final long number) {
long l = 10;
int i = 1;
while ((i < 19) && (number >= l)) {
l *= 10;
++i;
}
return i;
}
static void getChars(final long number, int index, char[] buffer) {
java.lang.String s = java.lang.Long.toString(number);
int length = s.length();
while (length > 0) {
buffer[--index] = s.charAt(--length);
}
}
}

View File

@ -1,21 +0,0 @@
package sandbox.java.lang;
import org.jetbrains.annotations.NotNull;
import java.io.Serializable;
@SuppressWarnings("unused")
public abstract class Number extends Object implements Serializable {
public abstract double doubleValue();
public abstract float floatValue();
public abstract long longValue();
public abstract int intValue();
public abstract short shortValue();
public abstract byte byteValue();
@Override
@NotNull
public String toDJVMString() {
return String.toDJVM(toString());
}
}

View File

@ -1,70 +0,0 @@
package sandbox.java.lang;
import org.jetbrains.annotations.NotNull;
import sandbox.net.corda.djvm.rules.RuleViolationError;
public class Object {
@Override
public int hashCode() {
return sandbox.java.lang.System.identityHashCode(this);
}
@Override
@NotNull
public java.lang.String toString() {
return toDJVMString().toString();
}
@NotNull
public String toDJVMString() {
return String.toDJVM("sandbox.java.lang.Object@" + java.lang.Integer.toString(hashCode(), 16));
}
@NotNull
java.lang.Object fromDJVM() {
return this;
}
public static java.lang.Object[] fromDJVM(java.lang.Object[] args) {
if (args == null) {
return null;
}
java.lang.Object[] unwrapped = (java.lang.Object[]) java.lang.reflect.Array.newInstance(
fromDJVM(args.getClass().getComponentType()), args.length
);
int i = 0;
for (java.lang.Object arg : args) {
unwrapped[i] = unwrap(arg);
++i;
}
return unwrapped;
}
private static java.lang.Object unwrap(java.lang.Object arg) {
if (arg instanceof Object) {
return ((Object) arg).fromDJVM();
} else if (java.lang.Object[].class.isAssignableFrom(arg.getClass())) {
return fromDJVM((java.lang.Object[]) arg);
} else {
return arg;
}
}
private static Class<?> fromDJVM(Class<?> type) {
try {
return DJVM.fromDJVMType(type);
} catch (ClassNotFoundException e) {
throw new RuleViolationError(e.getMessage());
}
}
static java.util.Locale fromDJVM(sandbox.java.util.Locale locale) {
return java.util.Locale.forLanguageTag(locale.toLanguageTag().fromDJVM());
}
static java.nio.charset.Charset fromDJVM(sandbox.java.nio.charset.Charset charset) {
return java.nio.charset.Charset.forName(charset.name().fromDJVM());
}
}

View File

@ -1,27 +0,0 @@
package sandbox.java.lang;
@SuppressWarnings("unused")
public final class Runtime extends Object {
private static final Runtime RUNTIME = new Runtime();
private Runtime() {}
public static Runtime getRuntime() {
return RUNTIME;
}
/**
* Everything inside the sandbox is single-threaded.
* @return 1
*/
public int availableProcessors() {
return 1;
}
public void loadLibrary(String libraryName) {}
public void load(String fileName) {}
public void runFinalization() {}
public void gc() {}
}

View File

@ -1,128 +0,0 @@
package sandbox.java.lang;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings({"unused", "WeakerAccess"})
public final class Short extends Number implements Comparable<Short> {
public static final short MIN_VALUE = java.lang.Short.MIN_VALUE;
public static final short MAX_VALUE = java.lang.Short.MAX_VALUE;
public static final int BYTES = java.lang.Short.BYTES;
public static final int SIZE = java.lang.Short.SIZE;
@SuppressWarnings("unchecked")
public static final Class<Short> TYPE = (Class) java.lang.Short.TYPE;
private final short value;
public Short(short value) {
this.value = value;
}
public Short(String s) throws NumberFormatException {
this.value = parseShort(s);
}
@Override
public byte byteValue() {
return (byte)value;
}
@Override
public short shortValue() {
return value;
}
@Override
public int intValue() {
return value;
}
@Override
public long longValue() {
return (long)value;
}
@Override
public float floatValue() {
return (float)value;
}
@Override
public double doubleValue() {
return (double)value;
}
@Override
@NotNull
public java.lang.String toString() {
return java.lang.Integer.toString(value);
}
@Override
@NotNull
java.lang.Short fromDJVM() {
return value;
}
@Override
public int hashCode() {
return hashCode(value);
}
public static int hashCode(short value) {
return java.lang.Short.hashCode(value);
}
@Override
public boolean equals(java.lang.Object other) {
return (other instanceof Short) && ((Short) other).value == value;
}
public int compareTo(@NotNull Short other) {
return compare(this.value, other.value);
}
public static int compare(short x, short y) {
return java.lang.Short.compare(x, y);
}
public static short reverseBytes(short value) {
return java.lang.Short.reverseBytes(value);
}
public static int toUnsignedInt(short x) {
return java.lang.Short.toUnsignedInt(x);
}
public static long toUnsignedLong(short x) {
return java.lang.Short.toUnsignedLong(x);
}
public static short parseShort(String s, int radix) throws NumberFormatException {
return java.lang.Short.parseShort(String.fromDJVM(s), radix);
}
public static short parseShort(String s) throws NumberFormatException {
return java.lang.Short.parseShort(String.fromDJVM(s));
}
public static Short valueOf(String s, int radix) throws NumberFormatException {
return toDJVM(java.lang.Short.valueOf(String.fromDJVM(s), radix));
}
public static Short valueOf(String s) throws NumberFormatException {
return toDJVM(java.lang.Short.valueOf(String.fromDJVM(s)));
}
public static Short valueOf(short s) {
return new Short(s);
}
public static Short decode(String nm) throws NumberFormatException {
return toDJVM(java.lang.Short.decode(String.fromDJVM(nm)));
}
public static Short toDJVM(java.lang.Short i) {
return (i == null) ? null : valueOf(i);
}
}

View File

@ -1,46 +0,0 @@
package sandbox.java.lang;
import org.jetbrains.annotations.NotNull;
/**
* This is a dummy class. We will load the genuine class at runtime.
*/
public final class StackTraceElement extends Object implements java.io.Serializable {
private final String className;
private final String methodName;
private final String fileName;
private final int lineNumber;
public StackTraceElement(String className, String methodName, String fileName, int lineNumber) {
this.className = className;
this.methodName = methodName;
this.fileName = fileName;
this.lineNumber = lineNumber;
}
public String getClassName() {
return className;
}
public String getMethodName() {
return methodName;
}
public String getFileName() {
return fileName;
}
public int getLineNumber() {
return lineNumber;
}
@Override
@NotNull
public String toDJVMString() {
return String.toDJVM(
className.toString() + ':' + methodName.toString()
+ (fileName != null ? '(' + fileName.toString() + ':' + lineNumber + ')' : "")
);
}
}

View File

@ -1,424 +0,0 @@
package sandbox.java.lang;
import net.corda.djvm.SandboxRuntimeContext;
import org.jetbrains.annotations.NotNull;
import sandbox.java.nio.charset.Charset;
import sandbox.java.util.Comparator;
import sandbox.java.util.Locale;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor;
@SuppressWarnings("unused")
public final class String extends Object implements Comparable<String>, CharSequence, Serializable {
public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator();
private static class CaseInsensitiveComparator extends Object implements Comparator<String>, Serializable {
@Override
public int compare(String s1, String s2) {
return java.lang.String.CASE_INSENSITIVE_ORDER.compare(String.fromDJVM(s1), String.fromDJVM(s2));
}
}
private static final String TRUE = new String("true");
private static final String FALSE = new String("false");
private static final Constructor SHARED;
static {
try {
SHARED = java.lang.String.class.getDeclaredConstructor(char[].class, java.lang.Boolean.TYPE);
SHARED.setAccessible(true);
} catch (NoSuchMethodException e) {
throw new NoSuchMethodError(e.getMessage());
}
}
private final java.lang.String value;
public String() {
this.value = "";
}
public String(java.lang.String value) {
this.value = value;
}
public String(char value[]) {
this.value = new java.lang.String(value);
}
public String(char value[], int offset, int count) {
this.value = new java.lang.String(value, offset, count);
}
public String(int[] codePoints, int offset, int count) {
this.value = new java.lang.String(codePoints, offset, count);
}
@Deprecated
public String(byte ascii[], int hibyte, int offset, int count) {
this.value = new java.lang.String(ascii, hibyte, offset, count);
}
@Deprecated
public String(byte ascii[], int hibyte) {
this.value = new java.lang.String(ascii, hibyte);
}
public String(byte bytes[], int offset, int length, String charsetName)
throws UnsupportedEncodingException {
this.value = new java.lang.String(bytes, offset, length, fromDJVM(charsetName));
}
public String(byte bytes[], int offset, int length, Charset charset) {
this.value = new java.lang.String(bytes, offset, length, fromDJVM(charset));
}
public String(byte bytes[], String charsetName)
throws UnsupportedEncodingException {
this.value = new java.lang.String(bytes, fromDJVM(charsetName));
}
public String(byte bytes[], Charset charset) {
this.value = new java.lang.String(bytes, fromDJVM(charset));
}
public String(byte bytes[], int offset, int length) {
this.value = new java.lang.String(bytes, offset, length);
}
public String(byte bytes[]) {
this.value = new java.lang.String(bytes);
}
public String(StringBuffer buffer) {
this.value = buffer.toString();
}
public String(StringBuilder builder) {
this.value = builder.toString();
}
String(char[] value, boolean share) {
java.lang.String newValue;
try {
// This is (presumably) an optimisation for memory usage.
newValue = (java.lang.String) SHARED.newInstance(value, share);
} catch (Exception e) {
newValue = new java.lang.String(value);
}
this.value = newValue;
}
@Override
public char charAt(int index) {
return value.charAt(index);
}
@Override
public int length() {
return value.length();
}
public boolean isEmpty() {
return value.isEmpty();
}
public int codePointAt(int index) {
return value.codePointAt(index);
}
public int codePointBefore(int index) {
return value.codePointBefore(index);
}
public int codePointCount(int beginIndex, int endIndex) {
return value.codePointCount(beginIndex, endIndex);
}
public int offsetByCodePoints(int index, int codePointOffset) {
return value.offsetByCodePoints(index, codePointOffset);
}
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
value.getChars(srcBegin, srcEnd, dst, dstBegin);
}
@Deprecated
public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) {
value.getBytes(srcBegin, srcEnd, dst, dstBegin);
}
public byte[] getBytes(String charsetName) throws UnsupportedEncodingException {
return value.getBytes(fromDJVM(charsetName));
}
public byte[] getBytes(Charset charset) {
return value.getBytes(fromDJVM(charset));
}
public byte[] getBytes() {
return value.getBytes();
}
@Override
public boolean equals(java.lang.Object other) {
return (other instanceof String) && ((String) other).value.equals(value);
}
@Override
public int hashCode() {
return value.hashCode();
}
@Override
@NotNull
public java.lang.String toString() {
return value;
}
@Override
@NotNull
public String toDJVMString() {
return this;
}
@Override
@NotNull
java.lang.String fromDJVM() {
return value;
}
public boolean contentEquals(StringBuffer sb) {
return value.contentEquals((CharSequence) sb);
}
public boolean contentEquals(CharSequence cs) {
return value.contentEquals(cs);
}
public boolean equalsIgnoreCase(String anotherString) {
return value.equalsIgnoreCase(fromDJVM(anotherString));
}
@Override
public CharSequence subSequence(int start, int end) {
return toDJVM((java.lang.String) value.subSequence(start, end));
}
@Override
public int compareTo(@NotNull String other) {
return value.compareTo(other.toString());
}
public int compareToIgnoreCase(String str) {
return value.compareToIgnoreCase(fromDJVM(str));
}
public boolean regionMatches(int toffset, String other, int ooffset, int len) {
return value.regionMatches(toffset, fromDJVM(other), ooffset, len);
}
public boolean regionMatches(boolean ignoreCase, int toffset,
String other, int ooffset, int len) {
return value.regionMatches(ignoreCase, toffset, fromDJVM(other), ooffset, len);
}
public boolean startsWith(String prefix, int toffset) {
return value.startsWith(fromDJVM(prefix), toffset);
}
public boolean startsWith(String prefix) {
return value.startsWith(fromDJVM(prefix));
}
public boolean endsWith(String suffix) {
return value.endsWith(fromDJVM(suffix));
}
public int indexOf(int ch) {
return value.indexOf(ch);
}
public int indexOf(int ch, int fromIndex) {
return value.indexOf(ch, fromIndex);
}
public int lastIndexOf(int ch) {
return value.lastIndexOf(ch);
}
public int lastIndexOf(int ch, int fromIndex) {
return value.lastIndexOf(ch, fromIndex);
}
public int indexOf(String str) {
return value.indexOf(fromDJVM(str));
}
public int indexOf(String str, int fromIndex) {
return value.indexOf(fromDJVM(str), fromIndex);
}
public int lastIndexOf(String str) {
return value.lastIndexOf(fromDJVM(str));
}
public int lastIndexOf(String str, int fromIndex) {
return value.lastIndexOf(fromDJVM(str), fromIndex);
}
public String substring(int beginIndex) {
return toDJVM(value.substring(beginIndex));
}
public String substring(int beginIndex, int endIndex) {
return toDJVM(value.substring(beginIndex, endIndex));
}
public String concat(String str) {
return toDJVM(value.concat(fromDJVM(str)));
}
public String replace(char oldChar, char newChar) {
return toDJVM(value.replace(oldChar, newChar));
}
public boolean matches(String regex) {
return value.matches(fromDJVM(regex));
}
public boolean contains(CharSequence s) {
return value.contains(s);
}
public String replaceFirst(String regex, String replacement) {
return toDJVM(value.replaceFirst(fromDJVM(regex), fromDJVM(replacement)));
}
public String replaceAll(String regex, String replacement) {
return toDJVM(value.replaceAll(fromDJVM(regex), fromDJVM(replacement)));
}
public String replace(CharSequence target, CharSequence replacement) {
return toDJVM(value.replace(target, replacement));
}
public String[] split(String regex, int limit) {
return toDJVM(value.split(fromDJVM(regex), limit));
}
public String[] split(String regex) {
return toDJVM(value.split(fromDJVM(regex)));
}
public String toLowerCase(Locale locale) {
return toDJVM(value.toLowerCase(fromDJVM(locale)));
}
public String toLowerCase() {
return toDJVM(value.toLowerCase());
}
public String toUpperCase(Locale locale) {
return toDJVM(value.toUpperCase(fromDJVM(locale)));
}
public String toUpperCase() {
return toDJVM(value.toUpperCase());
}
public String trim() {
return toDJVM(value.trim());
}
public String intern() { return (String) SandboxRuntimeContext.getInstance().intern(value, this); }
public char[] toCharArray() {
return value.toCharArray();
}
public static String format(String format, java.lang.Object... args) {
return toDJVM(java.lang.String.format(fromDJVM(format), fromDJVM(args)));
}
public static String format(Locale locale, String format, java.lang.Object... args) {
return toDJVM(java.lang.String.format(fromDJVM(locale), fromDJVM(format), fromDJVM(args)));
}
public static String join(CharSequence delimiter, CharSequence... elements) {
return toDJVM(java.lang.String.join(delimiter, elements));
}
public static String join(CharSequence delimiter,
Iterable<? extends CharSequence> elements) {
return toDJVM(java.lang.String.join(delimiter, elements));
}
public static String valueOf(java.lang.Object obj) {
return (obj instanceof Object) ? ((Object) obj).toDJVMString() : toDJVM(java.lang.String.valueOf(obj));
}
public static String valueOf(char data[]) {
return toDJVM(java.lang.String.valueOf(data));
}
public static String valueOf(char data[], int offset, int count) {
return toDJVM(java.lang.String.valueOf(data, offset, count));
}
public static String copyValueOf(char data[], int offset, int count) {
return toDJVM(java.lang.String.copyValueOf(data, offset, count));
}
public static String copyValueOf(char data[]) {
return toDJVM(java.lang.String.copyValueOf(data));
}
public static String valueOf(boolean b) {
return b ? TRUE : FALSE;
}
public static String valueOf(char c) {
return toDJVM(java.lang.String.valueOf(c));
}
public static String valueOf(int i) {
return toDJVM(java.lang.String.valueOf(i));
}
public static String valueOf(long l) {
return toDJVM(java.lang.String.valueOf(l));
}
public static String valueOf(float f) {
return toDJVM(java.lang.String.valueOf(f));
}
public static String valueOf(double d) {
return toDJVM(java.lang.String.valueOf(d));
}
static String[] toDJVM(java.lang.String[] value) {
if (value == null) {
return null;
}
String[] result = new String[value.length];
int i = 0;
for (java.lang.String v : value) {
result[i] = toDJVM(v);
++i;
}
return result;
}
public static String toDJVM(java.lang.String value) {
return (value == null) ? null : new String(value);
}
public static java.lang.String fromDJVM(String value) {
return (value == null) ? null : value.fromDJVM();
}
}

View File

@ -1,20 +0,0 @@
package sandbox.java.lang;
import java.io.Serializable;
/**
* This is a dummy class that implements just enough of {@link java.lang.StringBuffer}
* to allow us to compile {@link sandbox.java.lang.String}.
*/
public abstract class StringBuffer extends Object implements CharSequence, Appendable, Serializable {
@Override
public abstract StringBuffer append(CharSequence seq);
@Override
public abstract StringBuffer append(CharSequence seq, int start, int end);
@Override
public abstract StringBuffer append(char c);
}

View File

@ -1,20 +0,0 @@
package sandbox.java.lang;
import java.io.Serializable;
/**
* This is a dummy class that implements just enough of {@link java.lang.StringBuilder}
* to allow us to compile {@link sandbox.java.lang.String}.
*/
public abstract class StringBuilder extends Object implements Appendable, CharSequence, Serializable {
@Override
public abstract StringBuilder append(CharSequence seq);
@Override
public abstract StringBuilder append(CharSequence seq, int start, int end);
@Override
public abstract StringBuilder append(char c);
}

View File

@ -1,23 +0,0 @@
package sandbox.java.lang;
import net.corda.djvm.SandboxRuntimeContext;
@SuppressWarnings({"WeakerAccess", "unused"})
public final class System extends Object {
private System() {}
public static int identityHashCode(java.lang.Object obj) {
int nativeHashCode = java.lang.System.identityHashCode(obj);
return SandboxRuntimeContext.getInstance().getHashCodeFor(nativeHashCode);
}
public static final String lineSeparator = String.toDJVM("\n");
public static void arraycopy(java.lang.Object src, int srcPos, java.lang.Object dest, int destPos, int length) {
java.lang.System.arraycopy(src, srcPos, dest, destPos, length);
}
public static void runFinalization() {}
public static void gc() {}
}

View File

@ -1,59 +0,0 @@
package sandbox.java.lang;
import sandbox.java.util.function.Supplier;
/**
* Everything inside the sandbox is single-threaded, so this
* implementation of ThreadLocal is sufficient.
* @param <T> Underlying type of this thread-local variable.
*/
@SuppressWarnings({"unused", "WeakerAccess"})
public class ThreadLocal<T> extends Object {
private T value;
private boolean isSet;
public ThreadLocal() {
}
protected T initialValue() {
return null;
}
public T get() {
if (!isSet) {
set(initialValue());
}
return value;
}
public void set(T value) {
this.value = value;
this.isSet = true;
}
public void remove() {
value = null;
isSet = false;
}
public static <V> ThreadLocal<V> withInitial(Supplier<? extends V> supplier) {
return new SuppliedThreadLocal<>(supplier);
}
// Stub class for compiling ThreadLocal. The sandbox will import the
// actual SuppliedThreadLocal class at run-time. Having said that, we
// still need a working implementation here for the sake of our tests.
static final class SuppliedThreadLocal<T> extends ThreadLocal<T> {
private final Supplier<? extends T> supplier;
SuppliedThreadLocal(Supplier<? extends T> supplier) {
this.supplier = supplier;
}
@Override
protected T initialValue() {
return supplier.get();
}
}
}

View File

@ -1,137 +0,0 @@
package sandbox.java.lang;
import org.jetbrains.annotations.NotNull;
import sandbox.TaskTypes;
import java.io.Serializable;
@SuppressWarnings({"unused", "WeakerAccess"})
public class Throwable extends Object implements Serializable {
private static final StackTraceElement[] NO_STACK_TRACE = new StackTraceElement[0];
private String message;
private Throwable cause;
private StackTraceElement[] stackTrace;
public Throwable() {
this.cause = this;
fillInStackTrace();
}
public Throwable(String message) {
this();
this.message = message;
}
public Throwable(Throwable cause) {
this.cause = cause;
this.message = (cause == null) ? null : cause.toDJVMString();
fillInStackTrace();
}
public Throwable(String message, Throwable cause) {
this.message = message;
this.cause = cause;
fillInStackTrace();
}
protected Throwable(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
if (writableStackTrace) {
fillInStackTrace();
} else {
stackTrace = NO_STACK_TRACE;
}
this.message = message;
this.cause = cause;
}
public String getMessage() {
return message;
}
public String getLocalizedMessage() {
return getMessage();
}
public Throwable getCause() {
return (cause == this) ? null : cause;
}
public Throwable initCause(Throwable cause) {
if (this.cause != this) {
throw new java.lang.IllegalStateException(
"Can't overwrite cause with " + java.util.Objects.toString(cause, "a null"), fromDJVM());
}
if (cause == this) {
throw new java.lang.IllegalArgumentException("Self-causation not permitted", fromDJVM());
}
this.cause = cause;
return this;
}
@Override
@NotNull
public String toDJVMString() {
java.lang.String s = getClass().getName();
String localized = getLocalizedMessage();
return String.valueOf((localized != null) ? (s + ": " + localized.toString()) : s);
}
public StackTraceElement[] getStackTrace() {
return (stackTrace == NO_STACK_TRACE) ? stackTrace : stackTrace.clone();
}
public void setStackTrace(StackTraceElement[] stackTrace) {
StackTraceElement[] traceCopy = stackTrace.clone();
for (int i = 0; i < traceCopy.length; ++i) {
if (traceCopy[i] == null) {
throw new java.lang.NullPointerException("stackTrace[" + i + ']');
}
}
this.stackTrace = traceCopy;
}
@SuppressWarnings({"ThrowableNotThrown", "UnusedReturnValue"})
public Throwable fillInStackTrace() {
if (stackTrace == null) {
/*
* We have been invoked from within this exception's constructor.
* Work our way up the stack trace until we find this constructor,
* and then find out who actually invoked it. This is where our
* sandboxed stack trace will start from.
*
* Our stack trace will end at the point where we entered the sandbox.
*/
final java.lang.StackTraceElement[] elements = new java.lang.Throwable().getStackTrace();
final java.lang.String exceptionName = getClass().getName();
int startIdx = 1;
while (startIdx < elements.length && !isConstructorFor(elements[startIdx], exceptionName)) {
++startIdx;
}
while (startIdx < elements.length && isConstructorFor(elements[startIdx], exceptionName)) {
++startIdx;
}
int endIdx = startIdx;
while (endIdx < elements.length && !TaskTypes.isEntryPoint(elements[endIdx])) {
++endIdx;
}
stackTrace = (startIdx == elements.length) ? NO_STACK_TRACE : DJVM.copyToDJVM(elements, startIdx, endIdx);
}
return this;
}
private static boolean isConstructorFor(java.lang.StackTraceElement elt, java.lang.String className) {
return elt.getClassName().equals(className) && elt.getMethodName().equals("<init>");
}
public void printStackTrace() {}
@Override
@NotNull
java.lang.Throwable fromDJVM() {
return DJVM.fromDJVM(this);
}
}

View File

@ -1,18 +0,0 @@
package sandbox.java.nio.charset;
/**
* This is a dummy class that implements just enough of {@link java.nio.charset.Charset}
* to allow us to compile {@link sandbox.java.lang.String}.
*/
@SuppressWarnings("unused")
public abstract class Charset extends sandbox.java.lang.Object {
private final sandbox.java.lang.String canonicalName;
protected Charset(sandbox.java.lang.String canonicalName, sandbox.java.lang.String[] aliases) {
this.canonicalName = canonicalName;
}
public final sandbox.java.lang.String name() {
return canonicalName;
}
}

View File

@ -1,9 +0,0 @@
package sandbox.java.util;
/**
* This is a dummy class that implements just enough of {@link java.util.Comparator}
* to allow us to compile {@link sandbox.java.lang.String}.
*/
@FunctionalInterface
public interface Comparator<T> extends java.util.Comparator<T> {
}

View File

@ -1,13 +0,0 @@
package sandbox.java.util;
/**
* This is a dummy class to bootstrap us into the sandbox.
*/
public class LinkedHashMap<K, V> extends java.util.LinkedHashMap<K, V> implements Map<K, V> {
public LinkedHashMap(int initialSize) {
super(initialSize);
}
public LinkedHashMap() {
}
}

View File

@ -1,9 +0,0 @@
package sandbox.java.util;
/**
* This is a dummy class that implements just enough of {@link java.util.Locale}
* to allow us to compile {@link sandbox.java.lang.String}.
*/
public abstract class Locale extends sandbox.java.lang.Object {
public abstract sandbox.java.lang.String toLanguageTag();
}

View File

@ -1,7 +0,0 @@
package sandbox.java.util;
/**
* This is a dummy class to bootstrap us into the sandbox.
*/
public interface Map<K, V> extends java.util.Map<K, V> {
}

View File

@ -1,10 +0,0 @@
package sandbox.java.util.function;
/**
* This is a dummy class that implements just enough of {@link java.util.function.Function}
* to allow us to compile {@link sandbox.Task}.
*/
@FunctionalInterface
public interface Function<T, R> {
R apply(T item);
}

View File

@ -1,10 +0,0 @@
package sandbox.java.util.function;
/**
* This is a dummy class that implements just enough of @{link java.util.function.Supplier}
* to allow us to compile {@link sandbox.java.lang.ThreadLocal}.
*/
@FunctionalInterface
public interface Supplier<T> {
T get();
}

View File

@ -1,10 +0,0 @@
package sandbox.sun.misc;
import sandbox.java.lang.Enum;
@SuppressWarnings("unused")
public interface JavaLangAccess {
<E extends Enum<E>> E[] getEnumConstantsShared(Class<E> enumClass);
}

View File

@ -1,20 +0,0 @@
package sandbox.sun.misc;
import sandbox.java.lang.Enum;
@SuppressWarnings("unused")
public class SharedSecrets extends sandbox.java.lang.Object {
private static final JavaLangAccess javaLangAccess = new JavaLangAccessImpl();
private static class JavaLangAccessImpl implements JavaLangAccess {
@SuppressWarnings("unchecked")
@Override
public <E extends Enum<E>> E[] getEnumConstantsShared(Class<E> enumClass) {
return (E[]) sandbox.java.lang.DJVM.getEnumConstantsShared(enumClass);
}
}
public static JavaLangAccess getJavaLangAccess() {
return javaLangAccess;
}
}

View File

@ -1,68 +0,0 @@
package net.corda.djvm
import net.corda.djvm.analysis.AnalysisConfiguration
import net.corda.djvm.code.DefinitionProvider
import net.corda.djvm.code.EMIT_TRACING
import net.corda.djvm.code.Emitter
import net.corda.djvm.execution.ExecutionProfile
import net.corda.djvm.rewiring.SandboxClassLoader
import net.corda.djvm.rules.Rule
import net.corda.djvm.utilities.Discovery
/**
* Configuration to use for the deterministic sandbox.
*
* @property rules The rules to apply during the analysis phase.
* @property emitters The code emitters / re-writers to apply to all loaded classes.
* @property definitionProviders The meta-data providers to apply to class and member definitions.
* @property executionProfile The execution profile to use in the sandbox.
* @property analysisConfiguration The configuration used in the analysis of classes.
* @property parentClassLoader The [SandboxClassLoader] that this sandbox will use as a parent.
*/
class SandboxConfiguration private constructor(
val rules: List<Rule>,
val emitters: List<Emitter>,
val definitionProviders: List<DefinitionProvider>,
val executionProfile: ExecutionProfile,
val analysisConfiguration: AnalysisConfiguration,
val parentClassLoader: SandboxClassLoader?
) {
@Suppress("unused")
companion object {
/**
* Default configuration for the deterministic sandbox.
*/
@JvmField
val DEFAULT = SandboxConfiguration.of()
/**
* Configuration with no emitters, rules, meta-data providers or runtime thresholds.
*/
@JvmField
val EMPTY = SandboxConfiguration.of(
ExecutionProfile.UNLIMITED, emptyList(), emptyList(), emptyList()
)
/**
* Create a sandbox configuration where one or more properties deviates from the default.
*/
fun of(
profile: ExecutionProfile = ExecutionProfile.DEFAULT,
rules: List<Rule> = Discovery.find(),
emitters: List<Emitter>? = null,
definitionProviders: List<DefinitionProvider> = Discovery.find(),
enableTracing: Boolean = true,
analysisConfiguration: AnalysisConfiguration = AnalysisConfiguration.createRoot(),
parentClassLoader: SandboxClassLoader? = null
) = SandboxConfiguration(
executionProfile = profile,
rules = rules,
emitters = (emitters ?: Discovery.find()).filter {
enableTracing || it.priority > EMIT_TRACING
},
definitionProviders = definitionProviders,
analysisConfiguration = analysisConfiguration,
parentClassLoader = parentClassLoader
)
}
}

Some files were not shown because too many files have changed in this diff Show More