From 765ae56f6e8c5c303752f606961a3b2d89bb2090 Mon Sep 17 00:00:00 2001 From: Fred Bricon Date: Fri, 11 Sep 2020 16:19:55 +0200 Subject: [PATCH] Redirect stdio streams Signed-off-by: Fred Bricon --- .../org/eclipse/lemminx/NoOpInputStream.java | 66 +++++++++++++++++++ .../org/eclipse/lemminx/NoOpOutputStream.java | 36 ++++++++++ .../org/eclipse/lemminx/NoOpPrintStream.java | 27 ++++++++ .../eclipse/lemminx/XMLLanguageServer.java | 42 ++++++++---- .../eclipse/lemminx/XMLServerLauncher.java | 8 ++- .../org/eclipse/lemminx/logs/LogHelper.java | 50 +++++++------- .../lemminx/settings/LogsSettings.java | 2 +- 7 files changed, 190 insertions(+), 41 deletions(-) create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/NoOpInputStream.java create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/NoOpOutputStream.java create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/NoOpPrintStream.java diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/NoOpInputStream.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/NoOpInputStream.java new file mode 100644 index 000000000..2e7164dbd --- /dev/null +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/NoOpInputStream.java @@ -0,0 +1,66 @@ +/******************************************************************************* +* Copyright (c) 2020 Red Hat Inc. and others. +* All rights reserved. This program and the accompanying materials +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Contributors: +* Red Hat Inc. - initial API and implementation +*******************************************************************************/ +package org.eclipse.lemminx; + +import java.io.IOException; +import java.io.InputStream; + +/** + * No-Op {@link InputStream} + * + * @author Fred Bricon + */ +class NoOpInputStream extends InputStream { + + @Override + public int read() throws IOException { + return -1; + } + + @Override + public int read(byte[] b) throws IOException { + return -1; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + return -1; + } + + @Override + public int available() throws IOException { + return 0; + } + + @Override + public synchronized void mark(int readlimit) { + } + + @Override + public boolean markSupported() { + return true; + } + + @Override + public synchronized void reset() throws IOException { + } + + @Override + public long skip(long n) throws IOException { + return 0; + } + + @Override + public void close() throws IOException { + } + +} diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/NoOpOutputStream.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/NoOpOutputStream.java new file mode 100644 index 000000000..8da85adba --- /dev/null +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/NoOpOutputStream.java @@ -0,0 +1,36 @@ +/******************************************************************************* +* Copyright (c) 2020 Red Hat Inc. and others. +* All rights reserved. This program and the accompanying materials +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Contributors: +* Red Hat Inc. - initial API and implementation +*******************************************************************************/ +package org.eclipse.lemminx; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * No-Op {@link OutputStream}. + * + * @author Fred Bricon + */ +class NoOpOutputStream extends OutputStream { + + @Override + public void write(int b) throws IOException { + } + + @Override + public void write(byte[] b, int off, int len) { + } + + @Override + public void write(byte[] b) throws IOException { + } + +} diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/NoOpPrintStream.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/NoOpPrintStream.java new file mode 100644 index 000000000..f50cee3c2 --- /dev/null +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/NoOpPrintStream.java @@ -0,0 +1,27 @@ +/******************************************************************************* +* Copyright (c) 2020 Red Hat Inc. and others. +* All rights reserved. This program and the accompanying materials +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Contributors: +* Red Hat Inc. - initial API and implementation +*******************************************************************************/ +package org.eclipse.lemminx; + +import java.io.PrintStream; + +/** + * No-Op {@link PrintStream}. + * + * @author Fred Bricon + */ +class NoOpPrintStream extends PrintStream { + + public NoOpPrintStream() { + super(new NoOpOutputStream()); + } + +} diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/XMLLanguageServer.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/XMLLanguageServer.java index 9a97a97d7..6cb941a0e 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/XMLLanguageServer.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/XMLLanguageServer.java @@ -94,6 +94,12 @@ public XMLLanguageServer() { @Override public CompletableFuture initialize(InitializeParams params) { + Object initOptions = InitializationOptionsSettings.getSettings(params); + Object xmlSettings = AllXMLSettings.getAllXMLSettings(initOptions); + XMLGeneralClientSettings settings = XMLGeneralClientSettings.getGeneralXMLSettings(xmlSettings); + + LogHelper.initializeRootLogger(languageClient, settings == null? null : settings.getLogs()); + LOGGER.info("Initializing XML Language server" + System.lineSeparator() + new ServerInfo().details()); this.parentProcessId = params.getProcessId(); @@ -108,7 +114,7 @@ public CompletableFuture initialize(InitializeParams params) { xmlTextDocumentService.updateClientCapabilities(capabilityManager.getClientCapabilities().capabilities, capabilityManager.getClientCapabilities().getExtendedCapabilities()); - updateSettings(InitializationOptionsSettings.getSettings(params)); + updateSettings(initOptions, false /* already configured logging*/ ); ServerCapabilities nonDynamicServerCapabilities = ServerCapabilitiesInitializer.getNonDynamicServerCapabilities( capabilityManager.getClientCapabilities(), xmlTextDocumentService.isIncrementalSupport()); @@ -133,22 +139,31 @@ public void initialized(InitializedParams params) { /** * Update XML settings configured from the client. * - * @param initializationOptionsSettings the XML settings + * @param initOptions the XML settings + */ + public synchronized void updateSettings(Object initOptions) { + updateSettings(initOptions, true); + } + + /** + * Update XML settings configured from the client. + * + * @param initOptions Settings the XML settings + * @param initLogs whether to initialize the log handlers */ - public synchronized void updateSettings(Object initializationOptionsSettings) { - if (initializationOptionsSettings == null) { + private synchronized void updateSettings(Object initOptions, boolean initLogs) { + if (initOptions == null) { return; } // Update client settings - initializationOptionsSettings = AllXMLSettings.getAllXMLSettings(initializationOptionsSettings); - XMLGeneralClientSettings xmlClientSettings = XMLGeneralClientSettings - .getGeneralXMLSettings(initializationOptionsSettings); + Object initSettings = AllXMLSettings.getAllXMLSettings(initOptions); + XMLGeneralClientSettings xmlClientSettings = XMLGeneralClientSettings.getGeneralXMLSettings(initSettings); if (xmlClientSettings != null) { - // Update logs settings - LogsSettings logsSettings = xmlClientSettings.getLogs(); - if (logsSettings != null) { - LogHelper.initializeRootLogger(languageClient, logsSettings); + if (initLogs) { + // Update logs settings + LogHelper.initializeRootLogger(languageClient, xmlClientSettings.getLogs()); } + // Update format settings XMLFormattingOptions formatterSettings = xmlClientSettings.getFormat(); if (formatterSettings != null) { @@ -181,15 +196,14 @@ public synchronized void updateSettings(Object initializationOptionsSettings) { FilesUtils.setCachePathSetting(workDir); } } - ContentModelSettings cmSettings = ContentModelSettings - .getContentModelXMLSettings(initializationOptionsSettings); + ContentModelSettings cmSettings = ContentModelSettings.getContentModelXMLSettings(initSettings); if (cmSettings != null) { XMLValidationSettings validationSettings = cmSettings.getValidation(); xmlTextDocumentService.getValidationSettings().merge(validationSettings); } // Update XML language service extensions - xmlTextDocumentService.updateSettings(initializationOptionsSettings); + xmlTextDocumentService.updateSettings(initSettings); } @Override diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/XMLServerLauncher.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/XMLServerLauncher.java index 963214c9a..df93884a6 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/XMLServerLauncher.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/XMLServerLauncher.java @@ -14,6 +14,7 @@ import java.io.InputStream; import java.io.OutputStream; +import java.io.PrintStream; import java.net.Authenticator; import java.net.PasswordAuthentication; import java.util.concurrent.ExecutorService; @@ -48,7 +49,12 @@ protected PasswordAuthentication getPasswordAuthentication() { }); } - launch(System.in, System.out); + InputStream in = System.in; + PrintStream out = System.out; + System.setIn(new NoOpInputStream()); + System.setOut(new NoOpPrintStream()); + System.setErr(new NoOpPrintStream()); + launch(in, out); } /** diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/logs/LogHelper.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/logs/LogHelper.java index 20a14d933..cc174edb6 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/logs/LogHelper.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/logs/LogHelper.java @@ -31,43 +31,44 @@ */ public class LogHelper { + private static final String ROOT_LOGGER = ""; + // This will apply to all child loggers public static void initializeRootLogger(LanguageClient newLanguageClient, LogsSettings settings) { - if (newLanguageClient == null || settings == null) { + if (newLanguageClient == null) { return; } - Logger logger = Logger.getLogger(""); + Logger logger = Logger.getLogger(ROOT_LOGGER); unregisterAllHandlers(logger.getHandlers()); logger.setLevel(getLogLevel()); logger.setUseParentHandlers(false);// Stops output to console // Configure logging LSP client handler - if (settings.getClient()) { - try { - logger.addHandler(LogHelper.getClientHandler(newLanguageClient)); - } catch (Exception e) { - // TODO: handle exception + if (settings != null) { + if (settings.isClient()) { + try { + logger.addHandler(LogHelper.getClientHandler(newLanguageClient)); + } catch (Exception e) { + // TODO: handle exception + } } - } - - // Configure logging for file - String path = settings.getFile(); - if (path != null) { - createDirectoryPath(path); - try { - FileHandler fh = LogHelper.getFileHandler(path); - logger.addHandler(fh); - - } catch (SecurityException | IOException e) { - logger.warning("Error at creation of FileHandler for logging"); + // Configure logging for file + String path = settings.getFile(); + if (path != null) { + createDirectoryPath(path); + try { + FileHandler fh = LogHelper.getFileHandler(path); + logger.addHandler(fh); + } catch (SecurityException | IOException e) { + logger.warning("Error at creation of FileHandler for logging"); + } + } else { + logger.info("Log file could not be created, path not provided"); } - } else { - logger.info("Log file could not be created, path not provided"); } - } - + private static Level getLogLevel() { String logLevel = System.getProperty("log.level", "info").toLowerCase(); switch (logLevel) { @@ -132,7 +133,7 @@ public static void unregisterHandler(Handler handler) { return; } handler.close(); - Logger.getLogger("").removeHandler(handler); + Logger.getLogger(ROOT_LOGGER).removeHandler(handler); } public static void unregisterAllHandlers(Handler[] handlers) { @@ -141,7 +142,6 @@ public static void unregisterAllHandlers(Handler[] handlers) { } for (Handler h : handlers) { unregisterHandler(h); - ; } } } \ No newline at end of file diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/settings/LogsSettings.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/settings/LogsSettings.java index ac4b19480..ba787d417 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/settings/LogsSettings.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/settings/LogsSettings.java @@ -42,7 +42,7 @@ public void setFile(String file) { * @return true if LSP client is enabled and false * otherwise. */ - public boolean getClient() { + public boolean isClient() { return client; }