diff --git a/.gitignore b/.gitignore index 84a43ca6..74103a69 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ out/ # Can be used for repackaging with semantic information libs/ +/bin/ diff --git a/build.gradle b/build.gradle index 6d62d1a5..2c377094 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ apply plugin: 'war' war { baseName = 'remrem-generate' - version = '0.5.0' + version = '0.5.5' } @@ -52,10 +52,15 @@ sourceSets { } } +processResources { + expand(project.properties) +} + install.dependsOn assemble apply plugin: 'spring-boot' - +apply plugin: 'java' +apply plugin: 'eclipse' group 'com.ericsson.eiffel.remrem' version '1.0-SNAPSHOT' @@ -88,6 +93,7 @@ repositories { } dependencies { + compile('com.jayway.restassured:rest-assured:2.3.2') compile("org.springframework.boot:spring-boot-starter-web:$sprintBootVersion") { exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat' } @@ -110,11 +116,13 @@ dependencies { //Injectable Message Library and its Implementation compile 'com.github.Ericsson:eiffel-remrem-shared:0.1.4' - compile 'com.github.Ericsson:eiffel-remrem-semantics:0.1.2' + compile 'com.github.Ericsson:eiffel-remrem-semantics:0.1.0' //compileOnly is supported in gradle 2.12 but it might be required // in cucumber folder compile "org.projectlombok:lombok:1.16.8" + //commons CLI + compile 'commons-cli:commons-cli:1.3.1' // Declare the dependency for your favourite test framework you want to use in your tests. // TestNG is also supported by the Gradle Test task. Just change the diff --git a/src/main/java/com/ericsson/eiffel/remrem/generate/App.java b/src/main/java/com/ericsson/eiffel/remrem/generate/App.java index 248dd3e0..03878f5d 100644 --- a/src/main/java/com/ericsson/eiffel/remrem/generate/App.java +++ b/src/main/java/com/ericsson/eiffel/remrem/generate/App.java @@ -1,32 +1,30 @@ package com.ericsson.eiffel.remrem.generate; - +import org.springframework.boot.Banner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.web.SpringBootServletInitializer; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.ComponentScan; -import java.util.Arrays; +import com.ericsson.eiffel.remrem.generate.config.SpringLoggingInitializer; @SpringBootApplication @ComponentScan("com.ericsson.eiffel.remrem") public class App extends SpringBootServletInitializer { public static void main(String[] args) { - ApplicationContext ctx = SpringApplication.run(App.class, args); - - System.out.println("Let's inspect active profiles:"); - for (String envNames : ctx.getEnvironment().getActiveProfiles()) { - System.out.println(envNames); - } - - System.out.println("Let's inspect the beans provided by Spring Boot:"); - - String[] beanNames = ctx.getBeanDefinitionNames(); - Arrays.sort(beanNames); - for (String beanName : beanNames) { - System.out.println(beanName); - } + startService(args); + } + + private static void startService(String[] args) { + SpringApplication application = new SpringApplication(App.class); + application.addInitializers(new SpringLoggingInitializer()); + application.setBannerMode(Banner.Mode.OFF); + application.setLogStartupInfo(false); + // We do not start web service if any arguments are passed + if (args.length > 0) + application.setWebEnvironment(false); + ApplicationContext ctx = application.run(args); } -} +} \ No newline at end of file diff --git a/src/main/java/com/ericsson/eiffel/remrem/generate/cli/CLI.java b/src/main/java/com/ericsson/eiffel/remrem/generate/cli/CLI.java new file mode 100644 index 00000000..b54bb7e0 --- /dev/null +++ b/src/main/java/com/ericsson/eiffel/remrem/generate/cli/CLI.java @@ -0,0 +1,231 @@ +package com.ericsson.eiffel.remrem.generate.cli; + +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.file.Files; +import java.nio.file.Paths; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.DefaultParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.stereotype.Component; +import org.springframework.boot.CommandLineRunner; + +import com.ericsson.eiffel.remrem.semantics.SemanticsService; +import com.ericsson.eiffel.remrem.shared.MsgService; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; + +/** + * Class for interpreting the passed arguments from command line. + * Parse method returns true, meaning we need to start the service afterwards, if no argument + * is given. The same method returns false, meaning we do not start the service afterwards, if any + * argument is given. If an argument is given that it is not recognized we print help. + * Only Eiffel3 messaging is supported right now by default. + * Comment out @Qualifier("eiffel3") and activate @Qualifier("eiffel-semantics") if you want semantics + * @author evasiba + * + */ +@Component +@ComponentScan(basePackages = "com.ericsson.eiffel.remrem") +public class CLI implements CommandLineRunner{ + private Options options=null; + @Autowired + private MsgService[] msgServices; + + public CLI() { + options = createCLIOptions(); + } + + @Override + public void run(String... args) throws Exception { + // TODO Auto-generated method stub + boolean startService = parse(args); + if (!startService) + return; + } + + /** + * Creates the options needed by command line interface + * @return the options this CLI can handle + */ + private static Options createCLIOptions() { + Options options = new Options(); + options.addOption("h", "help", false, "show help."); + options.addOption("f", "content_file", true, "message content file"); + options.addOption("json", "json_content", true, "json content"); + options.addOption("t", "message_type", true, "message type, mandatory if -f or -json is given"); + options.addOption("r", "response_file", true, "file to store the response in, optional"); + options.addOption("d", "debug", false, "enable debug traces"); + options.addOption("mp", "messaging_protocol", true, "name of messaging protocol to be used, e.g. eiffel3, semantics"); + return options; + } + + /** + * Prints the help for this application and exits. + * @param options the options to print usage help for + */ + private static void help(Options options) { + // This prints out some help + HelpFormatter formater = new HelpFormatter(); + formater.printHelp("java -jar", options); + System.exit(1); + } + + /** + * Parse the given arguments and act on them + * @param args command line arguments + * @return if the service should start or not + */ + public boolean parse(String[] args) { + Logger log = (Logger) LoggerFactory.getLogger("ROOT"); + CommandLineParser parser = new DefaultParser(); + boolean startService = true; + try { + CommandLine commandLine = parser.parse(options, args); + Option[] existingOptions = commandLine.getOptions(); + if (existingOptions.length > 0) { + startService = false; + handleOptions(commandLine); + } + } catch (Exception e) { + e.printStackTrace(); + help(options); + } + return startService; + } + + /** + * @param commandLine + */ + private void handleLogging(CommandLine commandLine) { + if (!commandLine.hasOption("-d")) { + //Eiffel 3 messaging logs to stdout but since we also write + //to stdout we need to turn off logging unless specified by the user + System.setProperty("logging.level.root", "OFF"); + Logger log = (Logger) LoggerFactory.getLogger("ROOT"); + log.setLevel(Level.OFF); + } + } + + /** + * Delegates actions depending on the passed arguments + * @param commandLine command line arguments + */ + private void handleOptions(CommandLine commandLine) { + handleLogging(commandLine); + if (commandLine.hasOption("h")) { + System.out.println("You passed help flag."); + help(options); + } else if (commandLine.hasOption("f") && commandLine.hasOption("t")) { + handleFileArgs(commandLine); + } else if (commandLine.hasOption("json") && commandLine.hasOption("t")) { + handleJsonArgs(commandLine); + }else { + System.out.println("Nothing to do with the options you passed."); + help(options); + } + } + + /** + * Reads the content from the given file and sends it to message service + * @param commandLine + */ + private void handleFileArgs(CommandLine commandLine) { + String filePath = commandLine.getOptionValue("f"); + String jsonContent = readFileContent(filePath); + handleJsonString(jsonContent, commandLine); + } + + /** + * Read file content as String + * @param filePath + * @return + */ + private String readFileContent(String filePath) { + try { + byte[] fileBytes = Files.readAllBytes(Paths.get(filePath)); + return new String(fileBytes); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + System.exit(-2); + } + return null; + } + + /** + * Read passed json string from command line and sends it to message service + * @param commandLine + */ + private void handleJsonArgs(CommandLine commandLine) { + String jsonContent = commandLine.getOptionValue("json"); + handleJsonString(jsonContent, commandLine); + } + + /** + * Send the given json string to message service + * @param msgType the Eiffel message type + * @param filePath the file path where the message content resides + * @param responseFilePath the file path where to store the prepared message, stdout if null + */ + private void handleJsonString(String jsonString, + CommandLine commandLine) { + + String responseFilePath = null; + if (commandLine.hasOption("r")) + responseFilePath = commandLine.getOptionValue("r"); + String msgType = commandLine.getOptionValue("t"); + try { + JsonParser parser = new JsonParser(); + JsonObject jsonContent = parser.parse(jsonString).getAsJsonObject(); + MsgService msgService = getMessageService(commandLine); + String returnJsonStr = msgService.generateMsg(msgType, jsonContent); + returnJsonStr = "[" + returnJsonStr + "]"; + if (responseFilePath != null) { + try( PrintWriter out = new PrintWriter( responseFilePath ) ){ + out.println( returnJsonStr ); + } + } else { + System.out.println( returnJsonStr ); + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + System.exit(-1); + } + } + + private MsgService getMessageService(CommandLine commandLine) { + if (commandLine.hasOption("mp")) { + String protocol = commandLine.getOptionValue("mp"); + for (MsgService service : msgServices) { + boolean isEiffel3 = (protocol.equals("eiffel3")); + boolean isEiffel3Service = service.getClass().getName().endsWith("Eiffel3Service"); + if (isEiffel3 && isEiffel3Service) + return service; + + } + } else { + System.out.println( "No protocol has been specified. Semantics is used as default"); + for (MsgService service : msgServices) { + if (service instanceof SemanticsService) + return service; + } + } + + System.out.println( "No protocol service has been found registered."); + System.exit(-3); + return null; + } +} \ No newline at end of file diff --git a/src/main/java/com/ericsson/eiffel/remrem/generate/config/SpringLoggingInitializer.java b/src/main/java/com/ericsson/eiffel/remrem/generate/config/SpringLoggingInitializer.java new file mode 100644 index 00000000..e04c2b2b --- /dev/null +++ b/src/main/java/com/ericsson/eiffel/remrem/generate/config/SpringLoggingInitializer.java @@ -0,0 +1,33 @@ +package com.ericsson.eiffel.remrem.generate.config; + +import org.slf4j.LoggerFactory; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.actuate.endpoint.jmx.EndpointMBeanExporter; +import org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer; +import org.springframework.boot.context.config.ConfigFileApplicationListener; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import com.ericsson.eiffel.remrem.generate.App; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; + +public class SpringLoggingInitializer implements ApplicationContextInitializer { + + /* (non-Javadoc) + * @see org.springframework.context.ApplicationContextInitializer#initialize(org.springframework.context.ConfigurableApplicationContext) + * + * We need to turn off Spring logging since we want write the generated message to console. + */ + @Override + public void initialize(ConfigurableApplicationContext applicationContext) { + Class[] loggers = {SpringApplication.class, App.class, ConfigFileApplicationListener.class, EndpointMBeanExporter.class, + AutoConfigurationReportLoggingInitializer.class}; + Logger log = (Logger) LoggerFactory.getLogger("ROOT"); + log.setLevel(Level.ERROR); + for (Class logger : loggers) { + log = (Logger) LoggerFactory.getLogger(logger); + log.setLevel(Level.ERROR); + } + } +} diff --git a/src/main/java/com/ericsson/eiffel/remrem/generate/config/SwaggerConfig.java b/src/main/java/com/ericsson/eiffel/remrem/generate/config/SwaggerConfig.java index 9a7faebe..c832f7a7 100644 --- a/src/main/java/com/ericsson/eiffel/remrem/generate/config/SwaggerConfig.java +++ b/src/main/java/com/ericsson/eiffel/remrem/generate/config/SwaggerConfig.java @@ -8,7 +8,6 @@ import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; -@Configuration @EnableSwagger2 public class SwaggerConfig { @Bean diff --git a/src/main/java/com/ericsson/eiffel/remrem/generate/controller/Eiffel3Controller.java b/src/main/java/com/ericsson/eiffel/remrem/generate/controller/Eiffel3Controller.java index 6eb63c35..891661e2 100644 --- a/src/main/java/com/ericsson/eiffel/remrem/generate/controller/Eiffel3Controller.java +++ b/src/main/java/com/ericsson/eiffel/remrem/generate/controller/Eiffel3Controller.java @@ -15,7 +15,8 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -@Profile("eiffel3") @RestController @RequestMapping("/eiffel3") public class Eiffel3Controller { +@Profile("eiffel3") @RestController @RequestMapping("/eiffel3") +public class Eiffel3Controller { @Autowired @Qualifier("eiffel3") private MsgService msgService; diff --git a/src/main/java/com/ericsson/eiffel/remrem/generate/controller/EiffelSemanticsController.java b/src/main/java/com/ericsson/eiffel/remrem/generate/controller/EiffelSemanticsController.java index dd37ddcb..498c0141 100644 --- a/src/main/java/com/ericsson/eiffel/remrem/generate/controller/EiffelSemanticsController.java +++ b/src/main/java/com/ericsson/eiffel/remrem/generate/controller/EiffelSemanticsController.java @@ -14,8 +14,6 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; - - @RestController @RequestMapping("/eiffelsemantics") public class EiffelSemanticsController { @Autowired @Qualifier("eiffel-semantics") private MsgService msgService; diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 9983a4df..1f0e0d55 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -2,3 +2,15 @@ spring: http: converters: preferred-json-mapper: gson +debug: false +logging: + level: + root: ERROR + org: + springframework: + web: ERROR +org: + springframework: + boot: + logging: + LoggingSystem: none