- by default Logback is configured by batch, not by bootstrappers - ability to delegate logging to bootstrappers (require a SLF4J implementation)tags/2.14
@@ -29,6 +29,10 @@ import org.sonar.batch.bootstrapper.Reactor; | |||
import java.util.Iterator; | |||
import java.util.Properties; | |||
/** | |||
* @deprecated Replaced by {@link org.sonar.batch.bootstrapper.Batch} since version 2.14. | |||
*/ | |||
@Deprecated | |||
public final class Batch { | |||
private Module bootstrapModule; |
@@ -0,0 +1,151 @@ | |||
/* | |||
* Sonar, open source software quality management tool. | |||
* Copyright (C) 2008-2012 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* Sonar 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. | |||
* | |||
* Sonar 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 Sonar; if not, write to the Free Software | |||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 | |||
*/ | |||
package org.sonar.batch.bootstrapper; | |||
import com.google.common.collect.Lists; | |||
import org.sonar.api.batch.bootstrap.ProjectReactor; | |||
import org.sonar.batch.bootstrap.BootstrapModule; | |||
import org.sonar.batch.bootstrap.Module; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import java.util.Map; | |||
/** | |||
* Entry point for batch bootstrappers. | |||
* | |||
* @since 2.14 | |||
*/ | |||
public final class Batch { | |||
private LoggingConfiguration logging; | |||
private List components; | |||
private ProjectReactor projectReactor; | |||
private Batch(Builder builder) { | |||
components = Lists.newArrayList(); | |||
components.addAll(builder.components); | |||
components.add(builder.environment); | |||
projectReactor = builder.projectReactor; | |||
logging = LoggingConfiguration.create().setProperties((Map) projectReactor.getRoot().getProperties()); | |||
} | |||
/** | |||
* Disable the internal configuration of Logback. In this case the batch bootstrapper must provide its | |||
* own implementation of SLF4J. | |||
*/ | |||
public Batch disableLoggingConfiguration() { | |||
this.logging = null; | |||
return this; | |||
} | |||
public LoggingConfiguration getLoggingConfiguration() { | |||
return logging; | |||
} | |||
public Batch execute() { | |||
configureLogging(); | |||
startBatch(); | |||
return this; | |||
} | |||
private void configureLogging() { | |||
if (logging != null) { | |||
logging.configure(); | |||
} | |||
} | |||
private void startBatch() { | |||
Module bootstrapModule = new BootstrapModule(projectReactor, components.toArray(new Object[components.size()])).init(); | |||
try { | |||
bootstrapModule.start(); | |||
} finally { | |||
try { | |||
bootstrapModule.stop(); | |||
} catch (Exception e) { | |||
// never throw exceptions in a finally block | |||
} | |||
} | |||
} | |||
public static Builder builder() { | |||
return new Builder(); | |||
} | |||
public static final class Builder { | |||
private ProjectReactor projectReactor; | |||
private EnvironmentInformation environment; | |||
private List components = Lists.newArrayList(); | |||
private Builder() { | |||
} | |||
public ProjectReactor getProjectReactor() { | |||
return projectReactor; | |||
} | |||
public Builder setProjectReactor(ProjectReactor projectReactor) { | |||
this.projectReactor = projectReactor; | |||
return this; | |||
} | |||
public EnvironmentInformation getEnvironment() { | |||
return environment; | |||
} | |||
public Builder setEnvironment(EnvironmentInformation env) { | |||
this.environment = env; | |||
return this; | |||
} | |||
public List getComponents() { | |||
return components; | |||
} | |||
public Builder setComponents(List l) { | |||
this.components = l; | |||
return this; | |||
} | |||
public Builder addComponents(Object... components) { | |||
this.components.addAll(Arrays.asList(components)); | |||
return this; | |||
} | |||
public Builder addComponent(Object component) { | |||
this.components.add(component); | |||
return this; | |||
} | |||
public Batch build() { | |||
if (projectReactor == null) { | |||
throw new IllegalArgumentException("ProjectReactor is not set"); | |||
} | |||
if (environment == null) { | |||
throw new IllegalArgumentException("EnvironmentInfo is not set"); | |||
} | |||
if (components == null) { | |||
throw new IllegalArgumentException("Batch components are not set"); | |||
} | |||
return new Batch(this); | |||
} | |||
} | |||
} |
@@ -19,11 +19,11 @@ | |||
*/ | |||
package org.sonar.batch.bootstrapper; | |||
import com.google.common.collect.Maps; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.sonar.core.config.Logback; | |||
import java.io.File; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
/** | |||
@@ -33,17 +33,20 @@ 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_SQL_RESULTS_LOGGER_LEVEL = "SQL_RESULTS_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"; | |||
public static final String LEVEL_SQL_VERBOSE = "DEBUG"; | |||
public static final String LEVEL_SQL_DEFAULT = "WARN"; | |||
public static final String LEVEL_SQL_RESULTS_VERBOSE = "DEBUG"; | |||
public static final String LEVEL_SQL_RESULTS_DEFAULT = "WARN"; | |||
public static final String FORMAT_DEFAULT = "%d{HH:mm:ss.SSS} %-5level - %msg%n"; | |||
public static final String FORMAT_MAVEN = "[%level] [%d{HH:mm:ss.SSS}] %msg%n"; | |||
private Map<String, String> substitutionVariables = new HashMap<String, String>(); | |||
private Map<String, String> substitutionVariables = Maps.newHashMap(); | |||
private LoggingConfiguration() { | |||
setVerbose(false); | |||
@@ -51,12 +54,13 @@ public final class LoggingConfiguration { | |||
setFormat(FORMAT_DEFAULT); | |||
} | |||
public static LoggingConfiguration create() { | |||
static LoggingConfiguration create() { | |||
return new LoggingConfiguration(); | |||
} | |||
public LoggingConfiguration setProperties(Map<String, String> properties) { | |||
setShowSql("true".equals(properties.get("sonar.showSql"))); | |||
setShowSqlResults("true".equals(properties.get("sonar.showSqlResults"))); | |||
setVerbose("true".equals(properties.get("sonar.verbose"))); | |||
return this; | |||
} | |||
@@ -69,6 +73,10 @@ public final class LoggingConfiguration { | |||
return setSqlLevel(showSql ? LEVEL_SQL_VERBOSE : LEVEL_SQL_DEFAULT); | |||
} | |||
public LoggingConfiguration setShowSqlResults(boolean showSqlResults) { | |||
return setSqlResultsLevel(showSqlResults ? LEVEL_SQL_RESULTS_VERBOSE : LEVEL_SQL_RESULTS_DEFAULT); | |||
} | |||
public LoggingConfiguration setRootLevel(String level) { | |||
return addSubstitutionVariable(PROPERTY_ROOT_LOGGER_LEVEL, level); | |||
} | |||
@@ -77,6 +85,10 @@ public final class LoggingConfiguration { | |||
return addSubstitutionVariable(PROPERTY_SQL_LOGGER_LEVEL, level); | |||
} | |||
public LoggingConfiguration setSqlResultsLevel(String level) { | |||
return addSubstitutionVariable(PROPERTY_SQL_RESULTS_LOGGER_LEVEL, level); | |||
} | |||
public LoggingConfiguration setFormat(String format) { | |||
return addSubstitutionVariable(PROPERTY_FORMAT, StringUtils.defaultIfBlank(format, FORMAT_DEFAULT)); | |||
} | |||
@@ -90,17 +102,17 @@ public final class LoggingConfiguration { | |||
return substitutionVariables.get(key); | |||
} | |||
public LoggingConfiguration configure(String classloaderPath) { | |||
LoggingConfiguration configure(String classloaderPath) { | |||
Logback.configure(classloaderPath, substitutionVariables); | |||
return this; | |||
} | |||
public LoggingConfiguration configure(File logbackFile) { | |||
LoggingConfiguration configure(File logbackFile) { | |||
Logback.configure(logbackFile, substitutionVariables); | |||
return this; | |||
} | |||
public LoggingConfiguration configure() { | |||
LoggingConfiguration configure() { | |||
Logback.configure("/org/sonar/batch/bootstrapper/logback.xml", substitutionVariables); | |||
return this; | |||
} |
@@ -42,12 +42,15 @@ | |||
<logger name="org.hibernate.SQL"> | |||
<level value="${SQL_LOGGER_LEVEL:-ERROR}"/> | |||
</logger> | |||
<logger name="java.sql.Statement"> | |||
<logger name="org.apache.ibatis"> | |||
<level value="${SQL_LOGGER_LEVEL:-WARN}"/> | |||
</logger> | |||
<logger name="java.sql.PreparedStatement"> | |||
<logger name="java.sql"> | |||
<level value="${SQL_LOGGER_LEVEL:-WARN}"/> | |||
</logger> | |||
<logger name="java.sql.ResultSet"> | |||
<level value="${SQL_RESULTS_LOGGER_LEVEL:-WARN}"/> | |||
</logger> | |||
<root> | |||
<!-- sonar.verbose --> |
@@ -38,12 +38,15 @@ | |||
<logger name="org.hibernate.SQL"> | |||
<level value="${SQL_LOGGER_LEVEL:-ERROR}"/> | |||
</logger> | |||
<logger name="java.sql.Statement"> | |||
<logger name="org.apache.ibatis"> | |||
<level value="${SQL_LOGGER_LEVEL:-WARN}"/> | |||
</logger> | |||
<logger name="java.sql.PreparedStatement"> | |||
<logger name="java.sql"> | |||
<level value="${SQL_LOGGER_LEVEL:-WARN}"/> | |||
</logger> | |||
<logger name="java.sql.ResultSet"> | |||
<level value="${SQL_RESULTS_LOGGER_LEVEL:-WARN}"/> | |||
</logger> | |||
<root> | |||
<!-- sonar.verbose --> |
@@ -0,0 +1,80 @@ | |||
/* | |||
* Sonar, open source software quality management tool. | |||
* Copyright (C) 2008-2012 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* Sonar 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. | |||
* | |||
* Sonar 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 Sonar; if not, write to the Free Software | |||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 | |||
*/ | |||
package org.sonar.batch.bootstrapper; | |||
import org.junit.Test; | |||
import org.sonar.api.batch.bootstrap.ProjectReactor; | |||
import static org.junit.Assert.assertNotNull; | |||
import static org.junit.Assert.assertNull; | |||
public class BatchTest { | |||
@Test | |||
public void testBuilder() { | |||
Batch batch = newBatch(); | |||
assertNotNull(batch); | |||
} | |||
private Batch newBatch() { | |||
return Batch.builder() | |||
.setEnvironment(new EnvironmentInformation("Gradle", "1.0")) | |||
.setProjectReactor(new ProjectReactor(org.sonar.api.batch.bootstrap.ProjectDefinition.create())) | |||
.addComponent("fake") | |||
.build(); | |||
} | |||
@Test(expected = IllegalArgumentException.class) | |||
public void shouldFailIfNoEnvironment() { | |||
Batch.builder() | |||
.setProjectReactor(new ProjectReactor(org.sonar.api.batch.bootstrap.ProjectDefinition.create())) | |||
.addComponent("fake") | |||
.build(); | |||
} | |||
@Test(expected = IllegalArgumentException.class) | |||
public void shouldFailIfNoProjectReactor() { | |||
Batch.builder() | |||
.setEnvironment(new EnvironmentInformation("Gradle", "1.0")) | |||
.addComponent("fake") | |||
.build(); | |||
} | |||
@Test(expected = IllegalArgumentException.class) | |||
public void shouldFailIfNullComponents() { | |||
Batch.builder() | |||
.setProjectReactor(new ProjectReactor(org.sonar.api.batch.bootstrap.ProjectDefinition.create())) | |||
.setEnvironment(new EnvironmentInformation("Gradle", "1.0")) | |||
.setComponents(null) | |||
.build(); | |||
} | |||
@Test | |||
public void shouldDisableLoggingConfiguration() { | |||
Batch batch = newBatch(); | |||
batch.disableLoggingConfiguration(); | |||
assertNull(batch.getLoggingConfiguration()); | |||
} | |||
@Test | |||
public void loggingConfigurationShouldBeEnabledByDefault() { | |||
assertNotNull(newBatch().getLoggingConfiguration()); | |||
} | |||
} |
@@ -35,11 +35,13 @@ import org.apache.maven.project.MavenProjectBuilder; | |||
import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder; | |||
import org.sonar.api.batch.bootstrap.ProjectDefinition; | |||
import org.sonar.api.batch.bootstrap.ProjectReactor; | |||
import org.sonar.batch.Batch; | |||
import org.sonar.batch.MavenProjectConverter; | |||
import org.sonar.batch.bootstrapper.Batch; | |||
import org.sonar.batch.bootstrapper.EnvironmentInformation; | |||
import org.sonar.batch.bootstrapper.LoggingConfiguration; | |||
import java.util.Map; | |||
/** | |||
* @goal sonar | |||
* @aggregator | |||
@@ -132,41 +134,33 @@ public final class SonarMojo extends AbstractMojo { | |||
*/ | |||
private RuntimeInformation runtimeInformation; | |||
/** | |||
* @parameter expression="${sonar.verbose}" default-value="false" | |||
*/ | |||
private boolean verbose; | |||
/** | |||
* @parameter expression="${sonar.showSql}" default-value="false" | |||
*/ | |||
private boolean showSql; | |||
public void execute() throws MojoExecutionException, MojoFailureException { | |||
configureLogging(); | |||
executeBatch(); | |||
} | |||
private void executeBatch() throws MojoExecutionException { | |||
ProjectDefinition def = MavenProjectConverter.convert(session.getSortedProjects(), project); | |||
ProjectReactor reactor = new ProjectReactor(def); | |||
Batch batch = new Batch(reactor, session, getLog(), lifecycleExecutor, pluginManager, artifactFactory, | |||
localRepository, artifactMetadataSource, artifactCollector, dependencyTreeBuilder, | |||
projectBuilder, getEnvironmentInformation(), Maven2PluginExecutor.class); | |||
Batch batch = Batch.builder() | |||
.setEnvironment(getEnvironmentInformation()) | |||
.setProjectReactor(reactor) | |||
.addComponents( | |||
session, getLog(), lifecycleExecutor, pluginManager, artifactFactory, | |||
localRepository, artifactMetadataSource, artifactCollector, dependencyTreeBuilder, | |||
projectBuilder, Maven2PluginExecutor.class) | |||
.build(); | |||
configureLogging(batch.getLoggingConfiguration()); | |||
batch.execute(); | |||
} | |||
private void configureLogging(LoggingConfiguration logging) { | |||
logging.setProperties((Map) session.getExecutionProperties()); | |||
logging.setFormat(LoggingConfiguration.FORMAT_MAVEN); | |||
if (getLog().isDebugEnabled()) { | |||
logging.setVerbose(true); | |||
} | |||
} | |||
private EnvironmentInformation getEnvironmentInformation() { | |||
String mavenVersion = runtimeInformation.getApplicationVersion().toString(); | |||
return new EnvironmentInformation("Maven", mavenVersion); | |||
} | |||
private void configureLogging() { | |||
LoggingConfiguration.create() | |||
.setVerbose(verbose || getLog().isDebugEnabled()) | |||
.setShowSql(showSql) | |||
.setFormat(LoggingConfiguration.FORMAT_MAVEN) | |||
.configure(); | |||
} | |||
} |
@@ -34,11 +34,13 @@ import org.apache.maven.project.MavenProjectBuilder; | |||
import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder; | |||
import org.sonar.api.batch.bootstrap.ProjectDefinition; | |||
import org.sonar.api.batch.bootstrap.ProjectReactor; | |||
import org.sonar.batch.Batch; | |||
import org.sonar.batch.MavenProjectConverter; | |||
import org.sonar.batch.bootstrapper.Batch; | |||
import org.sonar.batch.bootstrapper.EnvironmentInformation; | |||
import org.sonar.batch.bootstrapper.LoggingConfiguration; | |||
import java.util.Map; | |||
/** | |||
* @goal sonar | |||
* @aggregator | |||
@@ -125,42 +127,33 @@ public final class SonarMojo extends AbstractMojo { | |||
*/ | |||
private RuntimeInformation runtimeInformation; | |||
/** | |||
* @parameter expression="${sonar.verbose}" default-value="false" | |||
*/ | |||
private boolean verbose; | |||
/** | |||
* @parameter expression="${sonar.showSql}" default-value="false" | |||
*/ | |||
private boolean showSql; | |||
public void execute() throws MojoExecutionException, MojoFailureException { | |||
configureLogging(); | |||
executeBatch(); | |||
} | |||
private void executeBatch() throws MojoExecutionException { | |||
ProjectDefinition def = MavenProjectConverter.convert(session.getSortedProjects(), project); | |||
ProjectReactor reactor = new ProjectReactor(def); | |||
Batch batch = new Batch(reactor, session, getLog(), lifecycleExecutor, artifactFactory, | |||
localRepository, artifactMetadataSource, artifactCollector, dependencyTreeBuilder, | |||
projectBuilder, getEnvironmentInformation(), Maven3PluginExecutor.class); | |||
Batch batch = Batch.builder() | |||
.setEnvironment(getEnvironmentInformation()) | |||
.setProjectReactor(reactor) | |||
.addComponents( | |||
session, getLog(), lifecycleExecutor, artifactFactory, localRepository, artifactMetadataSource, artifactCollector, | |||
dependencyTreeBuilder, projectBuilder, Maven3PluginExecutor.class) | |||
.build(); | |||
configureLogging(batch.getLoggingConfiguration()); | |||
batch.execute(); | |||
} | |||
private void configureLogging(LoggingConfiguration logging) { | |||
logging.setProperties((Map) session.getSystemProperties()); | |||
logging.setFormat(LoggingConfiguration.FORMAT_MAVEN); | |||
if (getLog().isDebugEnabled()) { | |||
logging.setVerbose(true); | |||
} | |||
} | |||
private EnvironmentInformation getEnvironmentInformation() { | |||
String mavenVersion = runtimeInformation.getApplicationVersion().toString(); | |||
return new EnvironmentInformation("Maven", mavenVersion); | |||
} | |||
private void configureLogging() { | |||
LoggingConfiguration.create() | |||
.setVerbose(verbose || getLog().isDebugEnabled()) | |||
.setShowSql(showSql) | |||
.setFormat(LoggingConfiguration.FORMAT_MAVEN) | |||
.configure(); | |||
} | |||
} |