diff options
author | Julien HENRY <julien.henry@sonarsource.com> | 2016-03-17 17:05:56 +0100 |
---|---|---|
committer | Julien HENRY <julien.henry@sonarsource.com> | 2016-03-18 09:35:05 +0100 |
commit | cfcbe278f7ced12599d898d50f3fe68bfbf95155 (patch) | |
tree | 5b4116ad08a8ba87ffc5bf9f159a431b9609b48f /sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper | |
parent | 38ce80934961773a9a35ec0401994b3d726597dc (diff) | |
download | sonarqube-cfcbe278f7ced12599d898d50f3fe68bfbf95155.tar.gz sonarqube-cfcbe278f7ced12599d898d50f3fe68bfbf95155.zip |
Rename batch into scanner
Diffstat (limited to 'sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper')
8 files changed, 846 insertions, 0 deletions
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/Batch.java b/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/Batch.java new file mode 100644 index 00000000000..d5d3da13087 --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/Batch.java @@ -0,0 +1,274 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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.batch.bootstrapper; + +import org.sonar.api.utils.MessageException; + +import com.google.common.base.Throwables; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.picocontainer.annotations.Nullable; +import org.sonar.batch.bootstrap.GlobalContainer; + +/** + * Entry point for sonar-runner 2.1. + * + * @since 2.14 + */ +public final class Batch { + + private boolean started = false; + private LoggingConfiguration loggingConfig; + private List<Object> components; + private Map<String, String> bootstrapProperties = Maps.newHashMap(); + private GlobalContainer bootstrapContainer; + + private Batch(Builder builder) { + components = Lists.newArrayList(); + components.addAll(builder.components); + if (builder.environment != null) { + components.add(builder.environment); + } + if (builder.bootstrapProperties != null) { + bootstrapProperties.putAll(builder.bootstrapProperties); + } + if (builder.isEnableLoggingConfiguration()) { + loggingConfig = new LoggingConfiguration(builder.environment).setProperties(bootstrapProperties); + + if (builder.logOutput != null) { + loggingConfig.setLogOutput(builder.logOutput); + } + } + } + + public LoggingConfiguration getLoggingConfiguration() { + return loggingConfig; + } + + /** + * @deprecated since 4.4 use {@link #start()}, {@link #executeTask(Map)} and then {@link #stop()} + */ + @Deprecated + public synchronized Batch execute() { + configureLogging(); + start(); + boolean threw = true; + try { + executeTask(bootstrapProperties); + threw = false; + } finally { + doStop(threw); + } + + return this; + } + + /** + * @since 4.4 + */ + public synchronized Batch start() { + return start(false); + } + + public synchronized Batch start(boolean preferCache) { + if (started) { + throw new IllegalStateException("Batch is already started"); + } + + configureLogging(); + try { + bootstrapContainer = GlobalContainer.create(bootstrapProperties, components, preferCache); + bootstrapContainer.startComponents(); + } catch (RuntimeException e) { + throw handleException(e); + } + this.started = true; + + return this; + } + + /** + * @since 4.4 + */ + public Batch executeTask(Map<String, String> analysisProperties, Object... components) { + checkStarted(); + configureTaskLogging(analysisProperties); + try { + bootstrapContainer.executeTask(analysisProperties, components); + } catch (RuntimeException e) { + throw handleException(e); + } + return this; + } + + /** + * @since 5.2 + */ + public Batch executeTask(Map<String, String> analysisProperties, IssueListener issueListener) { + checkStarted(); + configureTaskLogging(analysisProperties); + try { + bootstrapContainer.executeTask(analysisProperties, components, issueListener); + } catch (RuntimeException e) { + throw handleException(e); + } + return this; + } + + private void checkStarted() { + if (!started) { + throw new IllegalStateException("Batch is not started. Unable to execute task."); + } + } + + private RuntimeException handleException(RuntimeException t) { + if (loggingConfig.isVerbose()) { + return t; + } + + for (Throwable y : Throwables.getCausalChain(t)) { + if (y instanceof MessageException) { + return (MessageException) y; + } + } + + return t; + } + + /** + * @since 5.2 + */ + public Batch syncProject(String projectKey) { + checkStarted(); + bootstrapContainer.syncProject(projectKey, true); + return this; + } + + /** + * @since 4.4 + */ + public synchronized void stop() { + doStop(false); + } + + private void doStop(boolean swallowException) { + checkStarted(); + configureLogging(); + try { + bootstrapContainer.stopComponents(swallowException); + } catch (RuntimeException e) { + throw handleException(e); + } + this.started = false; + } + + private void configureLogging() { + if (loggingConfig != null) { + loggingConfig.setProperties(bootstrapProperties); + LoggingConfigurator.apply(loggingConfig); + } + } + + private void configureTaskLogging(Map<String, String> taskProperties) { + if (loggingConfig != null) { + loggingConfig.setProperties(taskProperties, bootstrapProperties); + LoggingConfigurator.apply(loggingConfig); + } + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private Map<String, String> bootstrapProperties; + private EnvironmentInformation environment; + private List<Object> components = Lists.newArrayList(); + private boolean enableLoggingConfiguration = true; + private LogOutput logOutput; + + private Builder() { + } + + public Builder setEnvironment(EnvironmentInformation env) { + this.environment = env; + return this; + } + + public Builder setComponents(List<Object> l) { + this.components = l; + return this; + } + + public Builder setLogOutput(@Nullable LogOutput logOutput) { + this.logOutput = logOutput; + return this; + } + + /** + * @deprecated since 3.7 use {@link #setBootstrapProperties(Map)} + */ + @Deprecated + public Builder setGlobalProperties(Map<String, String> globalProperties) { + this.bootstrapProperties = globalProperties; + return this; + } + + public Builder setBootstrapProperties(Map<String, String> bootstrapProperties) { + this.bootstrapProperties = bootstrapProperties; + return this; + } + + public Builder addComponents(Object... components) { + Collections.addAll(this.components, components); + return this; + } + + public Builder addComponent(Object component) { + this.components.add(component); + return this; + } + + public boolean isEnableLoggingConfiguration() { + return enableLoggingConfiguration; + } + + /** + * Logback is configured by default. It can be disabled, but n this case the batch bootstrapper must provide its + * own implementation of SLF4J. + */ + public Builder setEnableLoggingConfiguration(boolean b) { + this.enableLoggingConfiguration = b; + return this; + } + + public Batch build() { + if (components == null) { + throw new IllegalStateException("Batch components are not set"); + } + return new Batch(this); + } + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/EnvironmentInformation.java b/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/EnvironmentInformation.java new file mode 100644 index 00000000000..a04da9df40a --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/EnvironmentInformation.java @@ -0,0 +1,59 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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.batch.bootstrapper; + +import org.sonar.api.batch.BatchSide; + +/** + * Describes execution environment. + * + * @since 2.6 + */ +@BatchSide +public class EnvironmentInformation { + + private String key; + private String version; + + public EnvironmentInformation(String key, String version) { + this.key = key; + this.version = version; + } + + /** + * @return unique key of environment, for example - "maven", "ant" + */ + public String getKey() { + return key; + } + + /** + * @return version of environment, for example Maven can have "2.2.1" or "3.0.2", + * but there is no guarantees about format - it's just a string. + */ + public String getVersion() { + return version; + } + + @Override + public String toString() { + return String.format("%s/%s", key, version); + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/IssueListener.java b/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/IssueListener.java new file mode 100644 index 00000000000..bf3f399142a --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/IssueListener.java @@ -0,0 +1,167 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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.batch.bootstrapper; + +public interface IssueListener { + void handle(Issue issue); + + class Issue { + /** @since 5.3 */ + private Integer startLine; + /** @since 5.3 */ + private Integer startLineOffset; + /** @since 5.3 */ + private Integer endLine; + /** @since 5.3 */ + private Integer endLineOffset; + + private String key; + private String componentKey; + private String message; + private String ruleKey; + private String ruleName; + private String status; + private String resolution; + private boolean isNew; + private String assigneeLogin; + private String assigneeName; + private String severity; + + public String getSeverity() { + return severity; + } + + public void setSeverity(String severity) { + this.severity = severity; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getComponentKey() { + return componentKey; + } + + public void setComponentKey(String componentKey) { + this.componentKey = componentKey; + } + + public Integer getStartLine() { + return startLine; + } + + public void setStartLine(Integer startLine) { + this.startLine = startLine; + } + + public Integer getStartLineOffset() { + return startLineOffset; + } + + public void setStartLineOffset(Integer startLineOffset) { + this.startLineOffset = startLineOffset; + } + + public Integer getEndLine() { + return endLine; + } + + public void setEndLine(Integer endLine) { + this.endLine = endLine; + } + + public Integer getEndLineOffset() { + return endLineOffset; + } + + public void setEndLineOffset(Integer endLineOffset) { + this.endLineOffset = endLineOffset; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getRuleKey() { + return ruleKey; + } + + public void setRuleKey(String ruleKey) { + this.ruleKey = ruleKey; + } + + public String getRuleName() { + return ruleName; + } + + public void setRuleName(String ruleName) { + this.ruleName = ruleName; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getResolution() { + return resolution; + } + + public void setResolution(String resolution) { + this.resolution = resolution; + } + + public boolean isNew() { + return isNew; + } + + public void setNew(boolean isNew) { + this.isNew = isNew; + } + + public String getAssigneeLogin() { + return assigneeLogin; + } + + public void setAssigneeLogin(String assigneeLogin) { + this.assigneeLogin = assigneeLogin; + } + + public String getAssigneeName() { + return assigneeName; + } + + public void setAssigneeName(String assigneeName) { + this.assigneeName = assigneeName; + } + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/LogCallbackAppender.java b/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/LogCallbackAppender.java new file mode 100644 index 00000000000..183cd378711 --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/LogCallbackAppender.java @@ -0,0 +1,57 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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.batch.bootstrapper; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.UnsynchronizedAppenderBase; + +public class LogCallbackAppender extends UnsynchronizedAppenderBase<ILoggingEvent> { + protected LogOutput target; + + public LogCallbackAppender(LogOutput target) { + setTarget(target); + } + + public void setTarget(LogOutput target) { + this.target = target; + } + + @Override + protected void append(ILoggingEvent event) { + target.log(event.getFormattedMessage(), translate(event.getLevel())); + } + + private static LogOutput.Level translate(Level level) { + switch (level.toInt()) { + case Level.ERROR_INT: + return LogOutput.Level.ERROR; + case Level.WARN_INT: + return LogOutput.Level.WARN; + case Level.INFO_INT: + return LogOutput.Level.INFO; + case Level.TRACE_INT: + return LogOutput.Level.TRACE; + case Level.DEBUG_INT: + default: + return LogOutput.Level.DEBUG; + } + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/LogOutput.java b/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/LogOutput.java new file mode 100644 index 00000000000..b69c405d931 --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/LogOutput.java @@ -0,0 +1,33 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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.batch.bootstrapper; + +/** + * Allow to redirect batch logs to a custom output. By defaults logs are written to System.out + * @since 5.2 + */ +public interface LogOutput { + + void log(String formattedMessage, Level level); + + enum Level { + ERROR, WARN, INFO, DEBUG, TRACE; + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/LoggingConfiguration.java b/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/LoggingConfiguration.java new file mode 100644 index 00000000000..41a741bbd08 --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/LoggingConfiguration.java @@ -0,0 +1,153 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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.batch.bootstrapper; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.Maps; + +import java.util.Map; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +import org.apache.commons.lang.StringUtils; + +/** + * @since 2.14 + */ +public final class LoggingConfiguration { + + public static final String PROPERTY_ROOT_LOGGER_LEVEL = "ROOT_LOGGER_LEVEL"; + public static final String PROPERTY_SQL_LOGGER_LEVEL = "SQL_LOGGER_LEVEL"; + + public static final String PROPERTY_FORMAT = "FORMAT"; + + public static final String LEVEL_ROOT_VERBOSE = "DEBUG"; + public static final String LEVEL_ROOT_DEFAULT = "INFO"; + + @VisibleForTesting + static final String FORMAT_DEFAULT = "%d{HH:mm:ss.SSS} %-5level - %msg%n"; + @VisibleForTesting + static final String FORMAT_MAVEN = "[%level] [%d{HH:mm:ss.SSS}] %msg%n"; + + private Map<String, String> substitutionVariables = Maps.newHashMap(); + private LogOutput logOutput = null; + private boolean verbose; + + public LoggingConfiguration() { + this(null); + } + + public LoggingConfiguration(@Nullable EnvironmentInformation environment) { + setVerbose(false); + if (environment != null && "maven".equalsIgnoreCase(environment.getKey())) { + setFormat(FORMAT_MAVEN); + } else { + setFormat(FORMAT_DEFAULT); + } + } + + public LoggingConfiguration setProperties(Map<String, String> properties) { + setShowSql(properties, null); + setVerbose(properties, null); + return this; + } + + public LoggingConfiguration setProperties(Map<String, String> properties, @Nullable Map<String, String> fallback) { + setShowSql(properties, fallback); + setVerbose(properties, fallback); + return this; + } + + public LoggingConfiguration setLogOutput(@Nullable LogOutput listener) { + this.logOutput = listener; + return this; + } + + public LoggingConfiguration setVerbose(boolean verbose) { + return setRootLevel(verbose ? LEVEL_ROOT_VERBOSE : LEVEL_ROOT_DEFAULT); + } + + public boolean isVerbose() { + return verbose; + } + + public LoggingConfiguration setVerbose(Map<String, String> props, @Nullable Map<String, String> fallback) { + String logLevel = getFallback("sonar.log.level", props, fallback); + String deprecatedProfilingLevel = getFallback("sonar.log.profilingLevel", props, fallback); + verbose = "true".equals(getFallback("sonar.verbose", props, fallback)) || + "DEBUG".equals(logLevel) || "TRACE".equals(logLevel) || + "BASIC".equals(deprecatedProfilingLevel) || "FULL".equals(deprecatedProfilingLevel); + + return setVerbose(verbose); + } + + @CheckForNull + private static String getFallback(String key, Map<String, String> properties, @Nullable Map<String, String> fallback) { + if (properties.containsKey(key)) { + return properties.get(key); + } + + if (fallback != null) { + return fallback.get(key); + } + + return null; + } + + public LoggingConfiguration setRootLevel(String level) { + return addSubstitutionVariable(PROPERTY_ROOT_LOGGER_LEVEL, level); + } + + public LoggingConfiguration setShowSql(boolean showSql) { + return addSubstitutionVariable(PROPERTY_SQL_LOGGER_LEVEL, showSql ? "TRACE" : "WARN"); + } + + public LoggingConfiguration setShowSql(Map<String, String> properties, @Nullable Map<String, String> fallback) { + String logLevel = getFallback("sonar.log.level", properties, fallback); + String deprecatedProfilingLevel = getFallback("sonar.log.profilingLevel", properties, fallback); + boolean sql = "TRACE".equals(logLevel) || "FULL".equals(deprecatedProfilingLevel); + + return setShowSql(sql); + } + + @VisibleForTesting + LoggingConfiguration setFormat(String format) { + return addSubstitutionVariable(PROPERTY_FORMAT, StringUtils.defaultIfBlank(format, FORMAT_DEFAULT)); + } + + public LoggingConfiguration addSubstitutionVariable(String key, String value) { + substitutionVariables.put(key, value); + return this; + } + + @VisibleForTesting + String getSubstitutionVariable(String key) { + return substitutionVariables.get(key); + } + + Map<String, String> getSubstitutionVariables() { + return substitutionVariables; + } + + LogOutput getLogOutput() { + return logOutput; + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/LoggingConfigurator.java b/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/LoggingConfigurator.java new file mode 100644 index 00000000000..f7f45b1c6fe --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/LoggingConfigurator.java @@ -0,0 +1,76 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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.batch.bootstrapper; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.Appender; +import java.io.File; +import org.apache.commons.lang.StringUtils; +import org.slf4j.LoggerFactory; +import org.sonar.core.config.Logback; + +public class LoggingConfigurator { + private static final String CUSTOM_APPENDER_NAME = "custom_stream"; + + private LoggingConfigurator() { + } + + public static void apply(LoggingConfiguration conf, File logbackFile) { + Logback.configure(logbackFile, conf.getSubstitutionVariables()); + + if (conf.getLogOutput() != null) { + setCustomRootAppender(conf); + } + } + + public static void apply(LoggingConfiguration conf) { + apply(conf, "/org/sonar/batch/bootstrapper/logback.xml"); + } + + public static void apply(LoggingConfiguration conf, String classloaderPath) { + Logback.configure(classloaderPath, conf.getSubstitutionVariables()); + + // if not set, keep default behavior (configured to stdout through the file in classpath) + if (conf.getLogOutput() != null) { + setCustomRootAppender(conf); + } + } + + private static void setCustomRootAppender(LoggingConfiguration conf) { + Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); + String level = StringUtils.defaultIfBlank(conf.getSubstitutionVariables().get(LoggingConfiguration.PROPERTY_ROOT_LOGGER_LEVEL), LoggingConfiguration.LEVEL_ROOT_DEFAULT); + + if (logger.getAppender(CUSTOM_APPENDER_NAME) == null) { + logger.detachAndStopAllAppenders(); + logger.addAppender(createAppender(conf.getLogOutput())); + } + logger.setLevel(Level.toLevel(level)); + } + + private static Appender<ILoggingEvent> createAppender(LogOutput target) { + LogCallbackAppender appender = new LogCallbackAppender(target); + appender.setName(CUSTOM_APPENDER_NAME); + appender.start(); + + return appender; + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/package-info.java b/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/package-info.java new file mode 100644 index 00000000000..645b8d7dfe2 --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/package-info.java @@ -0,0 +1,27 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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. + */ +/** + * This package is a part of bootstrap process, so we should take care about backward compatibility. + */ +@ParametersAreNonnullByDefault +package org.sonar.batch.bootstrapper; + +import javax.annotation.ParametersAreNonnullByDefault; + |