From 3a78e2dd377c501a417036ee78509f461a3c6a6b Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Mon, 9 Jan 2017 10:22:36 +0100 Subject: Scanner cleanup * Fail fast when a WS call is made in medium test mode * Rename many Batch* -> Scanner* --- .../java/org/sonar/batch/bootstrapper/Batch.java | 2 +- .../scanner/analysis/DefaultAnalysisMode.java | 8 +- .../scanner/bootstrap/AbstractAnalysisMode.java | 11 +- .../bootstrap/BatchExtensionDictionnary.java | 265 --------------------- .../scanner/bootstrap/BatchPluginInstaller.java | 164 ------------- .../scanner/bootstrap/BatchPluginJarExploder.java | 80 ------- .../scanner/bootstrap/BatchPluginPredicate.java | 98 -------- .../scanner/bootstrap/BatchPluginRepository.java | 109 --------- .../org/sonar/scanner/bootstrap/BatchWsClient.java | 119 --------- .../scanner/bootstrap/BatchWsClientProvider.java | 66 ----- .../sonar/scanner/bootstrap/GlobalContainer.java | 10 +- .../org/sonar/scanner/bootstrap/GlobalMode.java | 6 +- .../sonar/scanner/bootstrap/PluginInstaller.java | 2 +- .../bootstrap/ScannerExtensionDictionnary.java | 265 +++++++++++++++++++++ .../scanner/bootstrap/ScannerPluginInstaller.java | 164 +++++++++++++ .../bootstrap/ScannerPluginJarExploder.java | 80 +++++++ .../scanner/bootstrap/ScannerPluginPredicate.java | 98 ++++++++ .../scanner/bootstrap/ScannerPluginRepository.java | 109 +++++++++ .../sonar/scanner/bootstrap/ScannerWsClient.java | 123 ++++++++++ .../scanner/bootstrap/ScannerWsClientProvider.java | 66 +++++ .../scanner/deprecated/InputFileComponent.java | 60 ----- .../tracking/DefaultServerLineHashesLoader.java | 6 +- .../scanner/mediumtest/FakePluginInstaller.java | 1 - .../sonar/scanner/phases/InitializersExecutor.java | 6 +- .../org/sonar/scanner/phases/PostJobsExecutor.java | 6 +- .../org/sonar/scanner/phases/SensorsExecutor.java | 6 +- .../org/sonar/scanner/platform/DefaultServer.java | 6 +- .../report/AnalysisContextReportPublisher.java | 6 +- .../org/sonar/scanner/report/ReportPublisher.java | 6 +- .../DefaultGlobalRepositoriesLoader.java | 6 +- .../DefaultProjectRepositoriesLoader.java | 6 +- .../repository/DefaultQualityProfileLoader.java | 6 +- .../repository/DefaultServerIssuesLoader.java | 6 +- .../repository/user/UserRepositoryLoader.java | 6 +- .../scanner/rule/DefaultActiveRulesLoader.java | 6 +- .../org/sonar/scanner/rule/DefaultRulesLoader.java | 6 +- .../sonar/scanner/scan/ModuleScanContainer.java | 4 +- 37 files changed, 970 insertions(+), 1024 deletions(-) delete mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchExtensionDictionnary.java delete mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchPluginInstaller.java delete mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchPluginJarExploder.java delete mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchPluginPredicate.java delete mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchPluginRepository.java delete mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchWsClient.java delete mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchWsClientProvider.java create mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerExtensionDictionnary.java create mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginInstaller.java create mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginJarExploder.java create mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginPredicate.java create mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginRepository.java create mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClient.java create mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClientProvider.java delete mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/InputFileComponent.java (limited to 'sonar-scanner-engine/src/main/java/org/sonar') 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 index b526a3e95c3..bfd02386af7 100644 --- 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 @@ -136,7 +136,7 @@ public final class Batch { private void checkStarted() { if (!started) { - throw new IllegalStateException("Batch is not started. Unable to execute task."); + throw new IllegalStateException("Scanner engine is not started. Unable to execute task."); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/analysis/DefaultAnalysisMode.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/analysis/DefaultAnalysisMode.java index f16fda3c995..3fc163d34a5 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/analysis/DefaultAnalysisMode.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/analysis/DefaultAnalysisMode.java @@ -26,7 +26,6 @@ import org.slf4j.LoggerFactory; import org.sonar.api.CoreProperties; import org.sonar.scanner.bootstrap.AbstractAnalysisMode; import org.sonar.scanner.bootstrap.GlobalProperties; -import org.sonar.scanner.mediumtest.FakePluginInstaller; /** * @since 4.0 @@ -36,17 +35,12 @@ public class DefaultAnalysisMode extends AbstractAnalysisMode { private static final Logger LOG = LoggerFactory.getLogger(DefaultAnalysisMode.class); private static final String KEY_SCAN_ALL = "sonar.scanAllFiles"; - private boolean mediumTestMode; private boolean scanAllFiles; public DefaultAnalysisMode(GlobalProperties globalProps, AnalysisProperties props) { init(globalProps.properties(), props.properties()); } - public boolean isMediumTest() { - return mediumTestMode; - } - public boolean scanAllFiles() { return scanAllFiles; } @@ -67,7 +61,7 @@ public class DefaultAnalysisMode extends AbstractAnalysisMode { String mode = getPropertyWithFallback(analysisProps, globalProps, CoreProperties.ANALYSIS_MODE); validate(mode); issues = CoreProperties.ANALYSIS_MODE_ISSUES.equals(mode) || CoreProperties.ANALYSIS_MODE_PREVIEW.equals(mode); - mediumTestMode = "true".equals(getPropertyWithFallback(analysisProps, globalProps, FakePluginInstaller.MEDIUM_TEST_ENABLED)); + mediumTestMode = "true".equals(getPropertyWithFallback(analysisProps, globalProps, MEDIUM_TEST_ENABLED)); String scanAllStr = getPropertyWithFallback(analysisProps, globalProps, KEY_SCAN_ALL); scanAllFiles = !issues || "true".equals(scanAllStr); } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/AbstractAnalysisMode.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/AbstractAnalysisMode.java index 2aa8108f3a2..546d6e88d83 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/AbstractAnalysisMode.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/AbstractAnalysisMode.java @@ -19,18 +19,19 @@ */ package org.sonar.scanner.bootstrap; +import java.util.Arrays; import org.apache.commons.lang.StringUtils; import org.sonar.api.CoreProperties; - -import java.util.Arrays; - import org.sonar.api.batch.AnalysisMode; public abstract class AbstractAnalysisMode implements AnalysisMode { + private static final String[] VALID_MODES = {CoreProperties.ANALYSIS_MODE_PREVIEW, CoreProperties.ANALYSIS_MODE_PUBLISH, CoreProperties.ANALYSIS_MODE_ISSUES}; + public static final String MEDIUM_TEST_ENABLED = "sonar.mediumTest.enabled"; protected boolean preview; protected boolean issues; + protected boolean mediumTestMode; protected AbstractAnalysisMode() { } @@ -50,6 +51,10 @@ public abstract class AbstractAnalysisMode implements AnalysisMode { return !preview && !issues; } + public boolean isMediumTest() { + return mediumTestMode; + } + protected static void validate(String mode) { if (StringUtils.isEmpty(mode)) { return; diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchExtensionDictionnary.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchExtensionDictionnary.java deleted file mode 100644 index 6aac81cf120..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchExtensionDictionnary.java +++ /dev/null @@ -1,265 +0,0 @@ -/* - * 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.scanner.bootstrap; - -import com.google.common.base.Predicates; -import com.google.common.collect.Collections2; -import com.google.common.collect.Lists; -import java.lang.annotation.Annotation; -import java.lang.reflect.Array; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import javax.annotation.Nullable; -import org.apache.commons.lang.ClassUtils; -import org.sonar.api.batch.CheckProject; -import org.sonar.api.batch.DependedUpon; -import org.sonar.api.batch.DependsUpon; -import org.sonar.api.batch.Phase; -import org.sonar.api.batch.postjob.PostJob; -import org.sonar.api.batch.postjob.PostJobContext; -import org.sonar.api.batch.sensor.Sensor; -import org.sonar.api.batch.sensor.SensorContext; -import org.sonar.api.resources.Project; -import org.sonar.api.utils.AnnotationUtils; -import org.sonar.api.utils.dag.DirectAcyclicGraph; -import org.sonar.core.platform.ComponentContainer; -import org.sonar.scanner.postjob.PostJobOptimizer; -import org.sonar.scanner.postjob.PostJobWrapper; -import org.sonar.scanner.sensor.DefaultSensorContext; -import org.sonar.scanner.sensor.SensorOptimizer; -import org.sonar.scanner.sensor.SensorWrapper; - -/** - * @since 2.6 - */ -public class BatchExtensionDictionnary { - - private final ComponentContainer componentContainer; - private final SensorContext sensorContext; - private final SensorOptimizer sensorOptimizer; - private final PostJobContext postJobContext; - private final PostJobOptimizer postJobOptimizer; - - public BatchExtensionDictionnary(ComponentContainer componentContainer, DefaultSensorContext sensorContext, SensorOptimizer sensorOptimizer, PostJobContext postJobContext, - PostJobOptimizer postJobOptimizer) { - this.componentContainer = componentContainer; - this.sensorContext = sensorContext; - this.sensorOptimizer = sensorOptimizer; - this.postJobContext = postJobContext; - this.postJobOptimizer = postJobOptimizer; - } - - public Collection select(Class type, @Nullable Project project, boolean sort, @Nullable ExtensionMatcher matcher) { - List result = getFilteredExtensions(type, project, matcher); - if (sort) { - return sort(result); - } - return result; - } - - private static Phase.Name evaluatePhase(Object extension) { - Object extensionToEvaluate; - if (extension instanceof SensorWrapper) { - extensionToEvaluate = ((SensorWrapper) extension).wrappedSensor(); - } else { - extensionToEvaluate = extension; - } - Phase phaseAnnotation = AnnotationUtils.getAnnotation(extensionToEvaluate, Phase.class); - if (phaseAnnotation != null) { - return phaseAnnotation.name(); - } - return Phase.Name.DEFAULT; - } - - private List getFilteredExtensions(Class type, @Nullable Project project, @Nullable ExtensionMatcher matcher) { - List result = Lists.newArrayList(); - for (Object extension : getExtensions(type)) { - if (org.sonar.api.batch.Sensor.class.equals(type) && extension instanceof Sensor) { - extension = new SensorWrapper((Sensor) extension, sensorContext, sensorOptimizer); - } - if (shouldKeep(type, extension, project, matcher)) { - result.add((T) extension); - } - } - if (org.sonar.api.batch.Sensor.class.equals(type)) { - // Retrieve new Sensors and wrap then in SensorWrapper - for (Object extension : getExtensions(Sensor.class)) { - extension = new SensorWrapper((Sensor) extension, sensorContext, sensorOptimizer); - if (shouldKeep(type, extension, project, matcher)) { - result.add((T) extension); - } - } - } - if (org.sonar.api.batch.PostJob.class.equals(type)) { - // Retrieve new PostJob and wrap then in PostJobWrapper - for (Object extension : getExtensions(PostJob.class)) { - extension = new PostJobWrapper((PostJob) extension, postJobContext, postJobOptimizer); - if (shouldKeep(type, extension, project, matcher)) { - result.add((T) extension); - } - } - } - return result; - } - - protected List getExtensions(Class type) { - List extensions = Lists.newArrayList(); - completeBatchExtensions(componentContainer, extensions, type); - return extensions; - } - - private static void completeBatchExtensions(ComponentContainer container, List extensions, Class type) { - extensions.addAll(container.getComponentsByType(type)); - ComponentContainer parentContainer = container.getParent(); - if (parentContainer != null) { - completeBatchExtensions(parentContainer, extensions, type); - } - } - - public Collection sort(Collection extensions) { - DirectAcyclicGraph dag = new DirectAcyclicGraph(); - - for (T extension : extensions) { - dag.add(extension); - for (Object dependency : getDependencies(extension)) { - dag.add(extension, dependency); - } - for (Object generates : getDependents(extension)) { - dag.add(generates, extension); - } - completePhaseDependencies(dag, extension); - } - List sortedList = dag.sort(); - - return Collections2.filter(sortedList, Predicates.in(extensions)); - } - - /** - * Extension dependencies - */ - private List getDependencies(T extension) { - List result = new ArrayList<>(); - result.addAll(evaluateAnnotatedClasses(extension, DependsUpon.class)); - return result; - } - - /** - * Objects that depend upon this extension. - */ - public List getDependents(T extension) { - List result = new ArrayList<>(); - result.addAll(evaluateAnnotatedClasses(extension, DependedUpon.class)); - return result; - } - - private static void completePhaseDependencies(DirectAcyclicGraph dag, Object extension) { - Phase.Name phase = evaluatePhase(extension); - dag.add(extension, phase); - for (Phase.Name name : Phase.Name.values()) { - if (phase.compareTo(name) < 0) { - dag.add(name, extension); - } else if (phase.compareTo(name) > 0) { - dag.add(extension, name); - } - } - } - - protected List evaluateAnnotatedClasses(Object extension, Class annotation) { - List results = Lists.newArrayList(); - Class aClass = extension.getClass(); - while (aClass != null) { - evaluateClass(aClass, annotation, results); - - for (Method method : aClass.getDeclaredMethods()) { - if (method.getAnnotation(annotation) != null) { - checkAnnotatedMethod(method); - evaluateMethod(extension, method, results); - } - } - aClass = aClass.getSuperclass(); - } - - return results; - } - - private static void evaluateClass(Class extensionClass, Class annotationClass, List results) { - Annotation annotation = extensionClass.getAnnotation(annotationClass); - if (annotation != null) { - if (annotation.annotationType().isAssignableFrom(DependsUpon.class)) { - results.addAll(Arrays.asList(((DependsUpon) annotation).value())); - - } else if (annotation.annotationType().isAssignableFrom(DependedUpon.class)) { - results.addAll(Arrays.asList(((DependedUpon) annotation).value())); - } - } - - Class[] interfaces = extensionClass.getInterfaces(); - for (Class anInterface : interfaces) { - evaluateClass(anInterface, annotationClass, results); - } - } - - private void evaluateMethod(Object extension, Method method, List results) { - try { - Object result = method.invoke(extension); - if (result != null) { - if (result instanceof Class) { - results.addAll(componentContainer.getComponentsByType((Class) result)); - - } else if (result instanceof Collection) { - results.addAll((Collection) result); - - } else if (result.getClass().isArray()) { - for (int i = 0; i < Array.getLength(result); i++) { - results.add(Array.get(result, i)); - } - - } else { - results.add(result); - } - } - } catch (Exception e) { - throw new IllegalStateException("Can not invoke method " + method, e); - } - } - - private static void checkAnnotatedMethod(Method method) { - if (!Modifier.isPublic(method.getModifiers())) { - throw new IllegalStateException("Annotated method must be public:" + method); - } - if (method.getParameterTypes().length > 0) { - throw new IllegalStateException("Annotated method must not have parameters:" + method); - } - } - - private static boolean shouldKeep(Class type, Object extension, @Nullable Project project, @Nullable ExtensionMatcher matcher) { - boolean keep = (ClassUtils.isAssignable(extension.getClass(), type) - || (org.sonar.api.batch.Sensor.class.equals(type) && ClassUtils.isAssignable(extension.getClass(), Sensor.class))) - && (matcher == null || matcher.accept(extension)); - if (keep && project != null && ClassUtils.isAssignable(extension.getClass(), CheckProject.class)) { - keep = ((CheckProject) extension).shouldExecuteOnProject(project); - } - return keep; - } -} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchPluginInstaller.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchPluginInstaller.java deleted file mode 100644 index 25ce8cf68a4..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchPluginInstaller.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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.scanner.bootstrap; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.Lists; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.CharUtils; -import org.apache.commons.lang.StringUtils; -import org.sonar.api.Plugin; -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.Loggers; -import org.sonar.api.utils.log.Profiler; -import org.sonar.core.platform.PluginInfo; -import org.sonar.core.platform.RemotePlugin; -import org.sonar.core.platform.RemotePluginFile; -import org.sonar.home.cache.FileCache; -import org.sonarqube.ws.client.GetRequest; -import org.sonarqube.ws.client.WsResponse; - -import static java.lang.String.format; - -/** - * Downloads the plugins installed on server and stores them in a local user cache - * (see {@link FileCacheProvider}). - */ -public class BatchPluginInstaller implements PluginInstaller { - - private static final Logger LOG = Loggers.get(BatchPluginInstaller.class); - private static final String PLUGINS_INDEX_URL = "/deploy/plugins/index.txt"; - - private final FileCache fileCache; - private final BatchPluginPredicate pluginPredicate; - private final BatchWsClient wsClient; - - public BatchPluginInstaller(BatchWsClient wsClient, FileCache fileCache, BatchPluginPredicate pluginPredicate) { - this.fileCache = fileCache; - this.pluginPredicate = pluginPredicate; - this.wsClient = wsClient; - } - - @Override - public Map installRemotes() { - return loadPlugins(listRemotePlugins()); - } - - private Map loadPlugins(List remotePlugins) { - Map infosByKey = new HashMap<>(); - - Profiler profiler = Profiler.create(LOG).startDebug("Load plugins"); - - for (RemotePlugin remotePlugin : remotePlugins) { - if (pluginPredicate.apply(remotePlugin.getKey())) { - File jarFile = download(remotePlugin); - PluginInfo info = PluginInfo.create(jarFile); - infosByKey.put(info.getKey(), info); - } - } - - profiler.stopDebug(); - return infosByKey; - } - - /** - * Returns empty on purpose. This method is used only by tests. - * @see org.sonar.scanner.mediumtest.BatchMediumTester - */ - @Override - public Map installLocals() { - return Collections.emptyMap(); - } - - @VisibleForTesting - File download(final RemotePlugin remote) { - try { - final RemotePluginFile file = remote.file(); - return fileCache.get(file.getFilename(), file.getHash(), new FileDownloader(remote.getKey())); - } catch (Exception e) { - throw new IllegalStateException("Fail to download plugin: " + remote.getKey(), e); - } - } - - /** - * Gets information about the plugins installed on server (filename, checksum) - */ - @VisibleForTesting - List listRemotePlugins() { - try { - String pluginIndex = loadPluginIndex(); - String[] rows = StringUtils.split(pluginIndex, CharUtils.LF); - List result = Lists.newArrayList(); - for (String row : rows) { - result.add(RemotePlugin.unmarshal(row)); - } - return result; - - } catch (Exception e) { - throw new IllegalStateException("Fail to load plugin index: " + PLUGINS_INDEX_URL, e); - } - } - - private String loadPluginIndex() { - Profiler profiler = Profiler.create(LOG).startInfo("Load plugins index"); - GetRequest getRequest = new GetRequest(PLUGINS_INDEX_URL); - String str; - try (Reader reader = wsClient.call(getRequest).contentReader()) { - str = IOUtils.toString(reader); - } catch(IOException e) { - throw new IllegalStateException(e); - } - - profiler.stopInfo(); - return str; - } - - private class FileDownloader implements FileCache.Downloader { - private String key; - - FileDownloader(String key) { - this.key = key; - } - - @Override - public void download(String filename, File toFile) throws IOException { - String url = format("/deploy/plugins/%s/%s", key, filename); - if (LOG.isDebugEnabled()) { - LOG.debug("Download plugin {} to {}", filename, toFile); - } else { - LOG.info("Download {}", filename); - } - - WsResponse response = wsClient.call(new GetRequest(url)); - try (InputStream stream = response.contentStream()) { - FileUtils.copyInputStreamToFile(stream, toFile); - } - } - } -} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchPluginJarExploder.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchPluginJarExploder.java deleted file mode 100644 index f4eea73f7db..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchPluginJarExploder.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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.scanner.bootstrap; - -import org.apache.commons.io.FileUtils; -import org.sonar.api.batch.ScannerSide; -import org.sonar.api.utils.ZipUtils; -import org.sonar.core.platform.ExplodedPlugin; -import org.sonar.core.platform.PluginJarExploder; -import org.sonar.core.platform.PluginInfo; -import org.sonar.home.cache.FileCache; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; - -import static org.sonar.core.util.FileUtils.deleteQuietly; - -@ScannerSide -public class BatchPluginJarExploder extends PluginJarExploder { - - private final FileCache fileCache; - - public BatchPluginJarExploder(FileCache fileCache) { - this.fileCache = fileCache; - } - - @Override - public ExplodedPlugin explode(PluginInfo info) { - try { - File dir = unzipFile(info.getNonNullJarFile()); - return explodeFromUnzippedDir(info.getKey(), info.getNonNullJarFile(), dir); - } catch (Exception e) { - throw new IllegalStateException(String.format("Fail to open plugin [%s]: %s", info.getKey(), info.getNonNullJarFile().getAbsolutePath()), e); - } - } - - private File unzipFile(File cachedFile) throws IOException { - String filename = cachedFile.getName(); - File destDir = new File(cachedFile.getParentFile(), filename + "_unzip"); - File lockFile = new File(cachedFile.getParentFile(), filename + "_unzip.lock"); - if (!destDir.exists()) { - FileOutputStream out = new FileOutputStream(lockFile); - try { - java.nio.channels.FileLock lock = out.getChannel().lock(); - try { - // Recheck in case of concurrent processes - if (!destDir.exists()) { - File tempDir = fileCache.createTempDir(); - ZipUtils.unzip(cachedFile, tempDir, newLibFilter()); - FileUtils.moveDirectory(tempDir, destDir); - } - } finally { - lock.release(); - } - } finally { - out.close(); - deleteQuietly(lockFile); - } - } - return destDir; - } -} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchPluginPredicate.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchPluginPredicate.java deleted file mode 100644 index f86adc3dd1d..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchPluginPredicate.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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.scanner.bootstrap; - -import com.google.common.base.Joiner; -import com.google.common.base.Predicate; -import com.google.common.base.Splitter; -import com.google.common.collect.Lists; - -import java.util.List; -import java.util.Set; - -import javax.annotation.Nonnull; - -import org.apache.commons.lang.StringUtils; -import org.sonar.api.CoreProperties; -import org.sonar.api.batch.ScannerSide; -import org.sonar.api.config.Settings; -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.Loggers; -import static com.google.common.collect.Sets.newHashSet; - -/** - * Filters the plugins to be enabled during analysis - */ -@ScannerSide -public class BatchPluginPredicate implements Predicate { - - private static final Logger LOG = Loggers.get(BatchPluginPredicate.class); - - private static final String BUILDBREAKER_PLUGIN_KEY = "buildbreaker"; - private static final Joiner COMMA_JOINER = Joiner.on(", "); - - private final Set whites = newHashSet(); - private final Set blacks = newHashSet(); - private final GlobalMode mode; - - public BatchPluginPredicate(Settings settings, GlobalMode mode) { - this.mode = mode; - if (mode.isPreview() || mode.isIssues()) { - // These default values are not supported by Settings because the class CorePlugin - // is not loaded yet. - whites.addAll(propertyValues(settings, - CoreProperties.PREVIEW_INCLUDE_PLUGINS, CoreProperties.PREVIEW_INCLUDE_PLUGINS_DEFAULT_VALUE)); - blacks.addAll(propertyValues(settings, - CoreProperties.PREVIEW_EXCLUDE_PLUGINS, CoreProperties.PREVIEW_EXCLUDE_PLUGINS_DEFAULT_VALUE)); - } - if (!whites.isEmpty()) { - LOG.info("Include plugins: " + COMMA_JOINER.join(whites)); - } - if (!blacks.isEmpty()) { - LOG.info("Exclude plugins: " + COMMA_JOINER.join(blacks)); - } - } - - @Override - public boolean apply(@Nonnull String pluginKey) { - if (BUILDBREAKER_PLUGIN_KEY.equals(pluginKey) && mode.isPreview()) { - LOG.info("Build Breaker plugin is no more supported in preview mode"); - return false; - } - - if (whites.isEmpty()) { - return blacks.isEmpty() || !blacks.contains(pluginKey); - } - return whites.contains(pluginKey); - } - - Set getWhites() { - return whites; - } - - Set getBlacks() { - return blacks; - } - - private static List propertyValues(Settings settings, String key, String defaultValue) { - String s = StringUtils.defaultIfEmpty(settings.getString(key), defaultValue); - return Lists.newArrayList(Splitter.on(",").trimResults().omitEmptyStrings().split(s)); - } -} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchPluginRepository.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchPluginRepository.java deleted file mode 100644 index 0bad3324f52..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchPluginRepository.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * 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.scanner.bootstrap; - -import com.google.common.base.Preconditions; -import com.google.common.collect.Maps; -import java.util.Collection; -import java.util.Map; -import org.picocontainer.Startable; -import org.sonar.api.Plugin; -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.Loggers; -import org.sonar.core.platform.PluginInfo; -import org.sonar.core.platform.PluginLoader; -import org.sonar.core.platform.PluginRepository; - -/** - * Orchestrates the installation and loading of plugins - */ -public class BatchPluginRepository implements PluginRepository, Startable { - private static final Logger LOG = Loggers.get(BatchPluginRepository.class); - - private final PluginInstaller installer; - private final PluginLoader loader; - - private Map pluginInstancesByKeys; - private Map infosByKeys; - - public BatchPluginRepository(PluginInstaller installer, PluginLoader loader) { - this.installer = installer; - this.loader = loader; - } - - @Override - public void start() { - infosByKeys = Maps.newHashMap(installer.installRemotes()); - pluginInstancesByKeys = Maps.newHashMap(loader.load(infosByKeys)); - - // this part is only used by tests - for (Map.Entry entry : installer.installLocals().entrySet()) { - String pluginKey = entry.getKey(); - infosByKeys.put(pluginKey, new PluginInfo(pluginKey)); - pluginInstancesByKeys.put(pluginKey, entry.getValue()); - } - - logPlugins(); - } - - private void logPlugins() { - if (infosByKeys.isEmpty()) { - LOG.debug("No plugins loaded"); - } else { - LOG.debug("Plugins:"); - for (PluginInfo p : infosByKeys.values()) { - LOG.debug(" * {} {} ({})", p.getName(), p.getVersion(), p.getKey()); - } - } - } - - @Override - public void stop() { - // close plugin classloaders - loader.unload(pluginInstancesByKeys.values()); - - pluginInstancesByKeys.clear(); - infosByKeys.clear(); - } - - @Override - public Collection getPluginInfos() { - return infosByKeys.values(); - } - - @Override - public PluginInfo getPluginInfo(String key) { - PluginInfo info = infosByKeys.get(key); - Preconditions.checkState(info != null, "Plugin [%s] does not exist", key); - return info; - } - - @Override - public Plugin getPluginInstance(String key) { - Plugin instance = pluginInstancesByKeys.get(key); - Preconditions.checkState(instance != null, "Plugin [%s] does not exist", key); - return instance; - } - - @Override - public boolean hasPlugin(String key) { - return infosByKeys.containsKey(key); - } -} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchWsClient.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchWsClient.java deleted file mode 100644 index 98269c46a67..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchWsClient.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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.scanner.bootstrap; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Joiner; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import java.util.ArrayList; -import java.util.List; -import org.sonar.api.CoreProperties; -import org.sonar.api.utils.MessageException; -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.Loggers; -import org.sonar.api.utils.log.Profiler; -import org.sonarqube.ws.client.HttpException; -import org.sonarqube.ws.client.WsClient; -import org.sonarqube.ws.client.WsConnector; -import org.sonarqube.ws.client.WsRequest; -import org.sonarqube.ws.client.WsResponse; - -import static java.lang.String.format; -import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; -import static java.net.HttpURLConnection.HTTP_FORBIDDEN; -import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; - -public class BatchWsClient { - - private static final Logger LOG = Loggers.get(BatchWsClient.class); - - private final WsClient target; - private final boolean hasCredentials; - - public BatchWsClient(WsClient target, boolean hasCredentials) { - this.target = target; - this.hasCredentials = hasCredentials; - } - - /** - * If an exception is not thrown, the response needs to be closed by either calling close() directly, or closing the - * body content's stream/reader. - * @throws IllegalStateException if the request could not be executed due to - * a connectivity problem or timeout. Because networks can - * fail during an exchange, it is possible that the remote server - * accepted the request before the failure - * @throws HttpException if the response code is not in range [200..300) - */ - public WsResponse call(WsRequest request) { - Profiler profiler = Profiler.createIfDebug(LOG).start(); - WsResponse response = target.wsConnector().call(request); - profiler.stopDebug(format("%s %d %s", request.getMethod(), response.code(), response.requestUrl())); - failIfUnauthorized(response); - return response; - } - - public String baseUrl() { - return target.wsConnector().baseUrl(); - } - - @VisibleForTesting - WsConnector wsConnector() { - return target.wsConnector(); - } - - private void failIfUnauthorized(WsResponse response) { - int code = response.code(); - if (code == HTTP_UNAUTHORIZED) { - response.close(); - if (hasCredentials) { - // credentials are not valid - throw MessageException.of(format("Not authorized. Please check the properties %s and %s.", - CoreProperties.LOGIN, CoreProperties.PASSWORD)); - } - // not authenticated - see https://jira.sonarsource.com/browse/SONAR-4048 - throw MessageException.of(format("Not authorized. Analyzing this project requires to be authenticated. " + - "Please provide the values of the properties %s and %s.", CoreProperties.LOGIN, CoreProperties.PASSWORD)); - - } - if (code == HTTP_FORBIDDEN || code == HTTP_BAD_REQUEST) { - // SONAR-4397 Details are in response content - throw MessageException.of(tryParseAsJsonError(response.content())); - } - response.failIfNotSuccessful(); - } - - private static String tryParseAsJsonError(String responseContent) { - try { - JsonParser parser = new JsonParser(); - JsonObject obj = parser.parse(responseContent).getAsJsonObject(); - JsonArray errors = obj.getAsJsonArray("errors"); - List errorMessages = new ArrayList<>(); - for (JsonElement e : errors) { - errorMessages.add(e.getAsJsonObject().get("msg").getAsString()); - } - return Joiner.on(", ").join(errorMessages); - } catch (Exception e) { - return responseContent; - } - } -} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchWsClientProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchWsClientProvider.java deleted file mode 100644 index c40c1ddb761..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchWsClientProvider.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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.scanner.bootstrap; - -import org.picocontainer.injectors.ProviderAdapter; -import org.sonar.api.CoreProperties; -import org.sonar.api.batch.ScannerSide; -import org.sonar.batch.bootstrapper.EnvironmentInformation; -import org.sonarqube.ws.client.HttpConnector; -import org.sonarqube.ws.client.WsClientFactories; - -import static java.lang.Integer.parseInt; -import static java.lang.String.valueOf; -import static org.apache.commons.lang.StringUtils.defaultIfBlank; - -@ScannerSide -public class BatchWsClientProvider extends ProviderAdapter { - - static final int CONNECT_TIMEOUT_MS = 5_000; - static final String READ_TIMEOUT_SEC_PROPERTY = "sonar.ws.timeout"; - static final int DEFAULT_READ_TIMEOUT_SEC = 60; - - private BatchWsClient wsClient; - - public synchronized BatchWsClient provide(final GlobalProperties settings, final EnvironmentInformation env) { - if (wsClient == null) { - String url = defaultIfBlank(settings.property("sonar.host.url"), CoreProperties.SERVER_BASE_URL_DEFAULT_VALUE); - HttpConnector.Builder connectorBuilder = HttpConnector.newBuilder(); - - String timeoutSec = defaultIfBlank(settings.property(READ_TIMEOUT_SEC_PROPERTY), valueOf(DEFAULT_READ_TIMEOUT_SEC)); - String login = defaultIfBlank(settings.property(CoreProperties.LOGIN), null); - connectorBuilder - .readTimeoutMilliseconds(parseInt(timeoutSec) * 1_000) - .connectTimeoutMilliseconds(CONNECT_TIMEOUT_MS) - .userAgent(env.toString()) - .url(url) - .credentials(login, settings.property(CoreProperties.PASSWORD)); - - // OkHttp detect 'http.proxyHost' java property, but credentials should be filled - final String proxyUser = System.getProperty("http.proxyUser", ""); - if (!System.getProperty("http.proxyHost", "").isEmpty() && !proxyUser.isEmpty()) { - connectorBuilder.proxyCredentials(proxyUser, System.getProperty("http.proxyPassword")); - } - - wsClient = new BatchWsClient(WsClientFactories.getDefault().newClient(connectorBuilder.build()), login != null); - } - return wsClient; - } -} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalContainer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalContainer.java index c4532d72ea9..19e2e4702fa 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalContainer.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalContainer.java @@ -73,18 +73,18 @@ public class GlobalContainer extends ComponentContainer { Version apiVersion = ApiVersion.load(System2.INSTANCE); add( // plugins - BatchPluginRepository.class, + ScannerPluginRepository.class, PluginLoader.class, PluginClassloaderFactory.class, - BatchPluginJarExploder.class, - BatchPluginPredicate.class, + ScannerPluginJarExploder.class, + ScannerPluginPredicate.class, ExtensionInstaller.class, new SonarQubeVersion(apiVersion), SonarRuntimeImpl.forSonarQube(apiVersion, SonarQubeSide.SCANNER), StoragesManager.class, GlobalSettings.class, - new BatchWsClientProvider(), + new ScannerWsClientProvider(), DefaultServer.class, new GlobalTempFolderProvider(), DefaultHttpDownloader.class, @@ -93,7 +93,7 @@ public class GlobalContainer extends ComponentContainer { System2.INSTANCE, new GlobalRepositoriesProvider(), UuidFactoryImpl.INSTANCE); - addIfMissing(BatchPluginInstaller.class, PluginInstaller.class); + addIfMissing(ScannerPluginInstaller.class, PluginInstaller.class); addIfMissing(DefaultGlobalRepositoriesLoader.class, GlobalRepositoriesLoader.class); } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalMode.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalMode.java index 29b6b805616..2e696df126b 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalMode.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalMode.java @@ -30,7 +30,7 @@ public class GlobalMode extends AbstractAnalysisMode { String mode = props.property(CoreProperties.ANALYSIS_MODE); validate(mode); issues = CoreProperties.ANALYSIS_MODE_ISSUES.equals(mode) || CoreProperties.ANALYSIS_MODE_PREVIEW.equals(mode); - + mediumTestMode = "true".equals(props.property(MEDIUM_TEST_ENABLED)); if (preview) { LOG.debug("Preview global mode"); } else if (issues) { @@ -38,5 +38,9 @@ public class GlobalMode extends AbstractAnalysisMode { } else { LOG.debug("Publish global mode"); } + if (mediumTestMode) { + LOG.info("Medium test mode"); + } } + } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PluginInstaller.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PluginInstaller.java index a839986ce7b..8334f61bfdd 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PluginInstaller.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PluginInstaller.java @@ -36,7 +36,7 @@ public interface PluginInstaller { /** * Used only by tests. - * @see org.sonar.scanner.mediumtest.BatchMediumTester + * @see org.sonar.scanner.mediumtest.ScannerMediumTester */ Map installLocals(); } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerExtensionDictionnary.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerExtensionDictionnary.java new file mode 100644 index 00000000000..1ffe0400337 --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerExtensionDictionnary.java @@ -0,0 +1,265 @@ +/* + * 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.scanner.bootstrap; + +import com.google.common.base.Predicates; +import com.google.common.collect.Collections2; +import com.google.common.collect.Lists; +import java.lang.annotation.Annotation; +import java.lang.reflect.Array; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import javax.annotation.Nullable; +import org.apache.commons.lang.ClassUtils; +import org.sonar.api.batch.CheckProject; +import org.sonar.api.batch.DependedUpon; +import org.sonar.api.batch.DependsUpon; +import org.sonar.api.batch.Phase; +import org.sonar.api.batch.postjob.PostJob; +import org.sonar.api.batch.postjob.PostJobContext; +import org.sonar.api.batch.sensor.Sensor; +import org.sonar.api.batch.sensor.SensorContext; +import org.sonar.api.resources.Project; +import org.sonar.api.utils.AnnotationUtils; +import org.sonar.api.utils.dag.DirectAcyclicGraph; +import org.sonar.core.platform.ComponentContainer; +import org.sonar.scanner.postjob.PostJobOptimizer; +import org.sonar.scanner.postjob.PostJobWrapper; +import org.sonar.scanner.sensor.DefaultSensorContext; +import org.sonar.scanner.sensor.SensorOptimizer; +import org.sonar.scanner.sensor.SensorWrapper; + +/** + * @since 2.6 + */ +public class ScannerExtensionDictionnary { + + private final ComponentContainer componentContainer; + private final SensorContext sensorContext; + private final SensorOptimizer sensorOptimizer; + private final PostJobContext postJobContext; + private final PostJobOptimizer postJobOptimizer; + + public ScannerExtensionDictionnary(ComponentContainer componentContainer, DefaultSensorContext sensorContext, SensorOptimizer sensorOptimizer, PostJobContext postJobContext, + PostJobOptimizer postJobOptimizer) { + this.componentContainer = componentContainer; + this.sensorContext = sensorContext; + this.sensorOptimizer = sensorOptimizer; + this.postJobContext = postJobContext; + this.postJobOptimizer = postJobOptimizer; + } + + public Collection select(Class type, @Nullable Project project, boolean sort, @Nullable ExtensionMatcher matcher) { + List result = getFilteredExtensions(type, project, matcher); + if (sort) { + return sort(result); + } + return result; + } + + private static Phase.Name evaluatePhase(Object extension) { + Object extensionToEvaluate; + if (extension instanceof SensorWrapper) { + extensionToEvaluate = ((SensorWrapper) extension).wrappedSensor(); + } else { + extensionToEvaluate = extension; + } + Phase phaseAnnotation = AnnotationUtils.getAnnotation(extensionToEvaluate, Phase.class); + if (phaseAnnotation != null) { + return phaseAnnotation.name(); + } + return Phase.Name.DEFAULT; + } + + private List getFilteredExtensions(Class type, @Nullable Project project, @Nullable ExtensionMatcher matcher) { + List result = Lists.newArrayList(); + for (Object extension : getExtensions(type)) { + if (org.sonar.api.batch.Sensor.class.equals(type) && extension instanceof Sensor) { + extension = new SensorWrapper((Sensor) extension, sensorContext, sensorOptimizer); + } + if (shouldKeep(type, extension, project, matcher)) { + result.add((T) extension); + } + } + if (org.sonar.api.batch.Sensor.class.equals(type)) { + // Retrieve new Sensors and wrap then in SensorWrapper + for (Object extension : getExtensions(Sensor.class)) { + extension = new SensorWrapper((Sensor) extension, sensorContext, sensorOptimizer); + if (shouldKeep(type, extension, project, matcher)) { + result.add((T) extension); + } + } + } + if (org.sonar.api.batch.PostJob.class.equals(type)) { + // Retrieve new PostJob and wrap then in PostJobWrapper + for (Object extension : getExtensions(PostJob.class)) { + extension = new PostJobWrapper((PostJob) extension, postJobContext, postJobOptimizer); + if (shouldKeep(type, extension, project, matcher)) { + result.add((T) extension); + } + } + } + return result; + } + + protected List getExtensions(Class type) { + List extensions = Lists.newArrayList(); + completeBatchExtensions(componentContainer, extensions, type); + return extensions; + } + + private static void completeBatchExtensions(ComponentContainer container, List extensions, Class type) { + extensions.addAll(container.getComponentsByType(type)); + ComponentContainer parentContainer = container.getParent(); + if (parentContainer != null) { + completeBatchExtensions(parentContainer, extensions, type); + } + } + + public Collection sort(Collection extensions) { + DirectAcyclicGraph dag = new DirectAcyclicGraph(); + + for (T extension : extensions) { + dag.add(extension); + for (Object dependency : getDependencies(extension)) { + dag.add(extension, dependency); + } + for (Object generates : getDependents(extension)) { + dag.add(generates, extension); + } + completePhaseDependencies(dag, extension); + } + List sortedList = dag.sort(); + + return Collections2.filter(sortedList, Predicates.in(extensions)); + } + + /** + * Extension dependencies + */ + private List getDependencies(T extension) { + List result = new ArrayList<>(); + result.addAll(evaluateAnnotatedClasses(extension, DependsUpon.class)); + return result; + } + + /** + * Objects that depend upon this extension. + */ + public List getDependents(T extension) { + List result = new ArrayList<>(); + result.addAll(evaluateAnnotatedClasses(extension, DependedUpon.class)); + return result; + } + + private static void completePhaseDependencies(DirectAcyclicGraph dag, Object extension) { + Phase.Name phase = evaluatePhase(extension); + dag.add(extension, phase); + for (Phase.Name name : Phase.Name.values()) { + if (phase.compareTo(name) < 0) { + dag.add(name, extension); + } else if (phase.compareTo(name) > 0) { + dag.add(extension, name); + } + } + } + + protected List evaluateAnnotatedClasses(Object extension, Class annotation) { + List results = Lists.newArrayList(); + Class aClass = extension.getClass(); + while (aClass != null) { + evaluateClass(aClass, annotation, results); + + for (Method method : aClass.getDeclaredMethods()) { + if (method.getAnnotation(annotation) != null) { + checkAnnotatedMethod(method); + evaluateMethod(extension, method, results); + } + } + aClass = aClass.getSuperclass(); + } + + return results; + } + + private static void evaluateClass(Class extensionClass, Class annotationClass, List results) { + Annotation annotation = extensionClass.getAnnotation(annotationClass); + if (annotation != null) { + if (annotation.annotationType().isAssignableFrom(DependsUpon.class)) { + results.addAll(Arrays.asList(((DependsUpon) annotation).value())); + + } else if (annotation.annotationType().isAssignableFrom(DependedUpon.class)) { + results.addAll(Arrays.asList(((DependedUpon) annotation).value())); + } + } + + Class[] interfaces = extensionClass.getInterfaces(); + for (Class anInterface : interfaces) { + evaluateClass(anInterface, annotationClass, results); + } + } + + private void evaluateMethod(Object extension, Method method, List results) { + try { + Object result = method.invoke(extension); + if (result != null) { + if (result instanceof Class) { + results.addAll(componentContainer.getComponentsByType((Class) result)); + + } else if (result instanceof Collection) { + results.addAll((Collection) result); + + } else if (result.getClass().isArray()) { + for (int i = 0; i < Array.getLength(result); i++) { + results.add(Array.get(result, i)); + } + + } else { + results.add(result); + } + } + } catch (Exception e) { + throw new IllegalStateException("Can not invoke method " + method, e); + } + } + + private static void checkAnnotatedMethod(Method method) { + if (!Modifier.isPublic(method.getModifiers())) { + throw new IllegalStateException("Annotated method must be public:" + method); + } + if (method.getParameterTypes().length > 0) { + throw new IllegalStateException("Annotated method must not have parameters:" + method); + } + } + + private static boolean shouldKeep(Class type, Object extension, @Nullable Project project, @Nullable ExtensionMatcher matcher) { + boolean keep = (ClassUtils.isAssignable(extension.getClass(), type) + || (org.sonar.api.batch.Sensor.class.equals(type) && ClassUtils.isAssignable(extension.getClass(), Sensor.class))) + && (matcher == null || matcher.accept(extension)); + if (keep && project != null && ClassUtils.isAssignable(extension.getClass(), CheckProject.class)) { + keep = ((CheckProject) extension).shouldExecuteOnProject(project); + } + return keep; + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginInstaller.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginInstaller.java new file mode 100644 index 00000000000..35b97e6ad7d --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginInstaller.java @@ -0,0 +1,164 @@ +/* + * 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.scanner.bootstrap; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.Lists; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.CharUtils; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.Plugin; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.sonar.api.utils.log.Profiler; +import org.sonar.core.platform.PluginInfo; +import org.sonar.core.platform.RemotePlugin; +import org.sonar.core.platform.RemotePluginFile; +import org.sonar.home.cache.FileCache; +import org.sonarqube.ws.client.GetRequest; +import org.sonarqube.ws.client.WsResponse; + +import static java.lang.String.format; + +/** + * Downloads the plugins installed on server and stores them in a local user cache + * (see {@link FileCacheProvider}). + */ +public class ScannerPluginInstaller implements PluginInstaller { + + private static final Logger LOG = Loggers.get(ScannerPluginInstaller.class); + private static final String PLUGINS_INDEX_URL = "/deploy/plugins/index.txt"; + + private final FileCache fileCache; + private final ScannerPluginPredicate pluginPredicate; + private final ScannerWsClient wsClient; + + public ScannerPluginInstaller(ScannerWsClient wsClient, FileCache fileCache, ScannerPluginPredicate pluginPredicate) { + this.fileCache = fileCache; + this.pluginPredicate = pluginPredicate; + this.wsClient = wsClient; + } + + @Override + public Map installRemotes() { + return loadPlugins(listRemotePlugins()); + } + + private Map loadPlugins(List remotePlugins) { + Map infosByKey = new HashMap<>(); + + Profiler profiler = Profiler.create(LOG).startDebug("Load plugins"); + + for (RemotePlugin remotePlugin : remotePlugins) { + if (pluginPredicate.apply(remotePlugin.getKey())) { + File jarFile = download(remotePlugin); + PluginInfo info = PluginInfo.create(jarFile); + infosByKey.put(info.getKey(), info); + } + } + + profiler.stopDebug(); + return infosByKey; + } + + /** + * Returns empty on purpose. This method is used only by tests. + * @see org.sonar.scanner.mediumtest.ScannerMediumTester + */ + @Override + public Map installLocals() { + return Collections.emptyMap(); + } + + @VisibleForTesting + File download(final RemotePlugin remote) { + try { + final RemotePluginFile file = remote.file(); + return fileCache.get(file.getFilename(), file.getHash(), new FileDownloader(remote.getKey())); + } catch (Exception e) { + throw new IllegalStateException("Fail to download plugin: " + remote.getKey(), e); + } + } + + /** + * Gets information about the plugins installed on server (filename, checksum) + */ + @VisibleForTesting + List listRemotePlugins() { + try { + String pluginIndex = loadPluginIndex(); + String[] rows = StringUtils.split(pluginIndex, CharUtils.LF); + List result = Lists.newArrayList(); + for (String row : rows) { + result.add(RemotePlugin.unmarshal(row)); + } + return result; + + } catch (Exception e) { + throw new IllegalStateException("Fail to load plugin index: " + PLUGINS_INDEX_URL, e); + } + } + + private String loadPluginIndex() { + Profiler profiler = Profiler.create(LOG).startInfo("Load plugins index"); + GetRequest getRequest = new GetRequest(PLUGINS_INDEX_URL); + String str; + try (Reader reader = wsClient.call(getRequest).contentReader()) { + str = IOUtils.toString(reader); + } catch(IOException e) { + throw new IllegalStateException(e); + } + + profiler.stopInfo(); + return str; + } + + private class FileDownloader implements FileCache.Downloader { + private String key; + + FileDownloader(String key) { + this.key = key; + } + + @Override + public void download(String filename, File toFile) throws IOException { + String url = format("/deploy/plugins/%s/%s", key, filename); + if (LOG.isDebugEnabled()) { + LOG.debug("Download plugin {} to {}", filename, toFile); + } else { + LOG.info("Download {}", filename); + } + + WsResponse response = wsClient.call(new GetRequest(url)); + try (InputStream stream = response.contentStream()) { + FileUtils.copyInputStreamToFile(stream, toFile); + } + } + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginJarExploder.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginJarExploder.java new file mode 100644 index 00000000000..f2d936e87d9 --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginJarExploder.java @@ -0,0 +1,80 @@ +/* + * 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.scanner.bootstrap; + +import org.apache.commons.io.FileUtils; +import org.sonar.api.batch.ScannerSide; +import org.sonar.api.utils.ZipUtils; +import org.sonar.core.platform.ExplodedPlugin; +import org.sonar.core.platform.PluginJarExploder; +import org.sonar.core.platform.PluginInfo; +import org.sonar.home.cache.FileCache; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import static org.sonar.core.util.FileUtils.deleteQuietly; + +@ScannerSide +public class ScannerPluginJarExploder extends PluginJarExploder { + + private final FileCache fileCache; + + public ScannerPluginJarExploder(FileCache fileCache) { + this.fileCache = fileCache; + } + + @Override + public ExplodedPlugin explode(PluginInfo info) { + try { + File dir = unzipFile(info.getNonNullJarFile()); + return explodeFromUnzippedDir(info.getKey(), info.getNonNullJarFile(), dir); + } catch (Exception e) { + throw new IllegalStateException(String.format("Fail to open plugin [%s]: %s", info.getKey(), info.getNonNullJarFile().getAbsolutePath()), e); + } + } + + private File unzipFile(File cachedFile) throws IOException { + String filename = cachedFile.getName(); + File destDir = new File(cachedFile.getParentFile(), filename + "_unzip"); + File lockFile = new File(cachedFile.getParentFile(), filename + "_unzip.lock"); + if (!destDir.exists()) { + FileOutputStream out = new FileOutputStream(lockFile); + try { + java.nio.channels.FileLock lock = out.getChannel().lock(); + try { + // Recheck in case of concurrent processes + if (!destDir.exists()) { + File tempDir = fileCache.createTempDir(); + ZipUtils.unzip(cachedFile, tempDir, newLibFilter()); + FileUtils.moveDirectory(tempDir, destDir); + } + } finally { + lock.release(); + } + } finally { + out.close(); + deleteQuietly(lockFile); + } + } + return destDir; + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginPredicate.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginPredicate.java new file mode 100644 index 00000000000..e3d0e2daea4 --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginPredicate.java @@ -0,0 +1,98 @@ +/* + * 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.scanner.bootstrap; + +import com.google.common.base.Joiner; +import com.google.common.base.Predicate; +import com.google.common.base.Splitter; +import com.google.common.collect.Lists; + +import java.util.List; +import java.util.Set; + +import javax.annotation.Nonnull; + +import org.apache.commons.lang.StringUtils; +import org.sonar.api.CoreProperties; +import org.sonar.api.batch.ScannerSide; +import org.sonar.api.config.Settings; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import static com.google.common.collect.Sets.newHashSet; + +/** + * Filters the plugins to be enabled during analysis + */ +@ScannerSide +public class ScannerPluginPredicate implements Predicate { + + private static final Logger LOG = Loggers.get(ScannerPluginPredicate.class); + + private static final String BUILDBREAKER_PLUGIN_KEY = "buildbreaker"; + private static final Joiner COMMA_JOINER = Joiner.on(", "); + + private final Set whites = newHashSet(); + private final Set blacks = newHashSet(); + private final GlobalMode mode; + + public ScannerPluginPredicate(Settings settings, GlobalMode mode) { + this.mode = mode; + if (mode.isPreview() || mode.isIssues()) { + // These default values are not supported by Settings because the class CorePlugin + // is not loaded yet. + whites.addAll(propertyValues(settings, + CoreProperties.PREVIEW_INCLUDE_PLUGINS, CoreProperties.PREVIEW_INCLUDE_PLUGINS_DEFAULT_VALUE)); + blacks.addAll(propertyValues(settings, + CoreProperties.PREVIEW_EXCLUDE_PLUGINS, CoreProperties.PREVIEW_EXCLUDE_PLUGINS_DEFAULT_VALUE)); + } + if (!whites.isEmpty()) { + LOG.info("Include plugins: " + COMMA_JOINER.join(whites)); + } + if (!blacks.isEmpty()) { + LOG.info("Exclude plugins: " + COMMA_JOINER.join(blacks)); + } + } + + @Override + public boolean apply(@Nonnull String pluginKey) { + if (BUILDBREAKER_PLUGIN_KEY.equals(pluginKey) && mode.isPreview()) { + LOG.info("Build Breaker plugin is no more supported in preview mode"); + return false; + } + + if (whites.isEmpty()) { + return blacks.isEmpty() || !blacks.contains(pluginKey); + } + return whites.contains(pluginKey); + } + + Set getWhites() { + return whites; + } + + Set getBlacks() { + return blacks; + } + + private static List propertyValues(Settings settings, String key, String defaultValue) { + String s = StringUtils.defaultIfEmpty(settings.getString(key), defaultValue); + return Lists.newArrayList(Splitter.on(",").trimResults().omitEmptyStrings().split(s)); + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginRepository.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginRepository.java new file mode 100644 index 00000000000..f804a528107 --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginRepository.java @@ -0,0 +1,109 @@ +/* + * 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.scanner.bootstrap; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Maps; +import java.util.Collection; +import java.util.Map; +import org.picocontainer.Startable; +import org.sonar.api.Plugin; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.sonar.core.platform.PluginInfo; +import org.sonar.core.platform.PluginLoader; +import org.sonar.core.platform.PluginRepository; + +/** + * Orchestrates the installation and loading of plugins + */ +public class ScannerPluginRepository implements PluginRepository, Startable { + private static final Logger LOG = Loggers.get(ScannerPluginRepository.class); + + private final PluginInstaller installer; + private final PluginLoader loader; + + private Map pluginInstancesByKeys; + private Map infosByKeys; + + public ScannerPluginRepository(PluginInstaller installer, PluginLoader loader) { + this.installer = installer; + this.loader = loader; + } + + @Override + public void start() { + infosByKeys = Maps.newHashMap(installer.installRemotes()); + pluginInstancesByKeys = Maps.newHashMap(loader.load(infosByKeys)); + + // this part is only used by tests + for (Map.Entry entry : installer.installLocals().entrySet()) { + String pluginKey = entry.getKey(); + infosByKeys.put(pluginKey, new PluginInfo(pluginKey)); + pluginInstancesByKeys.put(pluginKey, entry.getValue()); + } + + logPlugins(); + } + + private void logPlugins() { + if (infosByKeys.isEmpty()) { + LOG.debug("No plugins loaded"); + } else { + LOG.debug("Plugins:"); + for (PluginInfo p : infosByKeys.values()) { + LOG.debug(" * {} {} ({})", p.getName(), p.getVersion(), p.getKey()); + } + } + } + + @Override + public void stop() { + // close plugin classloaders + loader.unload(pluginInstancesByKeys.values()); + + pluginInstancesByKeys.clear(); + infosByKeys.clear(); + } + + @Override + public Collection getPluginInfos() { + return infosByKeys.values(); + } + + @Override + public PluginInfo getPluginInfo(String key) { + PluginInfo info = infosByKeys.get(key); + Preconditions.checkState(info != null, "Plugin [%s] does not exist", key); + return info; + } + + @Override + public Plugin getPluginInstance(String key) { + Plugin instance = pluginInstancesByKeys.get(key); + Preconditions.checkState(instance != null, "Plugin [%s] does not exist", key); + return instance; + } + + @Override + public boolean hasPlugin(String key) { + return infosByKeys.containsKey(key); + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClient.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClient.java new file mode 100644 index 00000000000..65ce8857932 --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClient.java @@ -0,0 +1,123 @@ +/* + * 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.scanner.bootstrap; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Joiner; +import com.google.common.base.Preconditions; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import java.util.ArrayList; +import java.util.List; +import org.sonar.api.CoreProperties; +import org.sonar.api.utils.MessageException; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.sonar.api.utils.log.Profiler; +import org.sonarqube.ws.client.HttpException; +import org.sonarqube.ws.client.WsClient; +import org.sonarqube.ws.client.WsConnector; +import org.sonarqube.ws.client.WsRequest; +import org.sonarqube.ws.client.WsResponse; + +import static java.lang.String.format; +import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; +import static java.net.HttpURLConnection.HTTP_FORBIDDEN; +import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; + +public class ScannerWsClient { + + private static final Logger LOG = Loggers.get(ScannerWsClient.class); + + private final WsClient target; + private final boolean hasCredentials; + private final GlobalMode globalMode; + + public ScannerWsClient(WsClient target, boolean hasCredentials, GlobalMode globalMode) { + this.target = target; + this.hasCredentials = hasCredentials; + this.globalMode = globalMode; + } + + /** + * If an exception is not thrown, the response needs to be closed by either calling close() directly, or closing the + * body content's stream/reader. + * @throws IllegalStateException if the request could not be executed due to + * a connectivity problem or timeout. Because networks can + * fail during an exchange, it is possible that the remote server + * accepted the request before the failure + * @throws HttpException if the response code is not in range [200..300) + */ + public WsResponse call(WsRequest request) { + Preconditions.checkState(!globalMode.isMediumTest(), "No WS call should be made in medium test mode"); + Profiler profiler = Profiler.createIfDebug(LOG).start(); + WsResponse response = target.wsConnector().call(request); + profiler.stopDebug(format("%s %d %s", request.getMethod(), response.code(), response.requestUrl())); + failIfUnauthorized(response); + return response; + } + + public String baseUrl() { + return target.wsConnector().baseUrl(); + } + + @VisibleForTesting + WsConnector wsConnector() { + return target.wsConnector(); + } + + private void failIfUnauthorized(WsResponse response) { + int code = response.code(); + if (code == HTTP_UNAUTHORIZED) { + response.close(); + if (hasCredentials) { + // credentials are not valid + throw MessageException.of(format("Not authorized. Please check the properties %s and %s.", + CoreProperties.LOGIN, CoreProperties.PASSWORD)); + } + // not authenticated - see https://jira.sonarsource.com/browse/SONAR-4048 + throw MessageException.of(format("Not authorized. Analyzing this project requires to be authenticated. " + + "Please provide the values of the properties %s and %s.", CoreProperties.LOGIN, CoreProperties.PASSWORD)); + + } + if (code == HTTP_FORBIDDEN || code == HTTP_BAD_REQUEST) { + // SONAR-4397 Details are in response content + throw MessageException.of(tryParseAsJsonError(response.content())); + } + response.failIfNotSuccessful(); + } + + private static String tryParseAsJsonError(String responseContent) { + try { + JsonParser parser = new JsonParser(); + JsonObject obj = parser.parse(responseContent).getAsJsonObject(); + JsonArray errors = obj.getAsJsonArray("errors"); + List errorMessages = new ArrayList<>(); + for (JsonElement e : errors) { + errorMessages.add(e.getAsJsonObject().get("msg").getAsString()); + } + return Joiner.on(", ").join(errorMessages); + } catch (Exception e) { + return responseContent; + } + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClientProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClientProvider.java new file mode 100644 index 00000000000..9e8203230bd --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClientProvider.java @@ -0,0 +1,66 @@ +/* + * 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.scanner.bootstrap; + +import org.picocontainer.injectors.ProviderAdapter; +import org.sonar.api.CoreProperties; +import org.sonar.api.batch.ScannerSide; +import org.sonar.batch.bootstrapper.EnvironmentInformation; +import org.sonarqube.ws.client.HttpConnector; +import org.sonarqube.ws.client.WsClientFactories; + +import static java.lang.Integer.parseInt; +import static java.lang.String.valueOf; +import static org.apache.commons.lang.StringUtils.defaultIfBlank; + +@ScannerSide +public class ScannerWsClientProvider extends ProviderAdapter { + + static final int CONNECT_TIMEOUT_MS = 5_000; + static final String READ_TIMEOUT_SEC_PROPERTY = "sonar.ws.timeout"; + static final int DEFAULT_READ_TIMEOUT_SEC = 60; + + private ScannerWsClient wsClient; + + public synchronized ScannerWsClient provide(final GlobalProperties settings, final EnvironmentInformation env, GlobalMode globalMode) { + if (wsClient == null) { + String url = defaultIfBlank(settings.property("sonar.host.url"), CoreProperties.SERVER_BASE_URL_DEFAULT_VALUE); + HttpConnector.Builder connectorBuilder = HttpConnector.newBuilder(); + + String timeoutSec = defaultIfBlank(settings.property(READ_TIMEOUT_SEC_PROPERTY), valueOf(DEFAULT_READ_TIMEOUT_SEC)); + String login = defaultIfBlank(settings.property(CoreProperties.LOGIN), null); + connectorBuilder + .readTimeoutMilliseconds(parseInt(timeoutSec) * 1_000) + .connectTimeoutMilliseconds(CONNECT_TIMEOUT_MS) + .userAgent(env.toString()) + .url(url) + .credentials(login, settings.property(CoreProperties.PASSWORD)); + + // OkHttp detect 'http.proxyHost' java property, but credentials should be filled + final String proxyUser = System.getProperty("http.proxyUser", ""); + if (!System.getProperty("http.proxyHost", "").isEmpty() && !proxyUser.isEmpty()) { + connectorBuilder.proxyCredentials(proxyUser, System.getProperty("http.proxyPassword")); + } + + wsClient = new ScannerWsClient(WsClientFactories.getDefault().newClient(connectorBuilder.build()), login != null, globalMode); + } + return wsClient; + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/InputFileComponent.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/InputFileComponent.java deleted file mode 100644 index 8a11c1856e4..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/InputFileComponent.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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.scanner.deprecated; - -import org.sonar.api.batch.fs.InputFile.Type; -import org.sonar.api.batch.fs.internal.DefaultInputFile; -import org.sonar.api.component.Component; -import org.sonar.api.resources.Qualifiers; - -public class InputFileComponent implements Component { - - private final DefaultInputFile inputFile; - - public InputFileComponent(DefaultInputFile inputFile) { - this.inputFile = inputFile; - } - - @Override - public String key() { - return inputFile.key(); - } - - @Override - public String path() { - return inputFile.relativePath(); - } - - @Override - public String name() { - return inputFile.file().getName(); - } - - @Override - public String longName() { - return inputFile.relativePath(); - } - - @Override - public String qualifier() { - return inputFile.type() == Type.MAIN ? Qualifiers.FILE : Qualifiers.UNIT_TEST_FILE; - } - -} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/tracking/DefaultServerLineHashesLoader.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/tracking/DefaultServerLineHashesLoader.java index 1e2d92c2cc6..ed0d6551fea 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/tracking/DefaultServerLineHashesLoader.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/tracking/DefaultServerLineHashesLoader.java @@ -29,13 +29,13 @@ import com.google.common.collect.Iterators; import org.apache.commons.io.IOUtils; import org.sonar.api.utils.log.Loggers; import org.sonar.api.utils.log.Profiler; -import org.sonar.scanner.bootstrap.BatchWsClient; +import org.sonar.scanner.bootstrap.ScannerWsClient; import org.sonar.scanner.util.BatchUtils; public class DefaultServerLineHashesLoader implements ServerLineHashesLoader { - private BatchWsClient wsClient; + private ScannerWsClient wsClient; - public DefaultServerLineHashesLoader(BatchWsClient wsClient) { + public DefaultServerLineHashesLoader(ScannerWsClient wsClient) { this.wsClient = wsClient; } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/FakePluginInstaller.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/FakePluginInstaller.java index 6fdb948df38..13c75c2e0eb 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/FakePluginInstaller.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/FakePluginInstaller.java @@ -27,7 +27,6 @@ import org.sonar.core.platform.PluginInfo; import org.sonar.scanner.bootstrap.PluginInstaller; public class FakePluginInstaller implements PluginInstaller { - public static final String MEDIUM_TEST_ENABLED = "sonar.mediumTest.enabled"; private final Map infosByKeys = new HashMap<>(); private final Map instancesByKeys = new HashMap<>(); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/InitializersExecutor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/InitializersExecutor.java index e2b5bc6fdac..91cf3e899a0 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/InitializersExecutor.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/InitializersExecutor.java @@ -26,7 +26,7 @@ import org.sonar.api.resources.Project; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.api.utils.log.Profiler; -import org.sonar.scanner.bootstrap.BatchExtensionDictionnary; +import org.sonar.scanner.bootstrap.ScannerExtensionDictionnary; import org.sonar.scanner.events.EventBus; import java.util.Collection; @@ -35,10 +35,10 @@ public class InitializersExecutor { private static final Logger LOG = Loggers.get(SensorsExecutor.class); private Project project; - private BatchExtensionDictionnary selector; + private ScannerExtensionDictionnary selector; private EventBus eventBus; - public InitializersExecutor(BatchExtensionDictionnary selector, Project project, EventBus eventBus) { + public InitializersExecutor(ScannerExtensionDictionnary selector, Project project, EventBus eventBus) { this.selector = selector; this.project = project; this.eventBus = eventBus; diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/PostJobsExecutor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/PostJobsExecutor.java index f01ab46a896..ce5863ecc1b 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/PostJobsExecutor.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/PostJobsExecutor.java @@ -28,7 +28,7 @@ import org.sonar.api.batch.SensorContext; import org.sonar.api.resources.Project; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; -import org.sonar.scanner.bootstrap.BatchExtensionDictionnary; +import org.sonar.scanner.bootstrap.ScannerExtensionDictionnary; import org.sonar.scanner.events.EventBus; import org.sonar.scanner.util.BatchUtils; @@ -36,11 +36,11 @@ import org.sonar.scanner.util.BatchUtils; public class PostJobsExecutor { private static final Logger LOG = Loggers.get(PostJobsExecutor.class); - private final BatchExtensionDictionnary selector; + private final ScannerExtensionDictionnary selector; private final Project project; private final EventBus eventBus; - public PostJobsExecutor(BatchExtensionDictionnary selector, Project project, EventBus eventBus) { + public PostJobsExecutor(ScannerExtensionDictionnary selector, Project project, EventBus eventBus) { this.selector = selector; this.project = project; this.eventBus = eventBus; diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/SensorsExecutor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/SensorsExecutor.java index 5953f4d5613..acaa8727cf9 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/SensorsExecutor.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/phases/SensorsExecutor.java @@ -24,7 +24,7 @@ import org.sonar.api.batch.ScannerSide; import org.sonar.api.batch.Sensor; import org.sonar.api.batch.SensorContext; import org.sonar.api.resources.Project; -import org.sonar.scanner.bootstrap.BatchExtensionDictionnary; +import org.sonar.scanner.bootstrap.ScannerExtensionDictionnary; import org.sonar.scanner.events.EventBus; import java.util.Collection; @@ -33,9 +33,9 @@ public class SensorsExecutor { private EventBus eventBus; private Project module; - private BatchExtensionDictionnary selector; + private ScannerExtensionDictionnary selector; - public SensorsExecutor(BatchExtensionDictionnary selector, Project project, EventBus eventBus) { + public SensorsExecutor(ScannerExtensionDictionnary selector, Project project, EventBus eventBus) { this.selector = selector; this.eventBus = eventBus; this.module = project; diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/platform/DefaultServer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/platform/DefaultServer.java index 594c7b5ba31..c125952ef3b 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/platform/DefaultServer.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/platform/DefaultServer.java @@ -28,7 +28,7 @@ import org.sonar.api.batch.ScannerSide; import org.sonar.api.config.Settings; import org.sonar.api.platform.Server; import org.sonar.api.utils.DateUtils; -import org.sonar.scanner.bootstrap.BatchWsClient; +import org.sonar.scanner.bootstrap.ScannerWsClient; import static org.apache.commons.lang.StringUtils.trimToEmpty; @@ -36,9 +36,9 @@ import static org.apache.commons.lang.StringUtils.trimToEmpty; public class DefaultServer extends Server { private final Settings settings; - private final BatchWsClient client; + private final ScannerWsClient client; - public DefaultServer(Settings settings, BatchWsClient client) { + public DefaultServer(Settings settings, ScannerWsClient client) { this.settings = settings; this.client = client; } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/AnalysisContextReportPublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/AnalysisContextReportPublisher.java index 65c483c535b..39f22a46aec 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/AnalysisContextReportPublisher.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/AnalysisContextReportPublisher.java @@ -37,7 +37,7 @@ import org.sonar.api.utils.System2; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.core.platform.PluginInfo; -import org.sonar.scanner.bootstrap.BatchPluginRepository; +import org.sonar.scanner.bootstrap.ScannerPluginRepository; import org.sonar.scanner.protocol.input.GlobalRepositories; import org.sonar.scanner.protocol.output.ScannerReportWriter; import org.sonar.scanner.repository.ProjectRepositories; @@ -51,7 +51,7 @@ public class AnalysisContextReportPublisher { private static final String ENV_PROP_PREFIX = "env."; private static final String SONAR_PROP_PREFIX = "sonar."; - private final BatchPluginRepository pluginRepo; + private final ScannerPluginRepository pluginRepo; private final AnalysisMode mode; private final System2 system; private final ProjectRepositories projectRepos; @@ -59,7 +59,7 @@ public class AnalysisContextReportPublisher { private ScannerReportWriter writer; - public AnalysisContextReportPublisher(AnalysisMode mode, BatchPluginRepository pluginRepo, System2 system, + public AnalysisContextReportPublisher(AnalysisMode mode, ScannerPluginRepository pluginRepo, System2 system, ProjectRepositories projectRepos, GlobalRepositories globalRepositories) { this.mode = mode; this.pluginRepo = pluginRepo; diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ReportPublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ReportPublisher.java index 5c291d30dd2..e082bcecfd9 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ReportPublisher.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ReportPublisher.java @@ -44,7 +44,7 @@ import org.sonar.api.utils.ZipUtils; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.scanner.analysis.DefaultAnalysisMode; -import org.sonar.scanner.bootstrap.BatchWsClient; +import org.sonar.scanner.bootstrap.ScannerWsClient; import org.sonar.scanner.protocol.output.ScannerReportWriter; import org.sonar.scanner.scan.ImmutableProjectReactor; import org.sonarqube.ws.MediaTypes; @@ -64,7 +64,7 @@ public class ReportPublisher implements Startable { public static final String METADATA_DUMP_FILENAME = "report-task.txt"; private final Settings settings; - private final BatchWsClient wsClient; + private final ScannerWsClient wsClient; private final AnalysisContextReportPublisher contextPublisher; private final ImmutableProjectReactor projectReactor; private final DefaultAnalysisMode analysisMode; @@ -75,7 +75,7 @@ public class ReportPublisher implements Startable { private File reportDir; private ScannerReportWriter writer; - public ReportPublisher(Settings settings, BatchWsClient wsClient, Server server, AnalysisContextReportPublisher contextPublisher, + public ReportPublisher(Settings settings, ScannerWsClient wsClient, Server server, AnalysisContextReportPublisher contextPublisher, ImmutableProjectReactor projectReactor, DefaultAnalysisMode analysisMode, TempFolder temp, ReportPublisherStep[] publishers) { this.settings = settings; this.wsClient = wsClient; diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultGlobalRepositoriesLoader.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultGlobalRepositoriesLoader.java index 84a44c49d12..5c2ca68395c 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultGlobalRepositoriesLoader.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultGlobalRepositoriesLoader.java @@ -19,7 +19,7 @@ */ package org.sonar.scanner.repository; -import org.sonar.scanner.bootstrap.BatchWsClient; +import org.sonar.scanner.bootstrap.ScannerWsClient; import org.sonar.scanner.protocol.input.GlobalRepositories; import org.sonarqube.ws.client.GetRequest; import java.io.IOException; @@ -30,9 +30,9 @@ import org.apache.commons.io.IOUtils; public class DefaultGlobalRepositoriesLoader implements GlobalRepositoriesLoader { private static final String BATCH_GLOBAL_URL = "/batch/global"; - private BatchWsClient wsClient; + private ScannerWsClient wsClient; - public DefaultGlobalRepositoriesLoader(BatchWsClient wsClient) { + public DefaultGlobalRepositoriesLoader(ScannerWsClient wsClient) { this.wsClient = wsClient; } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultProjectRepositoriesLoader.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultProjectRepositoriesLoader.java index abdefcae436..2ccfb6c8a7f 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultProjectRepositoriesLoader.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultProjectRepositoriesLoader.java @@ -31,7 +31,7 @@ import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.utils.MessageException; -import org.sonar.scanner.bootstrap.BatchWsClient; +import org.sonar.scanner.bootstrap.ScannerWsClient; import org.sonar.scanner.util.BatchUtils; import org.sonarqube.ws.WsBatch; import org.sonarqube.ws.WsBatch.WsProjectResponse; @@ -44,9 +44,9 @@ import org.sonarqube.ws.client.WsResponse; public class DefaultProjectRepositoriesLoader implements ProjectRepositoriesLoader { private static final Logger LOG = LoggerFactory.getLogger(DefaultProjectRepositoriesLoader.class); private static final String BATCH_PROJECT_URL = "/batch/project.protobuf"; - private BatchWsClient wsClient; + private ScannerWsClient wsClient; - public DefaultProjectRepositoriesLoader(BatchWsClient wsClient) { + public DefaultProjectRepositoriesLoader(ScannerWsClient wsClient) { this.wsClient = wsClient; } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultQualityProfileLoader.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultQualityProfileLoader.java index 6ed05d2a7bc..148f7ee0c82 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultQualityProfileLoader.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultQualityProfileLoader.java @@ -20,7 +20,7 @@ package org.sonar.scanner.repository; import org.sonar.api.utils.MessageException; -import org.sonar.scanner.bootstrap.BatchWsClient; +import org.sonar.scanner.bootstrap.ScannerWsClient; import org.sonar.scanner.util.BatchUtils; import org.sonarqube.ws.QualityProfiles.SearchWsResponse; import org.apache.commons.io.IOUtils; @@ -35,9 +35,9 @@ import java.util.List; public class DefaultQualityProfileLoader implements QualityProfileLoader { private static final String WS_URL = "/api/qualityprofiles/search.protobuf"; - private BatchWsClient wsClient; + private ScannerWsClient wsClient; - public DefaultQualityProfileLoader(BatchWsClient wsClient) { + public DefaultQualityProfileLoader(ScannerWsClient wsClient) { this.wsClient = wsClient; } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultServerIssuesLoader.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultServerIssuesLoader.java index 00015cee70a..02e8ff57a47 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultServerIssuesLoader.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultServerIssuesLoader.java @@ -23,16 +23,16 @@ import com.google.common.base.Function; import java.io.IOException; import java.io.InputStream; import org.apache.commons.io.IOUtils; -import org.sonar.scanner.bootstrap.BatchWsClient; +import org.sonar.scanner.bootstrap.ScannerWsClient; import org.sonar.scanner.protocol.input.ScannerInput.ServerIssue; import org.sonar.scanner.util.BatchUtils; import org.sonarqube.ws.client.GetRequest; public class DefaultServerIssuesLoader implements ServerIssuesLoader { - private final BatchWsClient wsClient; + private final ScannerWsClient wsClient; - public DefaultServerIssuesLoader(BatchWsClient wsClient) { + public DefaultServerIssuesLoader(ScannerWsClient wsClient) { this.wsClient = wsClient; } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/user/UserRepositoryLoader.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/user/UserRepositoryLoader.java index acf5d8c7d95..42d6fca9840 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/user/UserRepositoryLoader.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/user/UserRepositoryLoader.java @@ -22,7 +22,7 @@ package org.sonar.scanner.repository.user; import org.apache.commons.io.IOUtils; import com.google.common.collect.Lists; import com.google.common.base.Joiner; -import org.sonar.scanner.bootstrap.BatchWsClient; +import org.sonar.scanner.bootstrap.ScannerWsClient; import org.sonar.scanner.protocol.input.ScannerInput; import org.sonar.scanner.util.BatchUtils; import org.sonarqube.ws.client.GetRequest; @@ -35,9 +35,9 @@ import java.util.Collections; import java.util.List; public class UserRepositoryLoader { - private final BatchWsClient wsClient; + private final ScannerWsClient wsClient; - public UserRepositoryLoader(BatchWsClient wsClient) { + public UserRepositoryLoader(ScannerWsClient wsClient) { this.wsClient = wsClient; } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultActiveRulesLoader.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultActiveRulesLoader.java index 7df5a23f820..4a6db254ed9 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultActiveRulesLoader.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultActiveRulesLoader.java @@ -27,7 +27,7 @@ import java.util.List; import java.util.Map; import org.apache.commons.io.IOUtils; import org.sonar.api.rule.RuleKey; -import org.sonar.scanner.bootstrap.BatchWsClient; +import org.sonar.scanner.bootstrap.ScannerWsClient; import org.sonar.scanner.util.BatchUtils; import org.sonarqube.ws.Rules; import org.sonarqube.ws.Rules.Active; @@ -40,9 +40,9 @@ import org.sonarqube.ws.client.GetRequest; public class DefaultActiveRulesLoader implements ActiveRulesLoader { private static final String RULES_SEARCH_URL = "/api/rules/search.protobuf?f=repo,name,severity,lang,internalKey,templateKey,params,actives&activation=true"; - private final BatchWsClient wsClient; + private final ScannerWsClient wsClient; - public DefaultActiveRulesLoader(BatchWsClient wsClient) { + public DefaultActiveRulesLoader(ScannerWsClient wsClient) { this.wsClient = wsClient; } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultRulesLoader.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultRulesLoader.java index ff310de154b..3162e51eaf4 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultRulesLoader.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultRulesLoader.java @@ -20,7 +20,7 @@ package org.sonar.scanner.rule; import org.apache.commons.io.IOUtils; -import org.sonar.scanner.bootstrap.BatchWsClient; +import org.sonar.scanner.bootstrap.ScannerWsClient; import org.sonarqube.ws.Rules.ListResponse.Rule; import org.sonarqube.ws.client.GetRequest; import org.sonarqube.ws.Rules.ListResponse; @@ -32,9 +32,9 @@ import java.util.List; public class DefaultRulesLoader implements RulesLoader { private static final String RULES_SEARCH_URL = "/api/rules/list.protobuf"; - private final BatchWsClient wsClient; + private final ScannerWsClient wsClient; - public DefaultRulesLoader(BatchWsClient wsClient) { + public DefaultRulesLoader(ScannerWsClient wsClient) { this.wsClient = wsClient; } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleScanContainer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleScanContainer.java index 5ab42b57c2e..1033130b961 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleScanContainer.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleScanContainer.java @@ -31,7 +31,7 @@ import org.sonar.api.scan.filesystem.FileExclusions; import org.sonar.core.platform.ComponentContainer; import org.sonar.scanner.DefaultFileLinesContextFactory; import org.sonar.scanner.DefaultProjectTree; -import org.sonar.scanner.bootstrap.BatchExtensionDictionnary; +import org.sonar.scanner.bootstrap.ScannerExtensionDictionnary; import org.sonar.scanner.bootstrap.ExtensionInstaller; import org.sonar.scanner.bootstrap.ExtensionUtils; import org.sonar.scanner.deprecated.DeprecatedSensorContext; @@ -140,7 +140,7 @@ public class ModuleScanContainer extends ComponentContainer { DefaultPostJobContext.class, DefaultSensorStorage.class, DeprecatedSensorContext.class, - BatchExtensionDictionnary.class, + ScannerExtensionDictionnary.class, IssueFilters.class, CoverageExclusions.class, -- cgit v1.2.3