diff --git a/plugins/org.eclipse.glsp.server.websocket/src/org/eclipse/glsp/server/websocket/WebsocketServerLauncher.java b/plugins/org.eclipse.glsp.server.websocket/src/org/eclipse/glsp/server/websocket/WebsocketServerLauncher.java
index 928f2499..617c106c 100644
--- a/plugins/org.eclipse.glsp.server.websocket/src/org/eclipse/glsp/server/websocket/WebsocketServerLauncher.java
+++ b/plugins/org.eclipse.glsp.server.websocket/src/org/eclipse/glsp/server/websocket/WebsocketServerLauncher.java
@@ -29,9 +29,6 @@
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
-import com.google.inject.Guice;
-import com.google.inject.Injector;
-
public class WebsocketServerLauncher extends GLSPServerLauncher {
private static Logger LOG = Logger.getLogger(WebsocketServerLauncher.class);
private Server server;
@@ -41,6 +38,7 @@ public class WebsocketServerLauncher extends GLSPServerLauncher {
public WebsocketServerLauncher(final GLSPModule module, final String endpointPath) {
super(module);
this.endpointPath = endpointPath.startsWith("/") ? endpointPath.substring(1) : endpointPath;
+ addAdditionalModules(new WebsocketModule());
}
public WebsocketServerLauncher(final GLSPModule module, final String endpointPath, final String clientAppPath) {
@@ -48,14 +46,9 @@ public WebsocketServerLauncher(final GLSPModule module, final String endpointPat
this.clientAppPath = clientAppPath;
}
- @Override
- protected Injector doSetup() {
- return Guice.createInjector(getGLSPModule(), new WebsocketModule());
- }
-
@Override
@SuppressWarnings("checkstyle:IllegalCatch")
- public void run(final String hostname, final int port) {
+ public void start(final String hostname, final int port) {
try {
// Setup Jetty Server
server = new Server(new InetSocketAddress(hostname, port));
@@ -82,7 +75,7 @@ public void run(final String hostname, final int port) {
ServerContainer container = WebSocketServerContainerInitializer.configureContext(webAppContext);
ServerEndpointConfig.Builder builder = ServerEndpointConfig.Builder.create(GLSPServerEndpoint.class,
"/" + endpointPath);
- builder.configurator(new GLSPConfigurator(getInjector()));
+ builder.configurator(new GLSPConfigurator(createInjector()));
container.addEndpoint(builder.build());
// Start the server
diff --git a/plugins/org.eclipse.glsp.server/META-INF/MANIFEST.MF b/plugins/org.eclipse.glsp.server/META-INF/MANIFEST.MF
index ecf3da99..1cd0c668 100644
--- a/plugins/org.eclipse.glsp.server/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.glsp.server/META-INF/MANIFEST.MF
@@ -12,7 +12,8 @@ Require-Bundle: org.eclipse.glsp.api;bundle-version="0.7.0";visibility:=reexport
com.google.gson;bundle-version="2.8.2",
org.eclipse.lsp4j;bundle-version="0.7.0",
org.eclipse.lsp4j.jsonrpc,
- com.google.guava;bundle-version="21.0.0"
+ com.google.guava;bundle-version="21.0.0",
+ org.apache.commons.cli;bundle-version="1.4.0";visibility:=reexport
Import-Package: com.google.inject.multibindings;version="1.3.0"
Export-Package: org.eclipse.glsp.server.actionhandler,
org.eclipse.glsp.server.command,
diff --git a/plugins/org.eclipse.glsp.server/pom.xml b/plugins/org.eclipse.glsp.server/pom.xml
index 4f0a0ecf..be06e432 100644
--- a/plugins/org.eclipse.glsp.server/pom.xml
+++ b/plugins/org.eclipse.glsp.server/pom.xml
@@ -64,6 +64,11 @@
org.eclipse.emf.ecore.change
2.14.0
+
+ commons-cli
+ commons-cli
+ 1.4
+
diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/launch/CLIParser.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/launch/CLIParser.java
new file mode 100644
index 00000000..351f4d4e
--- /dev/null
+++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/launch/CLIParser.java
@@ -0,0 +1,92 @@
+/********************************************************************************
+ * Copyright (c) 2020 EclipseSource and others.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * https://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the Eclipse
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
+ * with the GNU Classpath Exception which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ ********************************************************************************/
+package org.eclipse.glsp.server.launch;
+
+import java.util.function.Predicate;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.log4j.Logger;
+import org.eclipse.glsp.server.utils.LaunchUtil;
+
+public abstract class CLIParser {
+ private static final Logger LOG = Logger.getLogger(CLIParser.class);
+ protected static final String INVALID_ARGUMENT_MESSAGE = "%s' is not a valid argument for option '--%s'! The default value '%s' is used.";
+
+ protected final CommandLine cmd;
+ protected final Options options;
+ protected final String processName;
+
+ public CLIParser(final String[] args, final Options options, final String processName) throws ParseException {
+ this.cmd = new DefaultParser().parse(options, args);
+ this.options = options;
+ this.processName = processName;
+ }
+
+ public boolean hasOption(final String optionName) {
+ return cmd.hasOption(optionName);
+ }
+
+ public String parseOption(final String optionName, final String defaultValue) {
+ return parseOption(optionName, defaultValue, null);
+ }
+
+ public String parseOption(final String optionName, final String defaultValue, final Predicate validator) {
+ String arg = cmd.getOptionValue(optionName);
+ if (arg != null) {
+ if (validator == null || validator.test(arg)) {
+ return arg;
+ }
+ LOG.warn(String.format(INVALID_ARGUMENT_MESSAGE,
+ arg, optionName, defaultValue));
+ }
+ return defaultValue;
+ }
+
+ public int parseIntOption(final String optionName, final int defaultValue) {
+ return parseIntOption(optionName, defaultValue, null);
+ }
+
+ public int parseIntOption(final String optionName, final int defaultValue, final Predicate validator) {
+ String intArg = cmd.getOptionValue(optionName);
+ int value = defaultValue;
+ if (intArg != null) {
+ try {
+ value = Integer.parseInt(intArg);
+ if (validator != null && !validator.test(value)) {
+ throw new NumberFormatException();
+ }
+ } catch (NumberFormatException e) {
+ LOG.warn(String.format(INVALID_ARGUMENT_MESSAGE,
+ intArg, optionName, defaultValue));
+ }
+ }
+ return value;
+ }
+
+ public boolean parseBoolOption(final String optionName, final boolean defaultValue) {
+ String arg = cmd.getOptionValue(optionName);
+ return arg != null ? Boolean.parseBoolean(arg) : defaultValue;
+ }
+
+ public void printHelp() {
+ LaunchUtil.printHelp(this.processName, options);
+ }
+
+ public CommandLine getCmd() { return cmd; }
+}
diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/launch/DefaultCLIParser.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/launch/DefaultCLIParser.java
new file mode 100644
index 00000000..fbd4e352
--- /dev/null
+++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/launch/DefaultCLIParser.java
@@ -0,0 +1,85 @@
+/********************************************************************************
+ * Copyright (c) 2020 EclipseSource and others.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * https://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the Eclipse
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
+ * with the GNU Classpath Exception which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ ********************************************************************************/
+package org.eclipse.glsp.server.launch;
+
+import java.io.File;
+import java.util.function.Predicate;
+
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.log4j.Level;
+import org.eclipse.glsp.server.utils.LaunchUtil;
+import org.eclipse.glsp.server.utils.LaunchUtil.DefaultOptions;
+
+public class DefaultCLIParser extends CLIParser {
+ public static final String OPTION_HELP = "help";
+ public static final String OPTION_PORT = "port";
+ public static final String OPTION_CONSOLE_LOG = "consoleLog";
+ public static final String OPTION_FILE_LOG = "fileLog";
+ public static final String OPTION_LOG_LEVEL = "logLevel";
+ public static final String OPTION_LOG_DIR = "logDir";
+
+ public DefaultCLIParser(final String[] args, final String processName) throws ParseException {
+ this(args, getDefaultOptions(), processName);
+ }
+
+ public DefaultCLIParser(final String[] args, final Options options, final String processName) throws ParseException {
+ super(args, options, processName);
+ }
+
+ public int parsePort() {
+ Predicate validator = (port) -> LaunchUtil.isValidPort(port);
+ return parseIntOption(OPTION_PORT, DefaultOptions.SERVER_PORT, validator);
+ }
+
+ public String parseLogDir() {
+ Predicate validator = (logDirArg) -> {
+ File file = new File(logDirArg);
+ return file.exists() && file.isDirectory();
+ };
+ String logDir = parseOption(OPTION_LOG_DIR, DefaultOptions.LOG_DIR, validator);
+ return new File(logDir).getAbsolutePath();
+ }
+
+ public Level parseLogLevel() {
+ String levelArg = parseOption(OPTION_LOG_LEVEL, DefaultOptions.LOG_LEVEL.toString());
+ return Level.toLevel(levelArg, DefaultOptions.LOG_LEVEL);
+ }
+
+ public boolean isConsoleLog() { return parseBoolOption(OPTION_CONSOLE_LOG, DefaultOptions.CONSOLE_LOG_ENABLED); }
+
+ public boolean isFileLog() { return parseBoolOption(OPTION_FILE_LOG, DefaultOptions.FILE_LOG_ENABLED); }
+
+ public boolean isHelp() { return hasOption(OPTION_HELP); }
+
+ public static Options getDefaultOptions() {
+ Options options = new Options();
+ options.addOption(null, OPTION_HELP, false, "Display usage information about GLSPServerLauncher");
+ options.addOption(null, OPTION_PORT, true,
+ String.format("Set server port. [default='%s']", DefaultOptions.SERVER_PORT));
+ options.addOption(null, OPTION_CONSOLE_LOG, true,
+ String.format("Enable/Disable console logging. [default='%s']", DefaultOptions.CONSOLE_LOG_ENABLED));
+ options.addOption(null, OPTION_FILE_LOG, true,
+ String.format("Enable/Disable file logging. [default='%s']", DefaultOptions.FILE_LOG_ENABLED));
+ options.addOption(null, OPTION_LOG_DIR, true,
+ String.format("Set the directory for log files (File logging has to be enabled). [default='%s']",
+ DefaultOptions.LOG_DIR));
+ options.addOption(null, OPTION_LOG_LEVEL, true,
+ String.format("Set the log level. [default='%s']", DefaultOptions.LOG_LEVEL));
+ return options;
+ }
+
+}
diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/launch/DefaultGLSPServerLauncher.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/launch/DefaultGLSPServerLauncher.java
index bafd4c24..64988339 100644
--- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/launch/DefaultGLSPServerLauncher.java
+++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/launch/DefaultGLSPServerLauncher.java
@@ -40,7 +40,6 @@
import org.eclipse.lsp4j.jsonrpc.MessageConsumer;
import com.google.gson.GsonBuilder;
-import com.google.inject.Guice;
import com.google.inject.Injector;
public class DefaultGLSPServerLauncher extends GLSPServerLauncher {
@@ -50,22 +49,20 @@ public class DefaultGLSPServerLauncher extends GLSPServerLauncher {
private AsynchronousServerSocketChannel serverSocket;
private CompletableFuture onShutdown;
- public DefaultGLSPServerLauncher(final GLSPModule module) {
- super(module);
+ public DefaultGLSPServerLauncher(final GLSPModule glspModule) {
+ super(glspModule);
}
@Override
- public void run(final String hostname, final int port) {
+ public void start(final String hostname, final int port) {
Future onClose;
try {
onClose = asyncRun(hostname, port);
onClose.get();
log.info("Stopped GLSP server");
} catch (IOException | InterruptedException | ExecutionException e) {
- log.error(e.getMessage());
- e.printStackTrace();
+ log.error("Error during server close!", e);
}
-
}
public Future asyncRun(final String hostname, final int port)
@@ -89,13 +86,13 @@ public void failed(final Throwable exc, final Void attachment) {
};
serverSocket.accept(null, handler);
- log.info("The GLSP server is ready to accept new client requests");
+ log.info("The GLSP server is ready to accept new client requests on port: " + port);
return onShutdown;
}
private void createClientConnection(final AsynchronousSocketChannel socketChannel) {
- Injector injector = Guice.createInjector(getGLSPModule());
+ Injector injector = createInjector();
GsonConfigurator gsonConf = injector.getInstance(GsonConfigurator.class);
try {
InputStream in = Channels.newInputStream(socketChannel);
@@ -117,7 +114,7 @@ private void createClientConnection(final AsynchronousSocketChannel socketChanne
try {
socketChannel.close();
} catch (IOException e) {
- log.debug("Excpetion occured when trying to close socketChannel", e);
+ log.error("Excpetion occured when trying to close socketChannel", e);
}
}
}
diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/launch/GLSPServerLauncher.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/launch/GLSPServerLauncher.java
index 68378971..b7b5e628 100644
--- a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/launch/GLSPServerLauncher.java
+++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/launch/GLSPServerLauncher.java
@@ -15,40 +15,40 @@
********************************************************************************/
package org.eclipse.glsp.server.launch;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
import org.eclipse.glsp.api.di.GLSPModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
+import com.google.inject.Module;
public abstract class GLSPServerLauncher {
- private GLSPModule module;
- private Injector injector;
-
- public GLSPServerLauncher() {}
+ private final GLSPModule glspModule;
+ private final List modules;
- public GLSPServerLauncher(final GLSPModule module) {
- this.module = module;
+ public GLSPServerLauncher(final GLSPModule glspModule) {
+ this.glspModule = glspModule;
+ modules = new ArrayList<>();
+ modules.add(glspModule);
}
- protected Injector doSetup() {
- return Guice.createInjector(module);
+ public void addAdditionalModules(final Module... modules) {
+ Arrays.stream(modules)
+ .filter(module -> !this.modules.contains(module))
+ .forEach(this.modules::add);
}
- public void start(final String hostname, final int port) {
- if (injector == null) {
- injector = doSetup();
- }
- run(hostname, port);
+ public Injector createInjector() {
+ return Guice.createInjector(modules);
}
- protected abstract void run(String hostname, int port);
+ public abstract void start(String hostname, int port);
public abstract void shutdown();
- public GLSPModule getGLSPModule() { return module; }
-
- public Injector getInjector() { return injector; }
-
- public void setModule(final GLSPModule module) { this.module = module; }
+ public GLSPModule getGLSPModule() { return glspModule; }
}
diff --git a/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/utils/LaunchUtil.java b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/utils/LaunchUtil.java
new file mode 100644
index 00000000..1761ba6a
--- /dev/null
+++ b/plugins/org.eclipse.glsp.server/src/org/eclipse/glsp/server/utils/LaunchUtil.java
@@ -0,0 +1,115 @@
+/********************************************************************************
+ * Copyright (c) 2020 EclipseSource and others.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * https://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the Eclipse
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
+ * with the GNU Classpath Exception which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ ********************************************************************************/
+package org.eclipse.glsp.server.utils;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.log4j.Appender;
+import org.apache.log4j.ConsoleAppender;
+import org.apache.log4j.FileAppender;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.log4j.PatternLayout;
+import org.eclipse.glsp.server.launch.DefaultCLIParser;
+
+public final class LaunchUtil {
+ private static Logger LOG = Logger.getLogger(LaunchUtil.class);
+
+ private LaunchUtil() {}
+
+ public static final class DefaultOptions {
+ public static final int SERVER_PORT = 5007;
+ public static final Level LOG_LEVEL = Level.INFO;
+ public static final String LOG_DIR = new File("./logs/").getAbsolutePath();
+ public static final boolean CONSOLE_LOG_ENABLED = true;
+ public static final boolean FILE_LOG_ENABLED = false;
+ }
+
+ public static boolean isValidPort(final Integer port) {
+ return port >= 0 && port <= 65535;
+ }
+
+ public static void configure(final DefaultCLIParser cli) throws ParseException, IOException {
+ if (cli.isHelp()) {
+ cli.printHelp();
+ System.exit(0);
+ }
+ configureLogger(cli);
+ if (cli.hasOption(DefaultCLIParser.OPTION_LOG_DIR) && !cli.isFileLog()) {
+ LOG.warn(String.format("File logging is disabled. The option '--%s' will be ignored.",
+ DefaultCLIParser.OPTION_LOG_DIR));
+ }
+ }
+
+ public static void configureLogger(final DefaultCLIParser cli) throws ParseException, IOException {
+ if (cli.isFileLog()) {
+ configureLogger(cli.isConsoleLog(), cli.parseLogDir(), cli.parseLogLevel());
+ } else {
+ configureLogger(cli.isConsoleLog(), cli.parseLogLevel());
+ }
+ }
+
+ public static void configureLogger(final boolean logToConsole, final Level logLevel) throws IOException {
+ configureLogger(logToConsole, null, logLevel);
+ }
+
+ public static void configureLogger(final boolean logToConsole, final String logDir, final Level logLevel)
+ throws IOException {
+ Logger root = Logger.getRootLogger();
+ List consoleAppenders = getAppenders(root, ConsoleAppender.class);
+ if (logToConsole) {
+ if (consoleAppenders.isEmpty()) {
+ root.addAppender(new ConsoleAppender(
+ new PatternLayout(PatternLayout.TTCC_CONVERSION_PATTERN)));
+ }
+ } else {
+ // Remove all console log appenders
+ consoleAppenders.forEach(root::removeAppender);
+ }
+ if (logDir != null && !logDir.isEmpty()) {
+ SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy_HH:mm:ss");
+ String fileName = formatter.format(new Date()) + ".log";
+ String logFile = new File(logDir, fileName).getAbsolutePath();
+ root.addAppender(
+ new FileAppender(new PatternLayout(PatternLayout.TTCC_CONVERSION_PATTERN), logFile));
+ }
+ root.setLevel(logLevel);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static List getAppenders(final Logger logger, final Class clazz) {
+ List result = new ArrayList<>();
+ logger.getAllAppenders().asIterator().forEachRemaining((appender) -> {
+ if (clazz.isInstance(appender)) {
+ result.add(clazz.cast(appender));
+ }
+ });
+ return result;
+ }
+
+ public static void printHelp(final String processName, final Options options) {
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp(90, processName, "\noptions:", options, "", true);
+ }
+}
diff --git a/targetplatforms/r2020-06.target b/targetplatforms/r2020-06.target
index c8e099f0..2df077d8 100644
--- a/targetplatforms/r2020-06.target
+++ b/targetplatforms/r2020-06.target
@@ -1,7 +1,7 @@
-
+
@@ -11,6 +11,7 @@
+
diff --git a/targetplatforms/r2020-06.tpd b/targetplatforms/r2020-06.tpd
index bfdd3b04..b95a1aec 100644
--- a/targetplatforms/r2020-06.tpd
+++ b/targetplatforms/r2020-06.tpd
@@ -8,6 +8,7 @@ location "http://download.eclipse.org/releases/2020-06" {
location "https://download.eclipse.org/tools/orbit/downloads/drops/R20200529191137/repository/" {
org.apache.log4j
+ org.apache.commons.cli
org.apache.commons.io
javax.servlet
com.google.gson [2.8.2,3.0.0)