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="common-configuration-parsing_main" 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_test" 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_canonicalizer_main" 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_test" 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="node-api_main" target="1.8" />
<module name="node-api_test" target="1.8" />
<module name="node-capsule_main" target="1.6" />
<module name="node-capsule_test" target="1.6" />
<module name="node-capsule_main" target="1.8" />
<module name="node-capsule_test" target="1.8" />
<module name="node-driver_integrationTest" target="1.8" />
<module name="node-driver_main" 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_smokeTest" 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_test" 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_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.
// We must configure it manually to use the latest capsule version.
@ -22,10 +42,12 @@ buildscript {
ext.asm_version = '5.0.4'
ext.artemis_version = '2.6.2'
ext.jackson_version = '2.9.8'
ext.jetty_version = '9.4.7.v20170914'
// upgrade Jackson only when corda is using kotlin 1.3.10
ext.jackson_version = '2.9.5'
ext.jetty_version = '9.4.18.v20190429'
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.log4j_version = '2.9.1'
ext.bouncycastle_version = constants.getProperty("bouncycastleVersion")
@ -34,14 +56,22 @@ buildscript {
ext.disruptor_version = constants.getProperty("disruptorVersion")
ext.metrics_version = constants.getProperty("metricsVersion")
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.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'
// 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_kotlin_version = '1.5.0'
ext.hamkrest_version = '1.4.2.2'
ext.mockito_kotlin_version = '1.6.0'
ext.hamkrest_version = '1.7.0.0'
ext.jopt_simple_version = '5.0.2'
ext.jansi_version = '1.14'
ext.hibernate_version = '5.3.10.Final'
@ -50,7 +80,7 @@ buildscript {
ext.rxjava_version = '1.3.8'
ext.dokka_version = '0.9.17'
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.beanutils_version = '1.9.3'
ext.crash_version = '810d2b774b85d4938be01b9b65e29e4fddbc450b'
@ -61,8 +91,8 @@ buildscript {
ext.liquibase_version = '3.5.5'
ext.artifactory_contextUrl = 'https://ci-artifactory.corda.r3cev.com/artifactory'
ext.snake_yaml_version = constants.getProperty('snakeYamlVersion')
ext.docker_compose_rule_version = '0.33.0'
ext.selenium_version = '3.8.1'
ext.docker_compose_rule_version = '0.35.0'
ext.selenium_version = '3.141.59'
ext.ghostdriver_version = '2.1.0'
ext.eaagentloader_version = '1.0.3'
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 "org.owasp:dependency-check-gradle:${dependency_checker_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 {
// 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.
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 {
@ -208,6 +236,8 @@ allprojects {
// Prevent the project from creating temporary files outside of the build directory.
systemProperty 'java.io.tmpdir', buildDir.absolutePath
maxHeapSize = "1g"
if (project.hasProperty('test.parallel') && project.property('test.parallel').toBoolean()) {
maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) as int ?: 1
}
@ -366,6 +396,7 @@ bintrayConfig {
'corda-node-api',
'corda-test-common',
'corda-test-utils',
'corda-test-db',
'corda-jackson',
'corda-webserver-impl',
'corda-webserver',
@ -461,8 +492,10 @@ if (file('corda-docs-only-build').exists() || (System.getenv('CORDA_DOCS_ONLY_BU
}
}
wrapper {
gradleVersion = "4.10.1"
gradleVersion = "5.4.1"
distributionType = Wrapper.DistributionType.ALL
}

View File

@ -18,8 +18,16 @@ dependencies {
testCompile project(':test-utils')
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 "junit:junit:$junit_version"
}
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. */
val availableCommands: Map<String, String>
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 paramNames = methodParamNames[name]!!
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> {
assertThat(fieldNames()).containsOnly(*fieldNames)
assertThat(fieldNames()).toIterable().containsOnly(*fieldNames)
return fieldNames.map { this[it] }
}

View File

@ -44,7 +44,13 @@ dependencies {
compile "org.apache.activemq:artemis-core-client:${artemis_version}"
// 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 project(':test-utils')

View File

@ -13,8 +13,14 @@ dependencies {
compile project(':finance:workflows')
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.
testCompile "junit:junit:$junit_version"
testCompile "org.assertj:assertj-core:${assertj_version}"
testCompile project(':test-utils')

View File

@ -9,10 +9,10 @@ description 'Corda client RPC modules'
//noinspection GroovyAssignabilityCheck
configurations {
integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime
integrationTestRuntimeOnly.extendsFrom testRuntimeOnly
smokeTestCompile.extendsFrom compile
smokeTestRuntime.extendsFrom runtime
smokeTestRuntimeOnly.extendsFrom runtimeOnly
}
compileKotlin {
@ -74,9 +74,13 @@ dependencies {
// For caches rather than guava
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.
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
testCompile "junit:junit:$junit_version"
testCompile "org.assertj:assertj-core:${assertj_version}"
testCompile project(':node-driver')
@ -91,7 +95,9 @@ dependencies {
smokeTestCompile "org.apache.logging.log4j:log4j-core:$log4j_version"
smokeTestCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_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) {

View File

@ -21,6 +21,7 @@ import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration
import org.apache.activemq.artemis.api.core.SimpleString
import org.junit.After
import org.junit.Assert.*
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import rx.Observable
@ -498,6 +499,7 @@ class RPCStabilityTests {
}
@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`() {
rpcDriver {
val server = startRpcServer(maxBufferedBytesPerClient = 10 * 1024 * 1024, ops = SlowConsumerRPCOpsImpl()).get()
@ -508,7 +510,7 @@ class RPCStabilityTests {
session.createTemporaryQueue(myQueue, ActiveMQDefaultConfiguration.getDefaultRoutingType(), myQueue)
val consumer = session.createConsumer(myQueue, null, -1, -1, false)
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()
}
val producer = session.createProducer(RPCApi.RPC_SERVER_QUEUE_NAME)
@ -520,7 +522,7 @@ class RPCStabilityTests {
val request = RPCApi.ClientToServer.RpcRequest(
clientAddress = SimpleString(myQueue),
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(),
sessionId = Trace.SessionId.newInstance()
)
@ -529,7 +531,7 @@ class RPCStabilityTests {
producer.send(message)
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)
}
}

View File

@ -23,7 +23,6 @@ import net.corda.serialization.internal.amqp.SerializationFactoryCacheKey
import net.corda.serialization.internal.amqp.SerializerFactory
import java.time.Duration
import java.util.ServiceLoader
import java.net.URLClassLoader
/**
* 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 {
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 (classLoader != null) {
val customSerializers = createInstancesOfClassesImplementing(classLoader, SerializationCustomSerializer::class.java)
val serializationWhitelists = ServiceLoader.load(SerializationWhitelist::class.java, classLoader).toSet()
AMQPClientSerializationScheme.initialiseSerialization(classLoader, customSerializers, serializationWhitelists, cache)
} else {
AMQPClientSerializationScheme.initialiseSerialization(classLoader, serializerFactoriesForContexts = cache)
}
// If the client has explicitly provided a classloader use this one to scan for custom serializers, otherwise use the current one.
val serializationClassLoader = this.classLoader ?: this.javaClass.classLoader
val customSerializers = createInstancesOfClassesImplementing(serializationClassLoader, SerializationCustomSerializer::class.java)
val serializationWhitelists = ServiceLoader.load(SerializationWhitelist::class.java, serializationClassLoader).toSet()
AMQPClientSerializationScheme.initialiseSerialization(serializationClassLoader, customSerializers, serializationWhitelists, cache)
} catch (e: IllegalStateException) {
// 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 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: "junit", name: "junit", version: junit_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: 'com.jfrog.artifactory'
@ -8,15 +9,23 @@ dependencies {
compile group: "org.jetbrains.kotlin", name: "kotlin-reflect", version: kotlin_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"
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 {
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 {
companion object {
private const val UNKNOWN = "Unknown"
const val current_major_release = "4.0-SNAPSHOT"
const val platformEditionCode = "OS"
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 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> {

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')
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)
testCompile "com.google.guava:guava-testlib:$guava_version"
@ -26,8 +31,6 @@ dependencies {
jar {
baseName 'corda-confidential-identities'
preserveFileTimestamps = false
reproducibleFileOrder = true
}
publish {

View File

@ -3,7 +3,7 @@ package net.corda.confidential
import co.paralleluniverse.fibers.Suspendable
import com.natpryce.hamkrest.MatchResult
import com.natpryce.hamkrest.Matcher
import com.natpryce.hamkrest.assertion.assert
import com.natpryce.hamkrest.assertion.assertThat
import com.natpryce.hamkrest.equalTo
import net.corda.core.crypto.DigitalSignature
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.flow.willReturn
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.junit.AfterClass
import org.junit.Test
@ -45,7 +48,7 @@ class SwapIdentitiesFlowTests {
@Test
fun `issue key`() {
assert.that(
assertThat(
aliceNode.services.startFlow(SwapIdentitiesInitiator(bob)),
willReturn(
hasOnlyEntries(

View File

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

View File

@ -12,10 +12,13 @@ dependencies {
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.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.

View File

@ -12,7 +12,11 @@ dependencies {
testCompile "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
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

View File

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

View File

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

View File

@ -11,10 +11,10 @@ evaluationDependsOn(':node:capsule')
configurations {
integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime
integrationTestRuntimeOnly.extendsFrom testRuntimeOnly
smokeTestCompile.extendsFrom compile
smokeTestRuntime.extendsFrom runtime
smokeTestRuntimeOnly.extendsFrom runtimeOnly
}
sourceSets {
@ -54,7 +54,13 @@ processSmokeTestResources {
}
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"
// Guava: Google test library (collections test suite)
@ -87,9 +93,15 @@ dependencies {
compile "com.github.ben-manes.caffeine:caffeine:$caffeine_version"
// 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 "org.assertj:assertj-core:${assertj_version}"
smokeTestCompile "junit:junit:$junit_version"
// RxJava: observable streams of events.
compile "io.reactivex:rxjava:$rxjava_version"
@ -97,7 +109,8 @@ dependencies {
// 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.
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/
compile "net.i2p.crypto:eddsa:$eddsa_version"
@ -128,7 +141,12 @@ jar {
}
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) {
@ -152,6 +170,35 @@ task smokeTest(type: Test) {
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 {
testArtifacts testJar
}

View File

@ -1,5 +1,7 @@
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.services.Vault
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].
*/
@CordaSerializable
@KeepForDJVM
sealed class StatePointer<T : ContractState> {
/**
* 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.
*/
@DeleteForDJVM
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
* throw a [TransactionResolutionException]
*/
@KeepForDJVM
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.
*/
@Throws(TransactionResolutionException::class)
@Suppress("UNCHECKED_CAST")
@DeleteForDJVM
override fun resolve(services: ServiceHub): StateAndRef<T> {
val transactionState = services.loadState(pointer) as TransactionState<T>
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
* 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>() {
/**
* 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.
*/
@Suppress("UNCHECKED_CAST")
@DeleteForDJVM
override fun resolve(services: ServiceHub): StateAndRef<T> {
// Return the latest version of the linear state.
// 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.
*/
@CordaSerializable
@KeepForDJVM
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,
* 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,
"""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.
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,
"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.
/** Thrown during classloading upon encountering an untrusted attachment (eg. not in the [TRUSTED_UPLOADERS] list) */
@KeepForDJVM
@CordaSerializable
class UntrustedAttachmentsException(val txId: SecureHash, val ids: List<SecureHash>) :
CordaException("Attempting to load untrusted transaction attachments: $ids. " +
"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.crypto.newSecureRandom
import org.apache.commons.lang.SystemUtils
import org.apache.commons.lang3.SystemUtils
import java.security.Provider
import java.security.SecureRandom
import java.security.SecureRandomSpi

View File

@ -83,12 +83,12 @@ data class CordaX500Name(val commonName: String?,
@JvmStatic
fun build(principal: X500Principal): CordaX500Name {
val attrsMap = principal.toAttributesMap(supportedAttributes)
val CN = attrsMap[BCStyle.CN]?.toString()
val OU = attrsMap[BCStyle.OU]?.toString()
val O = requireNotNull(attrsMap[BCStyle.O]?.toString()) { "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 ST = attrsMap[BCStyle.ST]?.toString()
val C = requireNotNull(attrsMap[BCStyle.C]?.toString()) { "Corda X.500 names must include an C attribute" }
val CN = attrsMap[BCStyle.CN]
val OU = attrsMap[BCStyle.OU]
val O = requireNotNull(attrsMap[BCStyle.O]) { "Corda X.500 names must include an O attribute" }
val L = requireNotNull(attrsMap[BCStyle.L]) { "Corda X.500 names must include an L attribute" }
val ST = attrsMap[BCStyle.ST]
val C = requireNotNull(attrsMap[BCStyle.C]) { "Corda X.500 names must include an C attribute" }
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.StatePointer
import org.apache.commons.lang3.reflect.FieldUtils
import java.lang.reflect.Field
import java.util.*
@ -25,20 +26,9 @@ class StatePointerSearch(val state: ContractState) {
// Queue of fields to search.
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.
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 ->
// 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.
*
*/
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 attrsMap: Map<ASN1ObjectIdentifier, ASN1Encodable> = x500Name.rdNs
val attrsMap: Map<ASN1ObjectIdentifier, String> = x500Name.rdNs
.flatMap { it.typesAndValues.asList() }
.groupBy(AttributeTypeAndValue::getType, AttributeTypeAndValue::getValue)
.mapValues {
require(it.value.size == 1) { "Duplicate attribute ${it.key}" }
it.value[0]
it.value[0].toString()
}
if (supportedAttributes.isNotEmpty()) {
(attrsMap.keys - supportedAttributes).let { unsupported ->

View File

@ -19,6 +19,7 @@ import java.io.IOException
import java.io.InputStream
import java.net.*
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
@ -139,7 +140,7 @@ class AttachmentsClassLoader(attachments: List<Attachment>,
attachment.openAsJAR().use { jar ->
while (true) {
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
@ -190,7 +191,7 @@ class AttachmentsClassLoader(attachments: List<Attachment>,
// 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.
val classLoaderEntries = mutableMapOf<String, Attachment>()
val classLoaderEntries = mutableMapOf<String, SecureHash.SHA256>()
for (attachment in attachments) {
// We may have been given an attachment loaded from the database in which case, important info like
// 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.
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.
if (path in classLoaderEntries.keys) {
val contentHash = readAttachment(attachment, path).sha256()
val originalAttachment = classLoaderEntries[path]!!
val originalContentHash = readAttachment(originalAttachment, path).sha256()
if (contentHash == originalContentHash) {
log.debug { "Duplicate entry $path has same content hash $contentHash" }
continue
} else {
// This calculates the hash of the current entry because the JarInputStream returns only the current entry.
fun entryHash() = ByteArrayOutputStream().use {
jar.copyTo(it)
it.toByteArray()
}.sha256()
// If 2 entries are identical, it means the same file is present in both attachments, so that is ok.
val currentHash = entryHash()
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" }
throw OverlappingAttachmentsException(sampleTxId, path)
}
}
log.debug { "Adding new entry for $path" }
classLoaderEntries[path] = attachment
}
}
log.debug { "${classLoaderEntries.size} classloaded entries for $attachment" }

View File

@ -1,6 +1,6 @@
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 java.math.BigInteger
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.EdDSANamedCurveTable
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.x509.SubjectPublicKeyInfo
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 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.crypto.SecureHash
import net.corda.core.flows.mixins.WithMockNet
@ -48,18 +48,18 @@ class AttachmentTests : WithMockNet {
val id = aliceNode.importAttachment(fakeAttachment("file1.txt", "Some useful content"))
// Get node one to run a flow to fetch it and insert it.
assert.that(
assertThat(
bobNode.startAttachmentFlow(id, alice),
willReturn(noAttachments()))
// Verify it was inserted into node one's store.
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.
aliceNode.dispose()
assert.that(
assertThat(
bobNode.startAttachmentFlow(id, alice),
willReturn(soleAttachment(attachment)))
}
@ -69,7 +69,7 @@ class AttachmentTests : WithMockNet {
val hash: SecureHash = SecureHash.randomSHA256()
// Get node one to fetch a non-existent attachment.
assert.that(
assertThat(
bobNode.startAttachmentFlow(hash, alice),
willThrow(withRequestedHash(hash)))
}
@ -97,7 +97,7 @@ class AttachmentTests : WithMockNet {
badAliceNode.updateAttachment(corruptAttachment)
// Get n1 to fetch the attachment. Should receive corrupted bytes.
assert.that(
assertThat(
bobNode.startAttachmentFlow(id, badAlice),
willThrow<FetchDataFlow.DownloadedVsRequestedDataMismatch>()
)

View File

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

View File

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

View File

@ -1,7 +1,7 @@
package net.corda.core.flows
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.flows.mixins.WithContracts
import net.corda.core.flows.mixins.WithFinality
@ -59,24 +59,24 @@ class ContractUpgradeFlowTest : WithContracts, WithFinality {
val bobTx = bobNode.getValidatedTransaction(stx)
// The request is expected to be rejected because party B hasn't authorised the upgrade yet.
assert.that(
assertThat(
aliceNode.initiateContractUpgrade(aliceTx, DummyContractV2::class),
willThrow<UnexpectedFlowEndException>())
// Party B authorises the contract state upgrade, and immediately de-authorises the same.
assert.that(bobNode.authoriseContractUpgrade(bobTx, DummyContractV2::class), willReturn())
assert.that(bobNode.deauthoriseContractUpgrade(bobTx), willReturn())
assertThat(bobNode.authoriseContractUpgrade(bobTx, DummyContractV2::class), willReturn())
assertThat(bobNode.deauthoriseContractUpgrade(bobTx), willReturn())
// 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),
willThrow<UnexpectedFlowEndException>())
// 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.
assert.that(
assertThat(
aliceNode.initiateContractUpgrade(aliceTx, DummyContractV2::class),
willReturn(
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.
// 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.
assert.that(
assertThat(
aliceNode.initiateContractUpgrade(upgradedState, DummyContractV3::class),
willReturn(
aliceNode.hasContractUpgradeTransaction<DummyContractV2.State, DummyContractV3.State>()
@ -125,14 +125,14 @@ class ContractUpgradeFlowTest : WithContracts, WithFinality {
val stateAndRef = cashFlowResult.stx.tx.outRef<Cash.State>(0)
// 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.
assert.that(aliceNode.initiateContractUpgrade(stateAndRef, CashV2::class), willReturn())
assertThat(aliceNode.initiateContractUpgrade(stateAndRef, CashV2::class), willReturn())
// Get contract state from the vault.
val upgradedState = aliceNode.getCashStateFromVault()
assert.that(upgradedState,
assertThat(upgradedState,
hasIssuedAmount(Amount(1000000, USD) `issued by` (alice.ref(1)))
and belongsTo(anonymisedRecipient))
@ -146,8 +146,8 @@ class ContractUpgradeFlowTest : WithContracts, WithFinality {
addCommand(CashV2.Move(), alice.owningKey)
}
assert.that(aliceNode.finalise(spendUpgradedTx), willReturn())
assert.that(aliceNode.getCashStateFromVault(), hasContractState(equalTo(movedState)))
assertThat(aliceNode.finalise(spendUpgradedTx), willReturn())
assertThat(aliceNode.getCashStateFromVault(), hasContractState(equalTo(movedState)))
}
class CashV2 : UpgradedContractWithLegacyConstraint<Cash.State, CashV2.State> {

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
package net.corda.core.utilities
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 kotlin.test.assertEquals
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