├── .gitignore
├── resources
├── architecture.png
├── architecture.psd
├── spash-logo.png
└── spash-logo.psd
├── core
├── src
│ ├── main
│ │ ├── resources
│ │ │ ├── hdfs-site.xml
│ │ │ └── log4j.properties
│ │ └── java
│ │ │ └── it
│ │ │ └── nerdammer
│ │ │ └── spash
│ │ │ └── shell
│ │ │ ├── SpashShellFactory.java
│ │ │ ├── command
│ │ │ ├── Command.java
│ │ │ ├── spi
│ │ │ │ ├── UnknownCommand.java
│ │ │ │ ├── NoOpCommand.java
│ │ │ │ ├── ExitCommand.java
│ │ │ │ ├── PwdCommand.java
│ │ │ │ ├── EchoCommand.java
│ │ │ │ ├── MkDirCommand.java
│ │ │ │ ├── RmDirCommand.java
│ │ │ │ ├── HeadCommand.java
│ │ │ │ ├── CatCommand.java
│ │ │ │ ├── CdCommand.java
│ │ │ │ ├── WriteCommand.java
│ │ │ │ ├── RmCommand.java
│ │ │ │ ├── GrepCommand.java
│ │ │ │ └── LsCommand.java
│ │ │ ├── ExecutionContext.java
│ │ │ ├── AbstractCommand.java
│ │ │ ├── CommandResult.java
│ │ │ ├── CommandFactory.java
│ │ │ ├── ExpressionTokenizer.java
│ │ │ └── CommandTokenizer.java
│ │ │ ├── api
│ │ │ ├── fs
│ │ │ │ ├── SpashFileSystem.java
│ │ │ │ ├── FileSystemFacade.java
│ │ │ │ └── FileSystemFacadeImpl.java
│ │ │ └── spark
│ │ │ │ ├── SpashSparkSubsystem.java
│ │ │ │ ├── SparkFacade.java
│ │ │ │ └── SparkFacadeImpl.java
│ │ │ ├── common
│ │ │ ├── SerializableFunction.java
│ │ │ ├── SpashCollectionEmptyAdapter.java
│ │ │ ├── SpashCollectionRDDAdapter.java
│ │ │ ├── SpashCollectionUnionAdapter.java
│ │ │ ├── SpashCollection.java
│ │ │ ├── SpashCollectionListAdapter.java
│ │ │ └── TabulatedValue.java
│ │ │ ├── SpashExitException.java
│ │ │ ├── Spash.java
│ │ │ ├── SpashSession.java
│ │ │ ├── SpashCommandCompleter.java
│ │ │ ├── SpashConfig.java
│ │ │ ├── SshServerFactory.java
│ │ │ └── SpashShell.java
│ └── test
│ │ └── java
│ │ └── it
│ │ └── nerdammer
│ │ └── spash
│ │ └── shell
│ │ └── command
│ │ ├── ExpressionTokenizerTest.java
│ │ └── CommandTokenizerTest.java
└── pom.xml
├── release
├── src
│ ├── conf
│ │ └── spash.properties
│ ├── assembly
│ │ ├── bin.xml
│ │ └── assembly-1.1.3.xsd
│ └── bin
│ │ └── spash.sh
└── pom.xml
├── pom.xml
├── README.md
└── LICENSE
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .idea/*
3 | *.ser
4 | target
5 | */target
6 | */*.iml
--------------------------------------------------------------------------------
/resources/architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdammer/spash/HEAD/resources/architecture.png
--------------------------------------------------------------------------------
/resources/architecture.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdammer/spash/HEAD/resources/architecture.psd
--------------------------------------------------------------------------------
/resources/spash-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdammer/spash/HEAD/resources/spash-logo.png
--------------------------------------------------------------------------------
/resources/spash-logo.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdammer/spash/HEAD/resources/spash-logo.psd
--------------------------------------------------------------------------------
/core/src/main/resources/hdfs-site.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | dfs.client.use.datanode.hostname
5 | true
6 |
7 |
--------------------------------------------------------------------------------
/release/src/conf/spash.properties:
--------------------------------------------------------------------------------
1 | # Configuration file for Spash
2 |
3 | # Spash Configuration
4 | spash.listen.port=2222
5 | spash.key.algorithm=RSA
6 | spash.key.length=2048
7 |
8 | # HDFS Configuration
9 | spash.hdfs.host=quickstart
10 | spash.hdfs.port=8020
11 |
12 |
--------------------------------------------------------------------------------
/core/src/main/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | # Root logger option
2 | log4j.rootLogger=DEBUG, stdout
3 |
4 | # Direct log messages to stdout
5 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender
6 | log4j.appender.stdout.Target=System.out
7 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
8 | log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/SpashShellFactory.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell;
2 |
3 | import org.apache.sshd.common.Factory;
4 | import org.apache.sshd.server.Command;
5 |
6 | /**
7 | * The factory of the Spash shell.
8 | *
9 | * @author Nicola Ferraro
10 | */
11 | public class SpashShellFactory implements Factory {
12 |
13 | public Command create()
14 | {
15 | return new SpashShell();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/command/Command.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.command;
2 |
3 | import it.nerdammer.spash.shell.SpashSession;
4 |
5 | /**
6 | * An abstract Spash command.
7 | *
8 | * @author Nicola Ferraro
9 | */
10 | public interface Command {
11 |
12 | /**
13 | * Executes the command action.
14 | *
15 | * @param ctx the execution context
16 | * @return the associated {@code CommandResult}
17 | */
18 | CommandResult execute(ExecutionContext ctx);
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | it.nerdammer.spash
8 | spash-pom
9 | 0.1
10 |
11 | pom
12 |
13 |
14 | core
15 | release
16 |
17 |
18 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/api/fs/SpashFileSystem.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.api.fs;
2 |
3 | import it.nerdammer.spash.shell.SpashConfig;
4 |
5 | /**
6 | * Holds a reference to the default file system.
7 | *
8 | * @author Nicola Ferraro
9 | */
10 | public final class SpashFileSystem {
11 |
12 | private static final FileSystemFacade FACADE_INSTANCE = new FileSystemFacadeImpl(SpashConfig.getInstance().hdfsHost(), SpashConfig.getInstance().hdfsPort());
13 |
14 | private SpashFileSystem() {
15 | }
16 |
17 | public static FileSystemFacade get() {
18 | return FACADE_INSTANCE;
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/command/spi/UnknownCommand.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.command.spi;
2 |
3 | import it.nerdammer.spash.shell.command.Command;
4 | import it.nerdammer.spash.shell.command.CommandResult;
5 | import it.nerdammer.spash.shell.SpashSession;
6 | import it.nerdammer.spash.shell.command.ExecutionContext;
7 |
8 | /**
9 | * @author Nicola Ferraro
10 | */
11 | public class UnknownCommand implements Command {
12 |
13 | public UnknownCommand(String commandString) {
14 | }
15 |
16 | @Override
17 | public CommandResult execute(ExecutionContext ctx) {
18 | return CommandResult.error(this, "command not found");
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/command/spi/NoOpCommand.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.command.spi;
2 |
3 | import it.nerdammer.spash.shell.command.Command;
4 | import it.nerdammer.spash.shell.command.CommandResult;
5 | import it.nerdammer.spash.shell.SpashSession;
6 | import it.nerdammer.spash.shell.command.ExecutionContext;
7 |
8 | /**
9 | * A command that does not do anything.
10 | *
11 | * @author Nicola Ferraro
12 | */
13 | public class NoOpCommand implements Command {
14 |
15 | public NoOpCommand(String commandStr) {}
16 |
17 | @Override
18 | public CommandResult execute(ExecutionContext ctx) {
19 | return CommandResult.success(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/common/SerializableFunction.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.common;
2 |
3 | import ch.lambdaj.function.convert.Converter;
4 | import org.apache.spark.api.java.function.Function;
5 |
6 | import java.io.Serializable;
7 |
8 | /**
9 | * A {@code Function} that is also {@code Serializable}.
10 | *
11 | * @author Nicola Ferraro
12 | */
13 | public abstract class SerializableFunction implements Function, Converter, Serializable {
14 |
15 | @Override
16 | public R call(T t) throws Exception {
17 | return apply(t);
18 | }
19 |
20 | @Override
21 | public R convert(T t) {
22 | return apply(t);
23 | }
24 |
25 | public abstract R apply(T v1);
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/SpashExitException.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell;
2 |
3 | /**
4 | * An exception that signal the willingness to exit the shell.
5 | *
6 | * @author Nicola Ferraro
7 | */
8 | public class SpashExitException extends RuntimeException {
9 |
10 | public SpashExitException() {
11 | }
12 |
13 | public SpashExitException(String message) {
14 | super(message);
15 | }
16 |
17 | public SpashExitException(String message, Throwable cause) {
18 | super(message, cause);
19 | }
20 |
21 | public SpashExitException(Throwable cause) {
22 | super(cause);
23 | }
24 |
25 | public SpashExitException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
26 | super(message, cause, enableSuppression, writableStackTrace);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/command/spi/ExitCommand.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.command.spi;
2 |
3 | import it.nerdammer.spash.shell.SpashExitException;
4 | import it.nerdammer.spash.shell.command.AbstractCommand;
5 | import it.nerdammer.spash.shell.command.CommandResult;
6 | import it.nerdammer.spash.shell.SpashSession;
7 | import it.nerdammer.spash.shell.command.ExecutionContext;
8 |
9 | import java.util.List;
10 |
11 | /**
12 | * A command that exits the shell.
13 | *
14 | * @author Nicola Ferraro
15 | */
16 | public class ExitCommand extends AbstractCommand {
17 |
18 | public ExitCommand(String commandString) {
19 | super(commandString);
20 | }
21 |
22 | @Override
23 | public CommandResult execute(ExecutionContext ctx) {
24 |
25 | List args = this.getArguments();
26 | if(args.size()>0) {
27 | return CommandResult.error(this, "Unexpected arguments: " + args);
28 | }
29 |
30 | throw new SpashExitException();
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/api/spark/SpashSparkSubsystem.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.api.spark;
2 |
3 | import it.nerdammer.spash.shell.api.fs.FileSystemFacade;
4 | import it.nerdammer.spash.shell.api.fs.FileSystemFacadeImpl;
5 | import org.apache.spark.SparkConf;
6 | import org.apache.spark.api.java.JavaSparkContext;
7 |
8 | /**
9 | * Holds a reference to the Spark context.
10 | *
11 | * @author Nicola Ferraro
12 | */
13 | public class SpashSparkSubsystem {
14 |
15 | private static final SparkFacade FACADE_INSTANCE;
16 |
17 | static {
18 | String master = System.getProperty("spark.master");
19 | if(master==null) {
20 | System.setProperty("spark.master", "local");
21 | }
22 |
23 | SparkConf conf = new SparkConf().setAppName("Spash");
24 | JavaSparkContext sc = new JavaSparkContext(conf);
25 | FACADE_INSTANCE = new SparkFacadeImpl(sc);
26 | }
27 |
28 | private SpashSparkSubsystem() {
29 | }
30 |
31 | public static SparkFacade get() {
32 | return FACADE_INSTANCE;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/release/src/assembly/bin.xml:
--------------------------------------------------------------------------------
1 |
4 | distribution
5 |
6 | tar.gz
7 | dir
8 |
9 |
10 |
11 |
12 | /lib
13 |
14 |
15 |
16 |
17 |
18 | src/bin
19 | bin
20 |
21 | *.sh
22 |
23 |
24 |
25 |
26 | src/conf
27 | conf
28 |
29 | *
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/command/ExecutionContext.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.command;
2 |
3 | import it.nerdammer.spash.shell.SpashSession;
4 |
5 | /**
6 | * The context associated with the execution of a {@code Command}.
7 | *
8 | * @author Nicola Ferraro
9 | */
10 | public class ExecutionContext {
11 |
12 | private SpashSession session;
13 |
14 | private CommandResult previousCommandResult;
15 |
16 | public ExecutionContext() {
17 | }
18 |
19 | public ExecutionContext(SpashSession session, CommandResult previousCommandResult) {
20 | this.session = session;
21 | this.previousCommandResult = previousCommandResult;
22 | }
23 |
24 | public SpashSession getSession() {
25 | return session;
26 | }
27 |
28 | public void setSession(SpashSession session) {
29 | this.session = session;
30 | }
31 |
32 | public CommandResult getPreviousCommandResult() {
33 | return previousCommandResult;
34 | }
35 |
36 | public void setPreviousCommandResult(CommandResult previousCommandResult) {
37 | this.previousCommandResult = previousCommandResult;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/Spash.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell;
2 |
3 | import it.nerdammer.spash.shell.api.fs.SpashFileSystem;
4 | import it.nerdammer.spash.shell.api.spark.SpashSparkSubsystem;
5 | import org.apache.sshd.server.SshServer;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import java.util.Arrays;
10 |
11 | /**
12 | * The main class of the application.
13 | *
14 | * @author Nicola Ferraro
15 | */
16 | public class Spash {
17 |
18 | public static void main(String[] args) throws Exception {
19 |
20 | Logger logger = LoggerFactory.getLogger(Spash.class);
21 |
22 | logger.info("Initializing the file system");
23 | SpashFileSystem.get().getFileSystem();
24 |
25 | logger.info("Initializing Spark by running a simple job");
26 | SpashSparkSubsystem.get().parallelize(Arrays.asList(1, 2, 3)).collect();
27 |
28 | logger.info("Starting the Spash shell");
29 | SshServer server = SshServerFactory.create();
30 | server.start();
31 |
32 | logger.info("Spash shell started");
33 |
34 | synchronized(Spash.class) {
35 | Spash.class.wait();
36 | }
37 |
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/release/src/bin/spash.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Compute the bin path
4 | pushd `dirname $0` > /dev/null
5 | SPASH_BIN=`pwd`
6 | popd > /dev/null
7 |
8 | # Compute the base path
9 | SPASH_BASE=`dirname $SPASH_BIN`
10 |
11 | # Compute the conf path
12 | SPASH_CONF=$SPASH_BASE/conf
13 |
14 | # Compute the lib path
15 | SPASH_LIB=$SPASH_BASE/lib
16 |
17 | # Jar list
18 | APP_JAR_LIST=`ls -dm $SPASH_LIB/* | tr -d ' \r\n'`
19 |
20 | # Main Jar
21 | APP_MAIN_JAR=`echo $APP_JAR_LIST | tr ',' '\n' | grep spash-core`
22 |
23 | # Hdfs Nio Jar
24 | APP_HDFS_NIO_JAR=`echo $APP_JAR_LIST | tr ',' '\n' | grep jsr203hadoop`
25 |
26 | # Jar Classpath
27 | APP_CLASSPATH=`echo $APP_JAR_LIST | tr ',' '\n' | grep -v spash-core | grep -v jsr203hadoop | tr '\n' ':'`
28 |
29 | # Jar csv
30 | APP_JARS_CSV=`echo $APP_CLASSPATH | tr ':' ','`
31 |
32 | echo "Using classpath: $APP_CLASSPATH"
33 | echo "Using main jar: $APP_MAIN_JAR"
34 |
35 | echo "Starting Spash"
36 |
37 | eval "spark-submit --class it.nerdammer.spash.shell.Spash \
38 | --master yarn --deploy-mode client \
39 | --jars $APP_JARS_CSV \
40 | --driver-class-path $APP_HDFS_NIO_JAR \
41 | --driver-java-options \"-Dspash.config.dir=$SPASH_CONF -Dspash.config=$SPASH_CONF/spash.properties\" \
42 | $APP_MAIN_JAR"
43 |
44 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/command/spi/PwdCommand.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.command.spi;
2 |
3 | import it.nerdammer.spash.shell.command.AbstractCommand;
4 | import it.nerdammer.spash.shell.command.CommandResult;
5 | import it.nerdammer.spash.shell.command.ExecutionContext;
6 | import it.nerdammer.spash.shell.common.SpashCollection;
7 | import it.nerdammer.spash.shell.common.SpashCollectionListAdapter;
8 |
9 | import java.util.Collections;
10 | import java.util.List;
11 |
12 | /**
13 | * A command that returns the current directory.
14 | *
15 | * @author Nicola Ferraro
16 | */
17 | public class PwdCommand extends AbstractCommand {
18 |
19 | public PwdCommand(String commandString) {
20 | super(commandString);
21 | }
22 |
23 | @Override
24 | public CommandResult execute(ExecutionContext ctx) {
25 |
26 | List args = this.getArguments();
27 | if(args.size()>0) {
28 | return CommandResult.error(this, "Unexpected arguments: " + args);
29 | }
30 |
31 | SpashCollection content = new SpashCollectionListAdapter<>(Collections.singletonList(ctx.getSession().getWorkingDir()));
32 | return CommandResult.success(this, content);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/SpashSession.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell;
2 |
3 | /**
4 | * Contains all information related to the user's session.
5 | *
6 | * @author Nicola Ferraro
7 | */
8 | public class SpashSession {
9 |
10 | /**
11 | * The default working directory.
12 | */
13 | private static final String DEFAULT_WORKING_DIR = "/";
14 |
15 | /**
16 | * The user connected to this session.
17 | */
18 | private String user;
19 |
20 | /**
21 | * The current working directory.
22 | */
23 | private String workingDir = DEFAULT_WORKING_DIR;
24 |
25 | public SpashSession(String user) {
26 | this.user = user;
27 | }
28 |
29 | public String getUser() {
30 | return user;
31 | }
32 |
33 | public void setUser(String user) {
34 | this.user = user;
35 | }
36 |
37 | public String getWorkingDir() {
38 | return workingDir;
39 | }
40 |
41 | public void setWorkingDir(String workingDir) {
42 | this.workingDir = workingDir;
43 | }
44 |
45 | @Override
46 | public String toString() {
47 | return "SpashSession{" +
48 | "user='" + user + '\'' +
49 | '}';
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/common/SpashCollectionEmptyAdapter.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.common;
2 |
3 | import org.apache.spark.api.java.JavaRDD;
4 | import org.apache.spark.api.java.JavaSparkContext;
5 |
6 | import java.io.PrintWriter;
7 | import java.util.Collections;
8 | import java.util.List;
9 |
10 | /**
11 | * An empty SpashCollection.
12 | *
13 | * @author Nicola Ferraro
14 | */
15 | public class SpashCollectionEmptyAdapter implements SpashCollection {
16 |
17 | public SpashCollectionEmptyAdapter() {
18 | }
19 |
20 | @Override
21 | public void mkString(PrintWriter writer) {
22 | }
23 |
24 | @Override
25 | public SpashCollection map(SerializableFunction f) {
26 | return new SpashCollectionEmptyAdapter<>();
27 | }
28 |
29 | @Override
30 | public SpashCollection union(SpashCollection coll) {
31 | return coll;
32 | }
33 |
34 | @Override
35 | public SpashCollection filter(SerializableFunction condition) {
36 | return this;
37 | }
38 |
39 | @Override
40 | public JavaRDD toRDD(JavaSparkContext sc) {
41 | return sc.emptyRDD();
42 | }
43 |
44 | @Override
45 | public List collect() {
46 | return Collections.emptyList();
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/command/spi/EchoCommand.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.command.spi;
2 |
3 | import it.nerdammer.spash.shell.command.AbstractCommand;
4 | import it.nerdammer.spash.shell.command.CommandResult;
5 | import it.nerdammer.spash.shell.command.ExecutionContext;
6 | import it.nerdammer.spash.shell.common.SpashCollectionListAdapter;
7 |
8 | import java.util.Collections;
9 | import java.util.List;
10 |
11 | /**
12 | * Command to echo the user input.
13 | *
14 | * @author Nicola Ferraro
15 | */
16 | public class EchoCommand extends AbstractCommand {
17 |
18 | public EchoCommand(String commandString) {
19 | super(commandString);
20 | }
21 |
22 | @Override
23 | public CommandResult execute(ExecutionContext ctx) {
24 |
25 | List args = this.getArguments();
26 | if(args.size()==0) {
27 | return CommandResult.error(this, "No arguments provided");
28 | }
29 |
30 | StringBuilder bui = new StringBuilder();
31 | for(int i=0; i stream = Collections.singletonList(bui.toString());
39 | return CommandResult.success(this, new SpashCollectionListAdapter<>(stream));
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/command/spi/MkDirCommand.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.command.spi;
2 |
3 | import it.nerdammer.spash.shell.api.fs.FileSystemFacade;
4 | import it.nerdammer.spash.shell.api.fs.SpashFileSystem;
5 | import it.nerdammer.spash.shell.command.AbstractCommand;
6 | import it.nerdammer.spash.shell.command.CommandResult;
7 | import it.nerdammer.spash.shell.command.ExecutionContext;
8 |
9 | import java.nio.file.Path;
10 | import java.util.List;
11 |
12 | /**
13 | * Command to create a directory.
14 | *
15 | * @author Nicola Ferraro
16 | */
17 | public class MkDirCommand extends AbstractCommand {
18 |
19 | public MkDirCommand(String commandString) {
20 | super(commandString);
21 | }
22 |
23 | @Override
24 | public CommandResult execute(ExecutionContext ctx) {
25 |
26 | FileSystemFacade fs = SpashFileSystem.get();
27 |
28 | List files = this.getArguments();
29 | if(files.size()==0) {
30 | return CommandResult.error(this, "Missing argument");
31 | } else if(files.size()>1) {
32 | return CommandResult.error(this, "Too many arguments");
33 | }
34 |
35 | String file = files.get(0);
36 |
37 | Path path = fs.getAbsolutePath(ctx.getSession().getWorkingDir(), file);
38 | boolean created = fs.mkdir(path.toString());
39 | if(!created) {
40 | return CommandResult.error(this, "File exists");
41 | }
42 |
43 | return CommandResult.success(this);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/api/spark/SparkFacade.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.api.spark;
2 |
3 | import it.nerdammer.spash.shell.common.SpashCollection;
4 |
5 | import java.nio.file.Path;
6 | import java.util.List;
7 |
8 | /**
9 | * Provide useful Spark functions and methods to access HDFS from Spark.
10 | *
11 | * @author Nicola Ferraro
12 | */
13 | public interface SparkFacade {
14 |
15 | /**
16 | * Returns a {@code SpashCollection} from the content of the file or directory.
17 | *
18 | * @param file the file or the directory to read
19 | * @return a collection of lines contained in the file
20 | */
21 | SpashCollection read(Path file);
22 |
23 | /**
24 | * Writes the provided content to the file.
25 | *
26 | * @param content the content
27 | * @param file the output file
28 | */
29 | void write(SpashCollection content, Path file);
30 |
31 | /**
32 | * Returns a {@code SpashCollection} from the first lines of the file or directory.
33 | *
34 | * @param file the file or the directory to read
35 | * @param lines the number of lines to show
36 | * @return a collection of the first lines contained in the file
37 | */
38 | SpashCollection head(Path file, int lines);
39 |
40 | /**
41 | * Parallelizes a collection as an RDD backed {@code SpashCollection}.
42 | *
43 | * @param coll the standard java collection
44 | * @param the type of the contained objects
45 | * @return the parallelized collection
46 | */
47 | SpashCollection parallelize(List coll);
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/common/SpashCollectionRDDAdapter.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.common;
2 |
3 | import org.apache.spark.api.java.JavaRDD;
4 | import org.apache.spark.api.java.JavaSparkContext;
5 |
6 | import java.io.PrintWriter;
7 | import java.util.Iterator;
8 | import java.util.List;
9 |
10 | /**
11 | * Adapts a {@code org.apache.spark.api.java.JavaRDD} to a {@code SpashCollection}.
12 | *
13 | * @author Nicola Ferraro
14 | */
15 | public class SpashCollectionRDDAdapter implements SpashCollection {
16 |
17 | private JavaRDD target;
18 |
19 | public SpashCollectionRDDAdapter(JavaRDD target) {
20 | this.target = target;
21 | }
22 |
23 | @Override
24 | public void mkString(PrintWriter writer) {
25 | Iterator it = target.toLocalIterator();
26 | while(it.hasNext()) {
27 | T el = it.next();
28 | writer.println(el != null ? el.toString() : "");
29 | }
30 | }
31 |
32 | @Override
33 | public SpashCollection map(final SerializableFunction f) {
34 | return new SpashCollectionRDDAdapter<>(target.map(f));
35 | }
36 |
37 | @Override
38 | public SpashCollection union(SpashCollection coll) {
39 | return new SpashCollectionUnionAdapter<>(this, coll);
40 | }
41 |
42 | @Override
43 | public SpashCollection filter(SerializableFunction condition) {
44 | return new SpashCollectionRDDAdapter<>(target.filter(condition));
45 | }
46 |
47 | @Override
48 | public JavaRDD toRDD(JavaSparkContext sc) {
49 | return this.target;
50 | }
51 |
52 | @Override
53 | public List collect() {
54 | return this.target.collect();
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/command/spi/RmDirCommand.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.command.spi;
2 |
3 | import it.nerdammer.spash.shell.api.fs.FileSystemFacade;
4 | import it.nerdammer.spash.shell.api.fs.SpashFileSystem;
5 | import it.nerdammer.spash.shell.command.AbstractCommand;
6 | import it.nerdammer.spash.shell.command.CommandResult;
7 | import it.nerdammer.spash.shell.command.ExecutionContext;
8 |
9 | import java.nio.file.Path;
10 | import java.util.List;
11 |
12 | /**
13 | * Command to remove a directory.
14 | *
15 | * @author Nicola Ferraro
16 | */
17 | public class RmDirCommand extends AbstractCommand {
18 |
19 | public RmDirCommand(String commandString) {
20 | super(commandString);
21 | }
22 |
23 | @Override
24 | public CommandResult execute(ExecutionContext ctx) {
25 |
26 | FileSystemFacade fs = SpashFileSystem.get();
27 |
28 | List files = this.getArguments();
29 | if(files.size()==0) {
30 | return CommandResult.error(this, "Missing argument");
31 | } else if(files.size()>1) {
32 | return CommandResult.error(this, "Too many arguments");
33 | }
34 |
35 | String file = files.get(0);
36 |
37 | Path path = fs.getAbsolutePath(ctx.getSession().getWorkingDir(), file);
38 |
39 | if(!fs.exists(path.toString())) {
40 | return CommandResult.error(this, "No such file or directory");
41 | }
42 |
43 | if(!fs.isDirectory(path.toString())) {
44 | return CommandResult.error(this, "Not a directory");
45 | }
46 |
47 | boolean removed = fs.rm(path.toString(), false);
48 | if(!removed) {
49 | return CommandResult.error(this, "Directory not empty");
50 | }
51 |
52 | return CommandResult.success(this);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/command/spi/HeadCommand.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.command.spi;
2 |
3 | import it.nerdammer.spash.shell.api.fs.FileSystemFacade;
4 | import it.nerdammer.spash.shell.api.fs.SpashFileSystem;
5 | import it.nerdammer.spash.shell.api.spark.SpashSparkSubsystem;
6 | import it.nerdammer.spash.shell.command.AbstractCommand;
7 | import it.nerdammer.spash.shell.command.CommandResult;
8 | import it.nerdammer.spash.shell.command.ExecutionContext;
9 | import it.nerdammer.spash.shell.common.SpashCollection;
10 | import it.nerdammer.spash.shell.SpashSession;
11 |
12 | import java.nio.file.Path;
13 |
14 | /**
15 | * Command to get the first lines of a file or directory.
16 | *
17 | * @author Nicola Ferraro
18 | */
19 | public class HeadCommand extends AbstractCommand {
20 |
21 | public static final int DEFAULT_NUM_LINES = 10;
22 |
23 | public HeadCommand(String commandString) {
24 | super(commandString);
25 | }
26 |
27 | @Override
28 | public CommandResult execute(ExecutionContext ctx) {
29 |
30 | FileSystemFacade fs = SpashFileSystem.get();
31 |
32 | if(this.getArguments().size()==0) {
33 | return CommandResult.error(this, "No file provided");
34 | } else if(this.getArguments().size()>1) {
35 | return CommandResult.error(this, "Too many arguments");
36 | }
37 |
38 | String file = this.getArguments().get(0);
39 |
40 | Path path = fs.getAbsolutePath(ctx.getSession().getWorkingDir(), file);
41 | boolean exists = fs.exists(path.toString());
42 | if(!exists) {
43 | return CommandResult.error(this, "No such file or directory");
44 | }
45 |
46 | SpashCollection content = SpashSparkSubsystem.get().head(path, DEFAULT_NUM_LINES);
47 |
48 | return CommandResult.success(this, content);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/command/spi/CatCommand.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.command.spi;
2 |
3 | import it.nerdammer.spash.shell.api.fs.FileSystemFacade;
4 | import it.nerdammer.spash.shell.api.fs.SpashFileSystem;
5 | import it.nerdammer.spash.shell.api.spark.SpashSparkSubsystem;
6 | import it.nerdammer.spash.shell.command.AbstractCommand;
7 | import it.nerdammer.spash.shell.command.CommandResult;
8 | import it.nerdammer.spash.shell.command.ExecutionContext;
9 | import it.nerdammer.spash.shell.common.SpashCollection;
10 | import it.nerdammer.spash.shell.SpashSession;
11 | import it.nerdammer.spash.shell.common.SpashCollectionEmptyAdapter;
12 |
13 | import java.nio.file.Path;
14 | import java.util.List;
15 |
16 | /**
17 | * Command to get the content of a file or directory.
18 | *
19 | * @author Nicola Ferraro
20 | */
21 | public class CatCommand extends AbstractCommand {
22 |
23 | public CatCommand(String commandString) {
24 | super(commandString);
25 | }
26 |
27 | @Override
28 | public CommandResult execute(ExecutionContext ctx) {
29 |
30 | FileSystemFacade fs = SpashFileSystem.get();
31 |
32 | List files = this.getArguments();
33 | if(files.size()==0) {
34 | return CommandResult.error(this, "No file provided");
35 | }
36 |
37 | SpashCollection content = new SpashCollectionEmptyAdapter<>();
38 | for(String file : files) {
39 | Path path = fs.getAbsolutePath(ctx.getSession().getWorkingDir(), file);
40 | boolean exists = fs.exists(path.toString());
41 | if (!exists) {
42 | return CommandResult.error(this, "No such file or directory");
43 | }
44 |
45 | content = content.union(SpashSparkSubsystem.get().read(path));
46 | }
47 |
48 | return CommandResult.success(this, content);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/common/SpashCollectionUnionAdapter.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.common;
2 |
3 | import org.apache.spark.api.java.JavaRDD;
4 | import org.apache.spark.api.java.JavaSparkContext;
5 |
6 | import java.io.PrintWriter;
7 | import java.util.List;
8 |
9 | /**
10 | * A SpashCollection that is the union of two {@code SpashCollection}s.
11 | *
12 | * @author Nicola Ferraro
13 | */
14 | public class SpashCollectionUnionAdapter implements SpashCollection {
15 |
16 | /**
17 | * The first collection.
18 | */
19 | private SpashCollection one;
20 |
21 | /**
22 | * The second collection.
23 | */
24 | private SpashCollection two;
25 |
26 | public SpashCollectionUnionAdapter(SpashCollection one, SpashCollection two) {
27 | this.one = one;
28 | this.two = two;
29 | }
30 |
31 | @Override
32 | public void mkString(PrintWriter writer) {
33 | one.mkString(writer);
34 | two.mkString(writer);
35 | }
36 |
37 | @Override
38 | public SpashCollection map(SerializableFunction f) {
39 | return new SpashCollectionUnionAdapter<>(one.map(f), two.map(f));
40 | }
41 |
42 | @Override
43 | public SpashCollection union(SpashCollection coll) {
44 | return new SpashCollectionUnionAdapter<>(this, coll);
45 | }
46 |
47 | @Override
48 | public SpashCollection filter(SerializableFunction condition) {
49 | return new SpashCollectionUnionAdapter<>(one.filter(condition), two.filter(condition));
50 | }
51 |
52 | @Override
53 | public JavaRDD toRDD(JavaSparkContext sc) {
54 | return this.one.toRDD(sc).union(this.two.toRDD(sc));
55 | }
56 |
57 | @Override
58 | public List collect() {
59 | List res = one.collect();
60 | res.addAll(two.collect());
61 | return res;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/command/spi/CdCommand.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.command.spi;
2 |
3 | import it.nerdammer.spash.shell.api.fs.FileSystemFacade;
4 | import it.nerdammer.spash.shell.api.fs.SpashFileSystem;
5 | import it.nerdammer.spash.shell.command.AbstractCommand;
6 | import it.nerdammer.spash.shell.command.CommandResult;
7 | import it.nerdammer.spash.shell.SpashSession;
8 | import it.nerdammer.spash.shell.command.ExecutionContext;
9 |
10 | import java.nio.file.Path;
11 |
12 | /**
13 | * @author Nicola Ferraro
14 | */
15 | public class CdCommand extends AbstractCommand {
16 |
17 | public CdCommand(String commandString) {
18 | super(commandString);
19 | }
20 |
21 | @Override
22 | public CommandResult execute(ExecutionContext ctx) {
23 |
24 | try {
25 | FileSystemFacade fs = SpashFileSystem.get();
26 |
27 | if(this.getArguments().size()==0) {
28 | return CommandResult.error(this, "No file provided");
29 | } else if(this.getArguments().size()>1) {
30 | return CommandResult.error(this, "Too many arguments");
31 | }
32 |
33 | String dir = this.getArguments().get(0);
34 | if (dir == null) {
35 | dir = "/"; // the default dir
36 | }
37 |
38 | Path dest = fs.getAbsolutePath(ctx.getSession().getWorkingDir(), dir);
39 | boolean exists = fs.exists(dest.toString());
40 | if (!exists) {
41 | return CommandResult.error(this, "No such file or directory");
42 | }
43 |
44 | boolean isDir = fs.isDirectory(dest.toString());
45 | if (!isDir) {
46 | return CommandResult.error(this, "Not a directory");
47 | }
48 |
49 | ctx.getSession().setWorkingDir(dest.toAbsolutePath().normalize().toString());
50 |
51 | return CommandResult.success(this);
52 | } catch(IllegalArgumentException e) {
53 | return CommandResult.error(this, "Illegal input");
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/command/spi/WriteCommand.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.command.spi;
2 |
3 | import it.nerdammer.spash.shell.api.fs.FileSystemFacade;
4 | import it.nerdammer.spash.shell.api.fs.SpashFileSystem;
5 | import it.nerdammer.spash.shell.api.spark.SparkFacade;
6 | import it.nerdammer.spash.shell.api.spark.SpashSparkSubsystem;
7 | import it.nerdammer.spash.shell.command.AbstractCommand;
8 | import it.nerdammer.spash.shell.command.CommandResult;
9 | import it.nerdammer.spash.shell.command.ExecutionContext;
10 | import it.nerdammer.spash.shell.common.SpashCollection;
11 | import it.nerdammer.spash.shell.common.SpashCollectionEmptyAdapter;
12 |
13 | import java.nio.file.Path;
14 | import java.util.List;
15 |
16 | /**
17 | * Command to append the result of a the previous command to a Hadoop file.
18 | *
19 | * @author Nicola Ferraro
20 | */
21 | public class WriteCommand extends AbstractCommand {
22 |
23 | public WriteCommand(String commandString) {
24 | super(commandString);
25 | }
26 |
27 | @Override
28 | public CommandResult execute(ExecutionContext ctx) {
29 |
30 | FileSystemFacade fs = SpashFileSystem.get();
31 | SparkFacade spark = SpashSparkSubsystem.get();
32 |
33 | List files = this.getArguments();
34 | if(files.size()==0) {
35 | return CommandResult.error(this, "No file provided");
36 | } else if(files.size()>1) {
37 | return CommandResult.error(this, "Too many arguments");
38 | }
39 |
40 | String file = this.getArguments().get(0);
41 | Path path = fs.getAbsolutePath(ctx.getSession().getWorkingDir(), file);
42 |
43 | CommandResult prevRes = ctx.getPreviousCommandResult();
44 | if(prevRes!=null && !prevRes.isSuccess()) {
45 | return CommandResult.success(this);
46 | }
47 |
48 | SpashCollection content = prevRes!=null ? prevRes.getContent() : new SpashCollectionEmptyAdapter();
49 | spark.write(content, path);
50 |
51 | return CommandResult.success(this);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/common/SpashCollection.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.common;
2 |
3 | import org.apache.spark.api.java.JavaRDD;
4 | import org.apache.spark.api.java.JavaSparkContext;
5 |
6 | import java.io.PrintWriter;
7 | import java.io.Serializable;
8 | import java.util.List;
9 |
10 | /**
11 | * An abstract collection. It can be implemented either by a standard java collection or a distributed collection.
12 | *
13 | * @author Nicola Ferraro
14 | */
15 | public interface SpashCollection extends Serializable {
16 |
17 | /**
18 | * Prints the whole collection to the given writer.
19 | *
20 | * @param writer the writer on which the collection will be printed on.
21 | */
22 | void mkString(PrintWriter writer);
23 |
24 | /**
25 | * Tranforms every element of the collection into another element.
26 | *
27 | * @param f the transformation function
28 | * @param the new type
29 | * @return the transformed collection
30 | */
31 | SpashCollection map(SerializableFunction f);
32 |
33 | /**
34 | * Merges this collection to the one provided as input.
35 | *
36 | * @param coll the collection to merge
37 | * @return the union of the two collections
38 | */
39 | SpashCollection union(SpashCollection coll);
40 |
41 | /**
42 | * Filters a collection retaining only elements respecting the given condition.
43 | *
44 | * @param condition the condition that must evaluate to true for retained elements
45 | * @return te resulting collection
46 | */
47 | SpashCollection filter(SerializableFunction condition);
48 |
49 | /**
50 | * Converts this collection to a Spark {@code JavaRDD}.
51 | *
52 | * @param sc the current Spark context
53 | * @return a RDD corresponding to this collection
54 | */
55 | JavaRDD toRDD(JavaSparkContext sc);
56 |
57 | /**
58 | * Collects the whole collection into a {@code List}.
59 | *
60 | * @return the elements of the collection
61 | */
62 | List collect();
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/api/spark/SparkFacadeImpl.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.api.spark;
2 |
3 | import it.nerdammer.spash.shell.api.fs.FileSystemFacade;
4 | import it.nerdammer.spash.shell.api.fs.SpashFileSystem;
5 | import it.nerdammer.spash.shell.common.SpashCollection;
6 | import it.nerdammer.spash.shell.common.SpashCollectionListAdapter;
7 | import it.nerdammer.spash.shell.common.SpashCollectionRDDAdapter;
8 | import org.apache.spark.api.java.JavaRDD;
9 | import org.apache.spark.api.java.JavaSparkContext;
10 |
11 | import java.net.URI;
12 | import java.nio.file.Path;
13 | import java.util.List;
14 |
15 | /**
16 | * The default implementation of the {@code SparkFacade}.
17 | *
18 | * @author Nicola Ferraro
19 | */
20 | public class SparkFacadeImpl implements SparkFacade {
21 |
22 | private JavaSparkContext sc;
23 |
24 | public SparkFacadeImpl(JavaSparkContext sc) {
25 | this.sc = sc;
26 | }
27 |
28 | @Override
29 | public SpashCollection read(Path file) {
30 | URI uri = SpashFileSystem.get().getURI(file.normalize().toString());
31 | JavaRDD rdd = sc.textFile(uri.toString());
32 |
33 | return new SpashCollectionRDDAdapter<>(rdd);
34 | }
35 |
36 | @Override
37 | public void write(SpashCollection content, Path file) {
38 | FileSystemFacade fs = SpashFileSystem.get();
39 | if(fs.exists(file.toString())) {
40 | fs.rm(file.toString(), true);
41 | }
42 |
43 | URI uri = SpashFileSystem.get().getURI(file.normalize().toString());
44 | content.toRDD(sc).saveAsTextFile(uri.toString());
45 | }
46 |
47 | @Override
48 | public SpashCollection head(Path file, int lines) {
49 | URI uri = SpashFileSystem.get().getURI(file.normalize().toString());
50 | JavaRDD rdd = sc.textFile(uri.toString());
51 | List stream = rdd.take(lines);
52 |
53 | return new SpashCollectionListAdapter<>(stream);
54 | }
55 |
56 | @Override
57 | public SpashCollection parallelize(List coll) {
58 | return new SpashCollectionRDDAdapter<>(sc.parallelize(coll));
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/command/spi/RmCommand.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.command.spi;
2 |
3 | import com.google.common.collect.ImmutableMap;
4 | import it.nerdammer.spash.shell.api.fs.FileSystemFacade;
5 | import it.nerdammer.spash.shell.api.fs.SpashFileSystem;
6 | import it.nerdammer.spash.shell.command.AbstractCommand;
7 | import it.nerdammer.spash.shell.command.CommandResult;
8 | import it.nerdammer.spash.shell.command.ExecutionContext;
9 |
10 | import java.nio.file.Path;
11 | import java.util.LinkedList;
12 | import java.util.List;
13 |
14 | /**
15 | * Command to remove a file or directory.
16 | *
17 | * @author Nicola Ferraro
18 | */
19 | public class RmCommand extends AbstractCommand {
20 |
21 | public RmCommand(String commandString) {
22 | super(commandString, ImmutableMap.builder()
23 | .put("r", false)
24 | .build());
25 | }
26 |
27 | @Override
28 | public CommandResult execute(ExecutionContext ctx) {
29 |
30 | FileSystemFacade fs = SpashFileSystem.get();
31 |
32 | List files = this.getArguments();
33 | if(files.size()==0) {
34 | return CommandResult.error(this, "Missing argument");
35 | }
36 |
37 | boolean recursive = this.getOptions().containsKey("r");
38 |
39 | List paths = new LinkedList<>();
40 | for(String file : files) {
41 | Path path = fs.getAbsolutePath(ctx.getSession().getWorkingDir(), file);
42 | paths.add(path);
43 |
44 | if(!fs.exists(path.toString())) {
45 | return CommandResult.error(this, "No such file or directory");
46 | }
47 |
48 | boolean isDirectory = fs.isDirectory(path.toString());
49 | if(isDirectory && !recursive) {
50 | return CommandResult.error(this, "is a directory");
51 | }
52 | }
53 |
54 | for(Path path : paths) {
55 | boolean removed = fs.rm(path.toString(), recursive);
56 | if(!removed) {
57 | return CommandResult.error(this, "Unable to remove file: operation interrupted");
58 | }
59 | }
60 |
61 | return CommandResult.success(this);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/release/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | it.nerdammer.spash
9 | spash-pom
10 | 0.1
11 |
12 |
13 | spash-release
14 |
15 | pom
16 |
17 |
18 |
19 | ${project.groupId}
20 | spash-core
21 | ${project.version}
22 |
23 |
24 |
25 | org.apache.hadoop
26 | hadoop-hdfs
27 |
28 |
29 | org.apache.hadoop
30 | hadoop-client
31 |
32 |
33 | org.apache.spark
34 | spark-core_2.10
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | maven-assembly-plugin
46 | 2.6
47 |
48 | src/assembly/bin.xml
49 | spash-${project.version}-bin
50 |
51 |
52 |
53 | package
54 |
55 | single
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/command/AbstractCommand.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.command;
2 |
3 | import java.util.*;
4 |
5 | /**
6 | * Provides useful methods and constructor for concrete commands.
7 | *
8 | * @author Nicola Ferraro
9 | */
10 | public abstract class AbstractCommand implements Command {
11 |
12 | private CommandTokenizer commandTokenizer;
13 |
14 | public AbstractCommand(String commandString) {
15 | this(commandString, Collections.emptyMap());
16 | }
17 |
18 | public AbstractCommand(String commandString, Map parametersValueInfo) {
19 | Set parameters = parametersValueInfo.keySet();
20 | Set valuedParameters = new TreeSet<>();
21 | for(Map.Entry e : parametersValueInfo.entrySet()) {
22 | if(e.getValue().booleanValue()) {
23 | valuedParameters.add(e.getKey());
24 | }
25 | }
26 |
27 | this.commandTokenizer = new CommandTokenizer(commandString, valuedParameters);
28 |
29 | if(!parameters.containsAll(this.commandTokenizer.getOptions().keySet())) {
30 | Set wrongParameters = new TreeSet<>(this.commandTokenizer.getOptions().keySet());
31 | wrongParameters.removeAll(parameters);
32 | throw new IllegalArgumentException("Unknown options: " + wrongParameters);
33 | }
34 | }
35 |
36 |
37 | /**
38 | * Returns the command associated to the command string.
39 | *
40 | * @return the command
41 | */
42 | public String getCommand() {
43 | return this.commandTokenizer.getCommand();
44 | }
45 |
46 | /**
47 | * Returns the option map associated to the command string.
48 | * Options not requiring a value contain null as value of the map.
49 | *
50 | * @return the option map
51 | */
52 | public Map getOptions() {
53 | return this.commandTokenizer.getOptions();
54 | }
55 |
56 | /**
57 | * Returns the argument part of the command string (the one after the parameter set).
58 | *
59 | * @return the arguments
60 | */
61 | public List getArguments() {
62 | return this.commandTokenizer.getArguments();
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/common/SpashCollectionListAdapter.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.common;
2 |
3 | import ch.lambdaj.Lambda;
4 | import ch.lambdaj.function.convert.Converter;
5 | import org.apache.spark.api.java.JavaRDD;
6 | import org.apache.spark.api.java.JavaSparkContext;
7 | import org.hamcrest.BaseMatcher;
8 | import org.hamcrest.Description;
9 |
10 | import java.io.PrintWriter;
11 | import java.util.List;
12 |
13 | /**
14 | * Adapts a Java {@code Iterable} to a SpashCollection.
15 | *
16 | * @author Nicola Ferraro
17 | */
18 | public class SpashCollectionListAdapter implements SpashCollection {
19 |
20 | /**
21 | * The iterable object.
22 | */
23 | private List target;
24 |
25 | public SpashCollectionListAdapter(List target) {
26 | this.target = target;
27 | }
28 |
29 | @Override
30 | public void mkString(PrintWriter writer) {
31 | for(T el : target) {
32 | writer.println(el != null ? el.toString() : "");
33 | }
34 | }
35 |
36 | @Override
37 | public SpashCollection map(final SerializableFunction f) {
38 | return new SpashCollectionListAdapter<>(Lambda.convert(target, new Converter() {
39 | @Override
40 | public R convert(T t) {
41 | return f.apply(t);
42 | }
43 | }));
44 | }
45 |
46 | @Override
47 | public SpashCollection union(SpashCollection coll) {
48 | return new SpashCollectionUnionAdapter<>(this, coll);
49 | }
50 |
51 | @Override
52 | public SpashCollection filter(final SerializableFunction condition) {
53 | return new SpashCollectionListAdapter<>(Lambda.filter(new BaseMatcher() {
54 | @Override
55 | public boolean matches(Object o) {
56 | return condition.apply((T) o);
57 | }
58 | @Override
59 | public void describeTo(Description description) {
60 | }
61 | }, target));
62 | }
63 |
64 | @Override
65 | public JavaRDD toRDD(JavaSparkContext sc) {
66 | return sc.parallelize(this.target);
67 | }
68 |
69 | @Override
70 | public List collect() {
71 | return this.target;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/common/TabulatedValue.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.common;
2 |
3 | import ch.lambdaj.Lambda;
4 | import ch.lambdaj.function.convert.StringLengthConverter;
5 | import org.apache.commons.lang3.StringUtils;
6 |
7 | import java.util.ArrayList;
8 | import java.util.Iterator;
9 | import java.util.List;
10 |
11 | /**
12 | * @author Nicola Ferraro
13 | */
14 | public class TabulatedValue implements Iterable {
15 |
16 | private List values;
17 |
18 | public TabulatedValue() {
19 | this.values = new ArrayList<>();
20 | }
21 |
22 | public void set(int pos, String value) {
23 | this.values.set(pos, value);
24 | }
25 |
26 | public String remove(int pos) {
27 | return this.values.remove(pos);
28 | }
29 |
30 | public void add(String value) {
31 | this.values.add(value);
32 | }
33 |
34 | @Override
35 | public Iterator iterator() {
36 | return values.iterator();
37 | }
38 |
39 | public String toString(List columnSizes) {
40 | if(columnSizes.size()!=this.values.size()) {
41 | throw new IllegalArgumentException("Size list and value list must have the same length: " + this.values.size() + "/" + columnSizes.size());
42 | }
43 |
44 | Iterator sizes = columnSizes.iterator();
45 | Iterator strs = this.iterator();
46 |
47 | StringBuilder bui = new StringBuilder();
48 |
49 | while(sizes.hasNext() && strs.hasNext()) {
50 | String str = strs.next();
51 | int size = sizes.next();
52 | bui.append(StringUtils.rightPad(str, size));
53 |
54 | if(strs.hasNext()) {
55 | bui.append(" ");
56 | }
57 | }
58 |
59 | return bui.toString();
60 | }
61 |
62 | public List columnSizes() {
63 | return Lambda.convert(this.values, new StringLengthConverter());
64 | }
65 |
66 | public static List combineColumnSizes(List s1, List s2) {
67 | Iterator i1 = s1.iterator();
68 | Iterator i2 = s2.iterator();
69 | List res = new ArrayList<>(s1.size());
70 | while(i1.hasNext() && i2.hasNext()) {
71 | int v = Math.max(i1.next(), i2.next());
72 | res.add(v);
73 | }
74 |
75 | if(i1.hasNext() || i2.hasNext()) {
76 | throw new IllegalArgumentException("Collections have different sizes");
77 | }
78 |
79 | return res;
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/command/CommandResult.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell.command;
2 |
3 | import it.nerdammer.spash.shell.common.SpashCollection;
4 |
5 | /**
6 | * Defines the result of the execution of a command.
7 | *
8 | * @author Nicola Ferraro
9 | */
10 | public class CommandResult {
11 |
12 | /**
13 | * The executed command.
14 | */
15 | private Command command;
16 |
17 | /**
18 | * Indicates whether the command completed successfully.
19 | */
20 | private boolean success;
21 |
22 | /**
23 | * An error message explaining the problem when the command failed to execute.
24 | */
25 | private String errorMessage;
26 |
27 | /**
28 | * The result of the command.
29 | */
30 | private SpashCollection content;
31 |
32 | private CommandResult(Command command, boolean success, String errorMessage, SpashCollection content) {
33 | this.command = command;
34 | this.success = success;
35 | this.errorMessage = errorMessage;
36 | this.content = content;
37 | }
38 |
39 | public static CommandResult success(Command command, SpashCollection content) {
40 | return new CommandResult(command, true, null, content);
41 | }
42 |
43 | public static CommandResult success(Command command) {
44 | return new CommandResult(command, true, null, null);
45 | }
46 |
47 | public static CommandResult error(Command command, String errorMessage) {
48 | return new CommandResult(command, false, errorMessage, null);
49 | }
50 |
51 | public Command getCommand() {
52 | return command;
53 | }
54 |
55 | public void setCommand(Command command) {
56 | this.command = command;
57 | }
58 |
59 | public boolean isSuccess() {
60 | return success;
61 | }
62 |
63 | public void setSuccess(boolean success) {
64 | this.success = success;
65 | }
66 |
67 | public String getErrorMessage() {
68 | return errorMessage;
69 | }
70 |
71 | public void setErrorMessage(String errorMessage) {
72 | this.errorMessage = errorMessage;
73 | }
74 |
75 | public SpashCollection getContent() {
76 | return content;
77 | }
78 |
79 | public void setContent(SpashCollection content) {
80 | this.content = content;
81 | }
82 |
83 | @Override
84 | public String toString() {
85 | return "CommandResult{" +
86 | "command=" + command +
87 | ", success=" + success +
88 | '}';
89 | }
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/core/src/main/java/it/nerdammer/spash/shell/SpashCommandCompleter.java:
--------------------------------------------------------------------------------
1 | package it.nerdammer.spash.shell;
2 |
3 | import ch.lambdaj.Lambda;
4 | import ch.lambdaj.function.convert.DefaultStringConverter;
5 | import ch.lambdaj.function.convert.PropertyExtractor;
6 | import it.nerdammer.spash.shell.api.fs.SpashFileSystem;
7 | import it.nerdammer.spash.shell.command.CommandFactory;
8 | import jline.console.completer.Completer;
9 | import jline.internal.Preconditions;
10 | import org.hamcrest.text.StringStartsWith;
11 |
12 | import java.nio.file.Path;
13 | import java.util.List;
14 | import java.util.Set;
15 |
16 | /**
17 | * @author Nicola Ferraro
18 | */
19 | public class SpashCommandCompleter implements Completer {
20 |
21 | private Set commands;
22 |
23 | private SpashSession session;
24 |
25 | public SpashCommandCompleter(SpashSession session) {
26 | this.commands = CommandFactory.getInstance().getAvailableCommands();
27 | this.session = session;
28 | }
29 |
30 | @Override
31 | public int complete(String buffer, int cursor, List candidates) {
32 | Preconditions.checkNotNull(candidates);
33 |
34 | String text = contextualBuffer(buffer, cursor);
35 |
36 | List commands = Lambda.filter(StringStartsWith.startsWith(text), this.commands);
37 | if(commands.size()>0) {
38 | candidates.addAll(commands);
39 |
40 | if(candidates.size()==1) {
41 | candidates.set(0, candidates.get(0) + " ");
42 | }
43 |
44 | return candidates.isEmpty() ? -1 : 0;
45 |
46 | } else if(text.contains(" ")) {
47 | int insertion = text.lastIndexOf(" ") + 1;
48 | String tailBuffer = text.substring(insertion);
49 |
50 | List files = Lambda.convert(Lambda.convert(SpashFileSystem.get().ls(this.session.getWorkingDir()).collect(), new PropertyExtractor