]> 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)
committerMalena Ebert <malena.ebert@sonarsource.com>
Wed, 8 Jul 2020 10:39:24 +0000 (12:39 +0200)
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-server/src/test/java/org/sonar/server/app/WebServerProcessLoggingTest.java

index 4e99b5f355c8351927e266ea032201302d533de3..8e54c0e69fd4349ec9225c08e1fd9579b642fec3 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 2203e351c63ec80e42b7a25697e3e89399c59703..5a94b4af7b3b95497c27d4c71a3085bcccab4d7d 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 75a9519aa135c189029e8045f38cea90f8f257d7..c2e11efec66a430e45eb5ccd0928298730e66602 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..df1d14e
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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 e1810fd3ffa692f0d741011964c8acfdf903ae14..41651658a6f0d6b61b16f4f24cb82b732d38446b 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..39adc1a
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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..87e1a25
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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 924e45bec0cee62ff4100a8801e937bf7e084f08..f9b0af9fcb8302bd5ea314a0b5553670041ef97d 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..81cd984
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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..e7858f6
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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 b5612766341d0cc7b0d5f4ce859ed7bd0459da94..a9045e01696e92ea6d21ec1585368ac4caa47e0d 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) {