Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions client/build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
plugins {
id 'java-test-fixtures'
id 'com.palantir.docker' version "${dockerPluginVersion}"
id 'net.ltgt.errorprone' version "${errorpronePluginVersion}"
id "com.github.spotbugs" version "${spotbugsPluginVersion}"
Expand Down Expand Up @@ -33,6 +34,10 @@ dependencies {
api group: 'org.glassfish', name: 'javax.json', version: "${jsonpVersion}"
api group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: "${jacksonVersion}"

// for tests
testFixturesImplementation group: 'info.picocli', name: 'picocli', version: "${picoCliVersion}"
testFixturesImplementation group: 'org.assertj', name: 'assertj-core', version: "${assertjVersion}"

// for Error Prone
errorprone "com.google.errorprone:error_prone_core:${errorproneVersion}"
errorproneJavac "com.google.errorprone:javac:${errorproneJavacVersion}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ public enum ClientError implements ScalarDlError {
StatusCode.RUNTIME_ERROR, "003", "Shutting down the channel failed. Details: %s", "", ""),
PROCESSING_JSON_FAILED(
StatusCode.RUNTIME_ERROR, "004", "Processing JSON failed. Details: %s", "", ""),
CLASS_FILE_LOAD_FAILED(
StatusCode.RUNTIME_ERROR, "005", "Failed to load the class file. File: %s", "", ""),
;

private static final String COMPONENT_NAME = "DL-CLIENT";
Expand Down
6 changes: 3 additions & 3 deletions client/src/main/java/com/scalar/dl/client/tool/Common.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class Common {
static final String SCALARDL_GC_SUBCOMMAND_NAME = "generic-contracts";
static final String SCALARDL_GC_ALIAS = "gc";

static JsonNode getValidationResult(LedgerValidationResult result) {
public static JsonNode getValidationResult(LedgerValidationResult result) {
ObjectNode json =
mapper.createObjectNode().put(Common.STATUS_CODE_KEY, result.getCode().toString());
json.set("Ledger", getProof(result.getLedgerProof().orElse(null)));
Expand Down Expand Up @@ -55,7 +55,7 @@ static void printOutput(@Nullable JsonNode value) {
printJson(json);
}

static void printError(ClientException e) {
public static void printError(ClientException e) {
JsonNode json =
mapper
.createObjectNode()
Expand All @@ -64,7 +64,7 @@ static void printError(ClientException e) {
printJson(json);
}

static void printJson(JsonNode json) {
public static void printJson(JsonNode json) {
try {
System.out.println(mapper.writeValueAsString(json));
} catch (JsonProcessingException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,26 @@ public class CommonOptions {
names = {"-h", "--help"},
usageHelp = true,
description = "display the help message.")
boolean helpRequested;
protected boolean helpRequested;

@CommandLine.Option(
names = {"--properties", "--config"},
required = true,
paramLabel = "PROPERTIES_FILE",
description = "A configuration file in properties format.")
String properties;
protected String properties;

@CommandLine.Option(
names = {"--stacktrace"},
description = "output Java Stack Trace to stderr stream.")
boolean stacktraceEnabled;
protected boolean stacktraceEnabled;

@CommandLine.Option(
names = {"-g", "--use-gateway"},
paramLabel = "USE_GATEWAY",
defaultValue = "false",
description = "A flag to use the gateway.")
boolean useGateway;
protected boolean useGateway;

/**
* Outputs Java stack trace to stderr stream by using {@link Exception#printStackTrace()} when the
Expand Down
23 changes: 23 additions & 0 deletions client/src/main/java/com/scalar/dl/client/util/Common.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

import com.scalar.dl.client.error.ClientError;
import com.scalar.dl.client.exception.ClientException;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;

public class Common {
private static final int CLASS_LOAD_BUFFER_SIZE = 4096;

public static byte[] fileToBytes(String filePath) {
try {
Expand All @@ -15,4 +18,24 @@ public static byte[] fileToBytes(String filePath) {
throw new ClientException(ClientError.READING_FILE_FAILED, e, filePath, e.getMessage());
}
}

public static byte[] getClassBytes(Class<?> clazz) {
String classResourcePath = clazz.getName().replace('.', '/') + ".class";
try (InputStream is = clazz.getClassLoader().getResourceAsStream(classResourcePath)) {
if (is == null) {
throw new ClientException(ClientError.CLASS_FILE_LOAD_FAILED, clazz.getName());
}

ByteArrayOutputStream buffer = new ByteArrayOutputStream();
byte[] tmp = new byte[CLASS_LOAD_BUFFER_SIZE];
int bytesRead;
while ((bytesRead = is.read(tmp)) != -1) {
buffer.write(tmp, 0, bytesRead);
}
return buffer.toByteArray();
} catch (IOException e) {
throw new RuntimeException(
ClientError.CLASS_FILE_LOAD_FAILED.buildMessage(clazz.getName()), e);
Comment on lines +37 to +38

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

For better consistency and error handling, it's preferable to throw a ClientException here instead of a generic RuntimeException. The rest of the client code, including the fileToBytes method in this same class, uses ClientException for expected error conditions. This allows callers to handle specific errors more gracefully rather than catching a broad RuntimeException.

      throw new ClientException(ClientError.CLASS_FILE_LOAD_FAILED, e, clazz.getName());

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public class Constants {
public static final String CONTRACT_INSERT = PACKAGE + "." + VERSION + ".Insert";
public static final String CONTRACT_SELECT = PACKAGE + "." + VERSION + ".Select";
public static final String CONTRACT_UPDATE = PACKAGE + "." + VERSION + ".Update";
public static final String CONTRACT_SHOW_TABLES = PACKAGE + "." + VERSION + ".ShowTables";
public static final String CONTRACT_GET_HISTORY = PACKAGE + "." + VERSION + ".GetHistory";
public static final String CONTRACT_GET_ASSET_ID = PACKAGE + "." + VERSION + ".GetAssetId";
public static final String CONTRACT_SCAN = PACKAGE + "." + VERSION + ".Scan";

Expand Down
20 changes: 20 additions & 0 deletions table-store/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@ plugins {
id "com.github.spotbugs" version "${spotbugsPluginVersion}"
}

apply plugin:'application'
startScripts.enabled = false

dependencies {
implementation project(':client')
implementation project(':generic-contracts')
implementation project(':ledger') // to use JacksonBasedContract
implementation group: 'info.picocli', name: 'picocli', version: "${picoCliVersion}"
implementation group: 'org.partiql', name: 'partiql-parser', version: "${partiqlVersion}"

// for test
testImplementation testFixtures(project(':client')) // to use CommandLineTestUtils

// for Error Prone
errorprone "com.google.errorprone:error_prone_core:${errorproneVersion}"
errorproneJavac "com.google.errorprone:javac:${errorproneJavacVersion}"
Expand All @@ -18,6 +26,18 @@ dependencies {
testCompileOnly "com.github.spotbugs:spotbugs-annotations:${spotbugsVersion}"
}

task TableStore(type: CreateStartScripts) {
mainClass = 'com.scalar.dl.tablestore.client.tool.TableStoreCommandLine'
applicationName = 'scalardl-table-store'
outputDir = new File(project.buildDir, 'tmp')
classpath = jar.outputs.files + project.configurations.runtimeClasspath
}

applicationDistribution.into('bin') {
from(TableStore)
fileMode = 0755
}

spotless {
java {
target 'src/*/java/**/*.java'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ public enum TableStoreClientError implements ScalarDlError {
"The limit clause is not supported except in the history query.",
"",
""),
MULTIPLE_STATEMENTS_NOT_SUPPORTED(
StatusCode.INVALID_ARGUMENT, "028", "Multiple statements are not supported.", "", ""),
;

private static final String COMPONENT_NAME = "DL-TABLE-STORE";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.scalar.dl.tablestore.client.model;

import com.google.common.collect.ImmutableList;
import com.scalar.dl.ledger.model.ContractExecutionResult;
import com.scalar.dl.ledger.proof.AssetProof;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import javax.annotation.concurrent.Immutable;

/**
* The result of statement execution. It contains the result of the statement execution along with a
* list of {@link AssetProof}s from Ledger and Auditor.
*/
@Immutable
// non-final for mocking
public class StatementExecutionResult {
private final String result;
private final ImmutableList<AssetProof> ledgerProofs;
private final ImmutableList<AssetProof> auditorProofs;

/**
* Constructs a {@code StatementExecutionResult} using the specified {@code
* ContractExecutionResult}
*
* @param contractExecutionResult a {@code ContractExecutionResult}
*/
public StatementExecutionResult(ContractExecutionResult contractExecutionResult) {
this.result = contractExecutionResult.getContractResult().orElse(null);
this.ledgerProofs = ImmutableList.copyOf(contractExecutionResult.getLedgerProofs());
this.auditorProofs = ImmutableList.copyOf(contractExecutionResult.getAuditorProofs());
}

/**
* Returns the result of statement execution.
*
* @return the result of statement execution
*/
public Optional<String> getResult() {
return Optional.ofNullable(result);
}

/**
* Returns the list of {@link AssetProof}s from Ledger.
*
* @return the list of {@link AssetProof}s from Ledger
*/
public List<AssetProof> getLedgerProofs() {
return ledgerProofs;
}

/**
* Returns the list of {@link AssetProof}s from Auditor.
*
* @return the list of {@link AssetProof}s from Auditor
*/
public List<AssetProof> getAuditorProofs() {
return auditorProofs;
}

/**
* Returns a hash code value for the object.
*
* @return a hash code value for this object.
*/
@Override
public int hashCode() {
return Objects.hash(result, ledgerProofs, auditorProofs);
}

/**
* Indicates whether some other object is "equal to" this object. The other object is considered
* equal if it is the same instance or if:
*
* <ul>
* <li>it is also an {@code StatementExecutionResult} and
* <li>both instances have the same result and proofs.
* </ul>
*
* @param o an object to be tested for equality
* @return {@code true} if the other object is "equal to" this object otherwise {@code false}
*/
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof StatementExecutionResult)) {
return false;
}
StatementExecutionResult other = (StatementExecutionResult) o;
return Objects.equals(this.result, other.result)
&& this.ledgerProofs.equals(other.ledgerProofs)
&& this.auditorProofs.equals(other.auditorProofs);
}
}
Loading