Skip to content

Commit bab9f9c

Browse files
Shenoda Guirguisatoomula
Shenoda Guirguis
authored andcommitted
Making Samza-Sql-Shell commands pluggable by adding CommandHandler (#1106)
1 parent e0ea235 commit bab9f9c

22 files changed

+986
-703
lines changed

samza-sql-shell/conf/shell-defaults.conf

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
# Example:
2323
shell.executor = org.apache.samza.sql.client.impl.SamzaExecutor
2424
samza.sql.output = compact
25+
# shell.commandhandlers = org.apache.samza.CustomeCommandHandler1, com.linkedin.CustomeCommandHandler2
2526
# samza.sql.system.kafka.address = localhost:2181
2627
# samza.sql.relSchemaProvider.config.schemaDir = /tmp/schemas/
2728
# samza.sql.ioResolver = config

samza-sql-shell/src/main/java/org/apache/samza/sql/client/cli/CliCommand.java

+7-5
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,25 @@
1919

2020
package org.apache.samza.sql.client.cli;
2121

22+
import org.apache.samza.sql.client.interfaces.CommandType;
23+
2224
/**
2325
* A shell command containing command name and parameters.
2426
*/
25-
class CliCommand {
26-
private CliCommandType commandType;
27+
public class CliCommand {
28+
private CommandType commandType;
2729
private String parameters;
2830

29-
public CliCommand(CliCommandType cmdType) {
31+
public CliCommand(CommandType cmdType) {
3032
this.commandType = cmdType;
3133
}
3234

33-
public CliCommand(CliCommandType cmdType, String parameters) {
35+
public CliCommand(CommandType cmdType, String parameters) {
3436
this(cmdType);
3537
this.parameters = parameters;
3638
}
3739

38-
public CliCommandType getCommandType() {
40+
public CommandType getCommandType() {
3941
return commandType;
4042
}
4143

samza-sql-shell/src/main/java/org/apache/samza/sql/client/cli/CliConstants.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
/**
2323
* Constant definitions for the shell.
2424
*/
25-
class CliConstants {
25+
public class CliConstants {
2626
public static final String APP_NAME = "Samza SQL Shell";
2727
public static final String WINDOW_TITLE = "Samza SQL Shell";
2828
public static final String PROMPT_1ST = "Samza SQL";
@@ -32,6 +32,7 @@ class CliConstants {
3232
public static final String CONFIG_SHELL_PREFIX = "shell.";
3333
// Specifies the executor used by the shell
3434
public static final String CONFIG_EXECUTOR = "shell.executor";
35+
public static final String CONFIG_COMMAND_HANDLER = "shell.commandhandlers";
3536
public static final String DEFAULT_EXECUTOR_CLASS = "org.apache.samza.sql.client.impl.SamzaExecutor";
3637

3738
public static final String WELCOME_MESSAGE;

samza-sql-shell/src/main/java/org/apache/samza/sql/client/cli/CliEnvironment.java

+57-15
Original file line numberDiff line numberDiff line change
@@ -19,30 +19,34 @@
1919

2020
package org.apache.samza.sql.client.cli;
2121

22+
import java.io.PrintWriter;
23+
import java.lang.reflect.Constructor;
24+
import java.lang.reflect.InvocationTargetException;
25+
import java.util.ArrayList;
26+
import java.util.Arrays;
27+
import java.util.HashMap;
28+
import java.util.List;
29+
import java.util.Map;
30+
import org.apache.samza.sql.client.exceptions.CommandHandlerException;
31+
import org.apache.samza.sql.client.interfaces.CommandHandler;
2232
import org.apache.samza.sql.client.interfaces.EnvironmentVariableHandler;
2333
import org.apache.samza.sql.client.interfaces.EnvironmentVariableSpecs;
24-
import org.apache.samza.sql.client.interfaces.ExecutorException;
34+
import org.apache.samza.sql.client.exceptions.ExecutorException;
2535
import org.apache.samza.sql.client.interfaces.SqlExecutor;
26-
import org.apache.samza.sql.client.util.CliException;
36+
import org.apache.samza.sql.client.exceptions.CliException;
2737
import org.apache.samza.sql.client.util.CliUtil;
2838
import org.apache.samza.sql.client.util.Pair;
2939
import org.slf4j.Logger;
3040
import org.slf4j.LoggerFactory;
3141

32-
import java.io.PrintWriter;
33-
import java.lang.reflect.Constructor;
34-
import java.lang.reflect.InvocationTargetException;
35-
import java.util.HashMap;
36-
import java.util.List;
37-
import java.util.Map;
38-
3942
/**
4043
* CliEnvironment handles "environment variables" that configures the shell behavior.
4144
*/
42-
class CliEnvironment {
45+
public class CliEnvironment {
4346
private EnvironmentVariableHandler shellEnvHandler;
4447
private EnvironmentVariableHandler executorEnvHandler;
4548
private SqlExecutor executor;
49+
private List<CommandHandler> commandHandlers;
4650
private Map<String, String> delayedExecutorVars;
4751

4852
// shell.executor is special and is specifically handled by CliEnvironment
@@ -51,6 +55,7 @@ class CliEnvironment {
5155

5256
CliEnvironment() {
5357
shellEnvHandler = new CliShellEnvironmentVariableHandler();
58+
commandHandlers = new ArrayList<>();
5459
}
5560

5661
/** Sets the value of an environment variable.
@@ -61,14 +66,23 @@ class CliEnvironment {
6166
* -1: invalid name
6267
* -2: invalid value
6368
*/
64-
int setEnvironmentVariable(String name, String value) throws ExecutorException{
69+
public int setEnvironmentVariable(String name, String value) throws ExecutorException, CommandHandlerException {
70+
name = name.toLowerCase();
6571
if(name.equals(CliConstants.CONFIG_EXECUTOR)) {
6672
createShellExecutor(value);
6773
activeExecutorClassName = value;
6874
executorEnvHandler = executor.getEnvironmentVariableHandler();
6975
return 0;
7076
}
7177

78+
if (name.equals(CliConstants.CONFIG_COMMAND_HANDLER)) {
79+
List<String> commandHandlersNames = Arrays.asList(value.split(","));
80+
for (String commandHandlerName : commandHandlersNames) {
81+
createCommandHandler(commandHandlerName.trim());
82+
}
83+
return 0;
84+
}
85+
7286
EnvironmentVariableHandler handler = getAppropriateHandler(name);
7387
if(handler == null) {
7488
// Shell doesn't recognize this variable. There's no executor handler yet. Save for future executor
@@ -132,7 +146,7 @@ public void printAll(PrintWriter writer) {
132146
* Gives CliEnvironment a chance to apply settings, especially during initialization, things like
133147
* making default values take effect
134148
*/
135-
public void finishInitialization() {
149+
public void finishInitialization() throws CliException {
136150
if(executor == null) {
137151
try {
138152
createShellExecutor(CliConstants.DEFAULT_EXECUTOR_CLASS);
@@ -144,7 +158,7 @@ public void finishInitialization() {
144158
}
145159
delayedExecutorVars = null;
146160
}
147-
} catch (ExecutorException e) {
161+
} catch (ExecutorException | CommandHandlerException e) {
148162
// Convert checked exception ExecutorException to an unchecked exception as
149163
// we have failed to create even the default executor thus not recoverable
150164
throw new CliException(e);
@@ -173,11 +187,39 @@ public SqlExecutor getExecutor() {
173187
return executor;
174188
}
175189

190+
public List<CommandHandler> getCommandHandlers() { return commandHandlers; }
191+
176192
private void createShellExecutor(String executorClassName) throws ExecutorException {
177193
try {
178-
Class<?> clazz = Class.forName(executorClassName);
194+
executor = (SqlExecutor) createInstance(executorClassName);
195+
} catch (ClassCastException e) {
196+
String errMsg = String.format("Error trying to cast Object of class %s to SqlExecutor", executorClassName);
197+
LOG.error(errMsg);
198+
throw new ExecutorException(errMsg, e);
199+
} catch (Exception e) {
200+
LOG.error(e.getMessage());
201+
throw new ExecutorException(e);
202+
}
203+
}
204+
205+
private void createCommandHandler(String handlerClassName) throws CommandHandlerException {
206+
try {
207+
commandHandlers.add((CommandHandler) createInstance(handlerClassName));
208+
} catch (ClassCastException e) {
209+
String errMsg = String.format("Error trying to cast Object of class %s to CommandHandler", handlerClassName);
210+
LOG.error(errMsg);
211+
throw new CommandHandlerException(errMsg, e);
212+
} catch (Exception e) {
213+
LOG.error(e.getMessage());
214+
throw new CommandHandlerException(e);
215+
}
216+
}
217+
218+
private Object createInstance(String className) throws Exception {
219+
try {
220+
Class<?> clazz = Class.forName(className);
179221
Constructor<?> ctor = clazz.getConstructor();
180-
executor = (SqlExecutor) ctor.newInstance();
222+
return ctor.newInstance();
181223
} catch (ClassNotFoundException | NoSuchMethodException
182224
| IllegalAccessException | InstantiationException | InvocationTargetException e) {
183225
throw new ExecutorException(e);

samza-sql-shell/src/main/java/org/apache/samza/sql/client/cli/CliHighlighter.java

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
package org.apache.samza.sql.client.cli;
2121

22+
import org.apache.samza.sql.client.impl.CliCommandType;
2223
import org.apache.samza.sql.client.util.CliUtil;
2324
import org.jline.reader.Highlighter;
2425
import org.jline.reader.LineReader;

0 commit comments

Comments
 (0)