]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-13461 fix SSF-112
authorJacek <jacek.poreda@sonarsource.com>
Fri, 26 Jun 2020 13:41:48 +0000 (15:41 +0200)
committersonartech <sonartech@sonarsource.com>
Tue, 30 Jun 2020 20:05:42 +0000 (20:05 +0000)
server/sonar-ce/src/test/java/org/sonar/ce/logging/CeProcessLoggingTest.java
server/sonar-main/src/main/java/org/sonar/application/AppLogging.java
server/sonar-main/src/test/java/org/sonar/application/AppLoggingTest.java
server/sonar-process/src/main/java/org/sonar/process/logging/EscapedMessageConverter.java [new file with mode: 0644]
server/sonar-process/src/main/java/org/sonar/process/logging/LogbackHelper.java
server/sonar-process/src/main/java/org/sonar/process/logging/PatternLayoutEncoder.java [new file with mode: 0644]
server/sonar-process/src/test/java/org/sonar/process/logging/EscapedMessageConverterTest.java [new file with mode: 0644]
server/sonar-process/src/test/java/org/sonar/process/logging/LogbackHelperTest.java
server/sonar-process/src/test/java/org/sonar/process/logging/PatternLayoutEncoderTest.java [new file with mode: 0644]
server/sonar-process/src/test/java/org/sonar/process/logging/TestILoggingEvent.java [new file with mode: 0644]
server/sonar-webserver-core/src/test/java/org/sonar/server/app/WebServerProcessLoggingTest.java

index 2e5d60207a7669e5bbed41a1bb87a3fd34618632..e8ad68179f30ed6ddb0d9cecdacc0e12a07fd1fa 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.ce.logging;
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.Logger;
 import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
 import ch.qos.logback.classic.spi.ILoggingEvent;
 import ch.qos.logback.core.Appender;
 import ch.qos.logback.core.ConsoleAppender;
@@ -40,6 +39,7 @@ import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.process.Props;
 import org.sonar.process.logging.LogbackHelper;
+import org.sonar.process.logging.PatternLayoutEncoder;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.slf4j.Logger.ROOT_LOGGER_NAME;
index 9d2c9a2b2e394b3f12883262736a04d16ec54671..974efbb47731dfd4ba7d53eb824041fa66918afa 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.application;
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.Logger;
 import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
 import ch.qos.logback.classic.spi.ILoggingEvent;
 import ch.qos.logback.core.ConsoleAppender;
 import ch.qos.logback.core.FileAppender;
@@ -32,6 +31,7 @@ import org.sonar.application.process.StreamGobbler;
 import org.sonar.process.ProcessId;
 import org.sonar.process.logging.LogLevelConfig;
 import org.sonar.process.logging.LogbackHelper;
+import org.sonar.process.logging.PatternLayoutEncoder;
 import org.sonar.process.logging.RootLoggerConfig;
 
 import static org.slf4j.Logger.ROOT_LOGGER_NAME;
index a675a68f58bdda27877033bdc0e7feb05a0012ba..c5b185de48846274ec34ff00e8cd168f9dfc00dd 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.application;
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.Logger;
 import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
 import ch.qos.logback.classic.spi.ILoggingEvent;
 import ch.qos.logback.core.Appender;
 import ch.qos.logback.core.ConsoleAppender;
@@ -44,6 +43,7 @@ import org.sonar.application.config.AppSettings;
 import org.sonar.application.config.TestAppSettings;
 import org.sonar.process.logging.LogbackHelper;
 import org.sonar.process.logging.LogbackJsonLayout;
+import org.sonar.process.logging.PatternLayoutEncoder;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.slf4j.Logger.ROOT_LOGGER_NAME;
diff --git a/server/sonar-process/src/main/java/org/sonar/process/logging/EscapedMessageConverter.java b/server/sonar-process/src/main/java/org/sonar/process/logging/EscapedMessageConverter.java
new file mode 100644 (file)
index 0000000..e66f105
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.process.logging;
+
+import ch.qos.logback.classic.pattern.ClassicConverter;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import java.util.regex.Pattern;
+
+/**
+ * Escapes log message which contains CR LF sequence
+ */
+public class EscapedMessageConverter extends ClassicConverter {
+
+  private static final Pattern CR_PATTERN = Pattern.compile("\r");
+  private static final Pattern LF_PATTERN = Pattern.compile("\n");
+
+  public String convert(ILoggingEvent event) {
+    String formattedMessage = event.getFormattedMessage();
+    if (formattedMessage != null) {
+      String result = CR_PATTERN.matcher(formattedMessage).replaceAll("\\\\r");
+      result = LF_PATTERN.matcher(result).replaceAll("\\\\n");
+      return result;
+    }
+    return null;
+  }
+
+}
index 85bb1a407794bd252a4e5c24c15e9805800fe31a..588f7e3e1ba45f3469ae10830c3e652eb25f61fa 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.process.logging;
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.Logger;
 import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
 import ch.qos.logback.classic.joran.JoranConfigurator;
 import ch.qos.logback.classic.jul.LevelChangePropagator;
 import ch.qos.logback.classic.spi.ILoggingEvent;
diff --git a/server/sonar-process/src/main/java/org/sonar/process/logging/PatternLayoutEncoder.java b/server/sonar-process/src/main/java/org/sonar/process/logging/PatternLayoutEncoder.java
new file mode 100644 (file)
index 0000000..9cc88bd
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.process.logging;
+
+import ch.qos.logback.classic.PatternLayout;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.pattern.PatternLayoutEncoderBase;
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+
+public class PatternLayoutEncoder extends PatternLayoutEncoderBase<ILoggingEvent> {
+
+  @Override
+  public void start() {
+    PatternLayout patternLayout = new PatternLayout();
+    patternLayout.getDefaultConverterMap().putAll(getEscapedMessageConverterConfig());
+    patternLayout.setContext(context);
+    patternLayout.setPattern(getPattern());
+    patternLayout.setOutputPatternAsHeader(outputPatternAsHeader);
+    patternLayout.start();
+    this.layout = patternLayout;
+    super.start();
+  }
+
+  private static Map<String, String> getEscapedMessageConverterConfig() {
+    return ImmutableMap.of(
+      "m", EscapedMessageConverter.class.getName(),
+      "msg", EscapedMessageConverter.class.getName(),
+      "message", EscapedMessageConverter.class.getName());
+  }
+
+}
diff --git a/server/sonar-process/src/test/java/org/sonar/process/logging/EscapedMessageConverterTest.java b/server/sonar-process/src/test/java/org/sonar/process/logging/EscapedMessageConverterTest.java
new file mode 100644 (file)
index 0000000..7411209
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.process.logging;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class EscapedMessageConverterTest {
+
+  private final EscapedMessageConverter underTest = new EscapedMessageConverter();
+
+  @Test
+  public void convert_null_message() {
+    ILoggingEvent event = createILoggingEvent(null);
+    assertThat(underTest.convert(event)).isNull();
+  }
+
+  @Test
+  public void convert_simple_message() {
+    ILoggingEvent event = createILoggingEvent("simple message");
+    assertThat(underTest.convert(event)).isEqualTo("simple message");
+  }
+
+  @Test
+  public void convert_message_with_CR() {
+    ILoggingEvent event = createILoggingEvent("simple\r message\r with\r CR\r");
+    assertThat(underTest.convert(event)).isEqualTo("simple\\r message\\r with\\r CR\\r");
+  }
+
+  @Test
+  public void convert_message_with_LF() {
+    ILoggingEvent event = createILoggingEvent("simple\n message\n with\n LF");
+    assertThat(underTest.convert(event)).isEqualTo("simple\\n message\\n with\\n LF");
+  }
+
+  @Test
+  public void convert_message_with_CRLF() {
+    ILoggingEvent event = createILoggingEvent("simple\n\r\n message\r with\r\n CR LF");
+    assertThat(underTest.convert(event)).isEqualTo("simple\\n\\r\\n message\\r with\\r\\n CR LF");
+  }
+
+  private static ILoggingEvent createILoggingEvent(String message) {
+    return new TestILoggingEvent(message);
+  }
+
+}
index 6603260c9ad19032915f392c280fa0959d869ce4..3fa05bebd51ec807cb462c3e717d33ba1c07eee0 100644 (file)
@@ -21,7 +21,6 @@ package org.sonar.process.logging;
 
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
 import ch.qos.logback.classic.spi.ILoggingEvent;
 import ch.qos.logback.classic.spi.LoggerContextListener;
 import ch.qos.logback.core.Appender;
diff --git a/server/sonar-process/src/test/java/org/sonar/process/logging/PatternLayoutEncoderTest.java b/server/sonar-process/src/test/java/org/sonar/process/logging/PatternLayoutEncoderTest.java
new file mode 100644 (file)
index 0000000..55d5edb
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.process.logging;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.entry;
+
+public class PatternLayoutEncoderTest {
+
+  PatternLayoutEncoder underTest = new PatternLayoutEncoder();
+
+  @Before
+  public void before() {
+    underTest.start();
+  }
+
+  @Test
+  public void start_should_initialize_escaped_message_converter() {
+    assertThat(underTest.getLayout())
+      .isInstanceOf(ch.qos.logback.classic.PatternLayout.class);
+
+    assertThat(((ch.qos.logback.classic.PatternLayout) underTest.getLayout()).getDefaultConverterMap())
+      .contains(
+        entry("m", EscapedMessageConverter.class.getName()),
+        entry("msg", EscapedMessageConverter.class.getName()),
+        entry("message", EscapedMessageConverter.class.getName()));
+  }
+
+}
diff --git a/server/sonar-process/src/test/java/org/sonar/process/logging/TestILoggingEvent.java b/server/sonar-process/src/test/java/org/sonar/process/logging/TestILoggingEvent.java
new file mode 100644 (file)
index 0000000..9214430
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.process.logging;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.classic.spi.IThrowableProxy;
+import ch.qos.logback.classic.spi.LoggerContextVO;
+import java.util.Map;
+import org.slf4j.Marker;
+
+public class TestILoggingEvent implements ILoggingEvent {
+  private String formattedMessage;
+
+  public TestILoggingEvent(String formattedMessage) {
+    this.formattedMessage = formattedMessage;
+  }
+
+  @Override
+  public String getThreadName() {
+    return null;
+  }
+
+  @Override
+  public Level getLevel() {
+    return null;
+  }
+
+  @Override
+  public String getMessage() {
+    return null;
+  }
+
+  @Override
+  public Object[] getArgumentArray() {
+    return null;
+  }
+
+  @Override
+  public String getFormattedMessage() {
+    return this.formattedMessage;
+  }
+
+  @Override
+  public String getLoggerName() {
+    return null;
+  }
+
+  @Override
+  public LoggerContextVO getLoggerContextVO() {
+    return null;
+  }
+
+  @Override
+  public IThrowableProxy getThrowableProxy() {
+    return null;
+  }
+
+  @Override
+  public StackTraceElement[] getCallerData() {
+    return new StackTraceElement[0];
+  }
+
+  @Override
+  public boolean hasCallerData() {
+    return false;
+  }
+
+  @Override
+  public Marker getMarker() {
+    return null;
+  }
+
+  @Override
+  public Map<String, String> getMDCPropertyMap() {
+    return null;
+  }
+
+  @Override
+  public Map<String, String> getMdc() {
+    return null;
+  }
+
+  @Override
+  public long getTimeStamp() {
+    return 0;
+  }
+
+  @Override
+  public void prepareForDeferredProcessing() {
+
+  }
+}
index c47feaaf1ba298f6ad096cc80fc5550996fe87fb..62bc9287bbaf4a8dacc392b2656991ca77537fea 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.server.app;
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.Logger;
 import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
 import ch.qos.logback.classic.spi.ILoggingEvent;
 import ch.qos.logback.core.Appender;
 import ch.qos.logback.core.AppenderBase;
@@ -48,6 +47,7 @@ import org.junit.rules.TemporaryFolder;
 import org.sonar.process.Props;
 import org.sonar.process.logging.LogbackHelper;
 import org.sonar.process.logging.LogbackJsonLayout;
+import org.sonar.process.logging.PatternLayoutEncoder;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.slf4j.Logger.ROOT_LOGGER_NAME;
@@ -508,10 +508,10 @@ public class WebServerProcessLoggingTest {
     LoggerContext context = underTest.configure(props);
 
     Logger rootLogger = context.getLogger(ROOT_LOGGER_NAME);
-    OutputStreamAppender appender = (OutputStreamAppender)rootLogger.getAppender("file_web");
+    OutputStreamAppender appender = (OutputStreamAppender) rootLogger.getAppender("file_web");
     Encoder<ILoggingEvent> encoder = appender.getEncoder();
     assertThat(encoder).isInstanceOf(LayoutWrappingEncoder.class);
-    assertThat(((LayoutWrappingEncoder)encoder).getLayout()).isInstanceOf(LogbackJsonLayout.class);
+    assertThat(((LayoutWrappingEncoder) encoder).getLayout()).isInstanceOf(LogbackJsonLayout.class);
   }
 
   private void verifyRootLogLevel(LoggerContext ctx, Level expected) {