From 118d1b31f5f7771023766fd72a8229db80f1f5a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 2 Feb 2021 04:28:36 +0100 Subject: [PATCH] fix: make compiled statements immutable (#843) --- .../ClientSideStatementExecutor.java | 13 ------------- .../connection/ClientSideStatementImpl.java | 11 +++++++---- .../ClientSideStatementNoParamExecutor.java | 14 +++++++++----- .../ClientSideStatementSetExecutor.java | 18 ++++++++++++------ 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementExecutor.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementExecutor.java index 2468193918..7ec0976669 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementExecutor.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementExecutor.java @@ -16,8 +16,6 @@ package com.google.cloud.spanner.connection; -import com.google.cloud.spanner.connection.ClientSideStatementImpl.CompileException; - /** * A {@link ClientSideStatementExecutor} is used to compile {@link ClientSideStatement}s from the * json source file, and to execute these against a {@link Connection} (through a {@link @@ -25,17 +23,6 @@ */ interface ClientSideStatementExecutor { - /** - * Compiles the given {@link ClientSideStatementImpl} and registers this statement with this - * executor. A statement must be compiled before it can be executed. The parser automatically - * compiles all available statements during initialization. - * - * @param statement The statement to compile. - * @throws CompileException If the statement could not be compiled. This should never happen, as - * it would indicate that an invalid statement has been defined in the source file. - */ - void compile(ClientSideStatementImpl statement) throws CompileException; - /** * Executes the {@link ClientSideStatementImpl} that has been compiled and registered with this * executor on the specified connection. diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementImpl.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementImpl.java index 7621a0ced5..e9c9c1654e 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementImpl.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementImpl.java @@ -19,6 +19,7 @@ import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.connection.StatementResult.ResultType; import com.google.common.base.Preconditions; +import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Collections; import java.util.List; @@ -143,10 +144,12 @@ public String getMessage() { ClientSideStatementImpl compile() throws CompileException { try { this.pattern = Pattern.compile(regex); - this.executor = - (ClientSideStatementExecutor) - Class.forName(getClass().getPackage().getName() + "." + executorName).newInstance(); - this.executor.compile(this); + @SuppressWarnings("unchecked") + Constructor constructor = + (Constructor) + Class.forName(getClass().getPackage().getName() + "." + executorName) + .getDeclaredConstructor(ClientSideStatementImpl.class); + this.executor = constructor.newInstance(this); return this; } catch (Exception e) { throw new CompileException(e, this); diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementNoParamExecutor.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementNoParamExecutor.java index 4c31e3e28d..6f5e683ce6 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementNoParamExecutor.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementNoParamExecutor.java @@ -24,12 +24,16 @@ * SHOW AUTOCOMMIT. The executor just calls a method with no parameters. */ class ClientSideStatementNoParamExecutor implements ClientSideStatementExecutor { - private Method method; + private final Method method; - ClientSideStatementNoParamExecutor() {} - - @Override - public void compile(ClientSideStatementImpl statement) throws CompileException { + /** + * Creates and compiles the given {@link ClientSideStatementImpl}. + * + * @param statement The statement to compile. + * @throws CompileException If the statement could not be compiled. This should never happen, as + * it would indicate that an invalid statement has been defined in the source file. + */ + ClientSideStatementNoParamExecutor(ClientSideStatementImpl statement) throws CompileException { try { this.method = ConnectionStatementExecutor.class.getDeclaredMethod(statement.getMethodName()); } catch (NoSuchMethodException | SecurityException e) { diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementSetExecutor.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementSetExecutor.java index 54765282f5..4f4fe14042 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementSetExecutor.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementSetExecutor.java @@ -30,14 +30,20 @@ * AUTOCOMMIT=TRUE. */ class ClientSideStatementSetExecutor implements ClientSideStatementExecutor { - private ClientSideStatementImpl statement; - private Method method; - private ClientSideStatementValueConverter converter; - private Pattern allowedValuesPattern; + private final ClientSideStatementImpl statement; + private final Method method; + private final ClientSideStatementValueConverter converter; + private final Pattern allowedValuesPattern; + /** + * Creates and compiles the given {@link ClientSideStatementImpl}. + * + * @param statement The statement to compile. + * @throws CompileException If the statement could not be compiled. This should never happen, as + * it would indicate that an invalid statement has been defined in the source file. + */ @SuppressWarnings("unchecked") - @Override - public void compile(ClientSideStatementImpl statement) throws CompileException { + ClientSideStatementSetExecutor(ClientSideStatementImpl statement) throws CompileException { Preconditions.checkNotNull(statement.getSetStatement()); try { this.statement = statement;