Merge branch '2-create-cli-options-parser' into 'master'

Resolve "Create CLI options' parser"

Closes #2

See merge request bartlomiej.pluta/esa-tool!2
This commit is contained in:
Bartłomiej Pluta
2019-03-30 09:54:54 +00:00
8 changed files with 200 additions and 14 deletions

View File

@@ -1,20 +1,32 @@
package com.bartek.esa;
import com.bartek.esa.cli.model.CliArgsOptions;
import com.bartek.esa.cli.parser.CliArgsParser;
import com.bartek.esa.di.DaggerDependencyInjector;
import com.bartek.esa.dispatcher.dispatcher.MethodDispatcher;
import com.bartek.esa.dispatcher.model.DispatcherActions;
import javax.inject.Inject;
public class EsaMain {
private final CliArgsParser cliArgsParser;
private final MethodDispatcher methodDispatcher;
@Inject
EsaMain(CliArgsParser cliArgsParser) {
EsaMain(CliArgsParser cliArgsParser, MethodDispatcher methodDispatcher) {
this.cliArgsParser = cliArgsParser;
this.methodDispatcher = methodDispatcher;
}
private void run(String[] args) {
// cliArgsParser.parse(...)
DispatcherActions dispatcherActions = DispatcherActions.builder()
.sourceAnalysis(source -> {})
.apkAudit(source -> {})
.build();
CliArgsOptions options = cliArgsParser.parse(args);
methodDispatcher.dispatchMethod(options, dispatcherActions);
}
public static void main(String[] args) {

View File

@@ -1,9 +0,0 @@
package com.bartek.esa.cli.model;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class CliArgsActions {
}

View File

@@ -0,0 +1,34 @@
package com.bartek.esa.cli.model;
import lombok.Builder;
import lombok.Data;
import java.util.Set;
import static java.util.Collections.emptySet;
@Data
@Builder
public class CliArgsOptions {
private String sourceAnalysisDirectory;
private String apkAuditFile;
private Set<String> excludes;
private Set<String> plugins;
public boolean isSourceAnalysis() {
return sourceAnalysisDirectory != null;
}
public boolean isApkAudit() {
return apkAuditFile != null;
}
public static CliArgsOptions empty() {
return CliArgsOptions.builder()
.sourceAnalysisDirectory(null)
.apkAuditFile(null)
.excludes(emptySet())
.plugins(emptySet())
.build();
}
}

View File

@@ -1,15 +1,110 @@
package com.bartek.esa.cli.parser;
import com.bartek.esa.cli.model.CliArgsActions;
import com.bartek.esa.cli.model.CliArgsOptions;
import org.apache.commons.cli.*;
import javax.inject.Inject;
import java.util.HashSet;
import static java.util.Arrays.asList;
import static java.util.Collections.emptySet;
public class CliArgsParser {
private static final String SRC_OPT = "src";
private static final String APK_OPT = "apk";
private static final String EXCLUDE_OPT = "exclude";
private static final String HELP_OPT = "help";
private static final String PLUGINS_OPT = "plugins";
@Inject
public CliArgsParser() {}
public void parse(String[] args, CliArgsActions actions) {
public CliArgsOptions parse(String[] args) {
try {
return tryToParse(args);
} catch (ParseException e) {
printHelp();
return CliArgsOptions.empty();
}
}
private CliArgsOptions tryToParse(String[] args) throws ParseException {
CommandLine command = new DefaultParser().parse(prepareOptions(), args);
if (command.hasOption(HELP_OPT)) {
printHelp();
return CliArgsOptions.empty();
}
boolean isNeitherAuditNorAnalysis = !command.hasOption(SRC_OPT) && !command.hasOption(APK_OPT);
if (isNeitherAuditNorAnalysis) {
printHelp();
return CliArgsOptions.empty();
}
return CliArgsOptions.builder()
.sourceAnalysisDirectory(command.hasOption(SRC_OPT) ? command.getOptionValue(SRC_OPT) : null)
.apkAuditFile(command.hasOption(APK_OPT) ? command.getOptionValue(APK_OPT) : null)
.plugins(command.hasOption(PLUGINS_OPT) ? new HashSet<>(asList(command.getOptionValues(PLUGINS_OPT))) : emptySet())
.excludes(command.hasOption(EXCLUDE_OPT) ? new HashSet<>(asList(command.getOptionValues(EXCLUDE_OPT))) : emptySet())
.build();
}
private void printHelp() {
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp("esa", prepareOptions(), true);
}
private Options prepareOptions() {
Options options = new Options();
options.addOption(source());
options.addOption(apk());
options.addOption(exclude());
options.addOption(plugins());
options.addOption(help());
return options;
}
private Option source() {
return Option.builder()
.longOpt(SRC_OPT)
.argName("SOURCE_PATH")
.hasArg()
.desc("perform analysis for Java code and XML resources")
.build();
}
private Option apk() {
return Option.builder()
.longOpt(APK_OPT)
.argName("APK_PATH")
.hasArg()
.desc("perform audit for compiled APK file")
.build();
}
private Option exclude() {
return Option.builder()
.longOpt(EXCLUDE_OPT)
.argName("CODES")
.numberOfArgs(Option.UNLIMITED_VALUES)
.desc("exclude particular security checks from audit/analysis")
.build();
}
private Option help() {
return Option.builder()
.longOpt(HELP_OPT)
.desc("print this help")
.build();
}
private Option plugins() {
return Option.builder()
.longOpt(PLUGINS_OPT)
.argName("CODES")
.numberOfArgs(Option.UNLIMITED_VALUES)
.desc("use only selected security checks for audit/analysis")
.build();
}
}

View File

@@ -2,10 +2,12 @@ package com.bartek.esa.di;
import com.bartek.esa.EsaMain;
import com.bartek.esa.cli.di.CliModule;
import com.bartek.esa.dispatcher.di.DispatcherModule;
import dagger.Component;
@Component(modules = {
CliModule.class
CliModule.class,
DispatcherModule.class
})
public interface DependencyInjector {
EsaMain esa();

View File

@@ -0,0 +1,14 @@
package com.bartek.esa.dispatcher.di;
import com.bartek.esa.dispatcher.dispatcher.MethodDispatcher;
import dagger.Module;
import dagger.Provides;
@Module
public class DispatcherModule {
@Provides
MethodDispatcher methodDispatcher() {
return new MethodDispatcher();
}
}

View File

@@ -0,0 +1,25 @@
package com.bartek.esa.dispatcher.dispatcher;
import com.bartek.esa.cli.model.CliArgsOptions;
import com.bartek.esa.dispatcher.model.DispatcherActions;
import javax.inject.Inject;
public class MethodDispatcher {
@Inject
public MethodDispatcher() {
}
public void dispatchMethod(CliArgsOptions options, DispatcherActions actions) {
if(options.isSourceAnalysis()) {
actions.getSourceAnalysis().accept(options.getSourceAnalysisDirectory());
return;
}
if(options.isApkAudit()) {
actions.getApkAudit().accept(options.getApkAuditFile());
}
}
}

View File

@@ -0,0 +1,13 @@
package com.bartek.esa.dispatcher.model;
import lombok.Builder;
import lombok.Data;
import java.util.function.Consumer;
@Data
@Builder
public class DispatcherActions {
private Consumer<String> sourceAnalysis;
private Consumer<String> apkAudit;
}