diff options
author | Simon Brandhof <simon.brandhof@sonarsource.com> | 2015-04-24 09:15:05 +0200 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@sonarsource.com> | 2015-05-11 10:21:55 +0200 |
commit | 14a5c982e5f1b28354a853073bd3e225b3914abe (patch) | |
tree | e298a2948f49628880f8d5290451adc14a920613 /sonar-batch | |
parent | cba928d505985972e13c8e895b490a52702af925 (diff) | |
download | sonarqube-14a5c982e5f1b28354a853073bd3e225b3914abe.tar.gz sonarqube-14a5c982e5f1b28354a853073bd3e225b3914abe.zip |
SONAR-6370 isolate plugin classloader from core
Diffstat (limited to 'sonar-batch')
24 files changed, 835 insertions, 601 deletions
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java index 0f1eea698ea..1575f757006 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java @@ -32,7 +32,7 @@ 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.platform.ComponentContainer; +import org.sonar.core.platform.ComponentContainer; import org.sonar.api.resources.Project; import org.sonar.api.utils.AnnotationUtils; import org.sonar.api.utils.dag.DirectAcyclicGraph; diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/DefaultPluginsRepository.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginInstaller.java index 2687ebc56df..6e2c5886c60 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/DefaultPluginsRepository.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginInstaller.java @@ -19,13 +19,14 @@ */ package org.sonar.batch.bootstrap; +import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Lists; import org.apache.commons.lang.CharUtils; import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.SonarPlugin; -import org.sonar.api.platform.PluginMetadata; +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.plugins.RemotePlugin; import org.sonar.core.plugins.RemotePluginFile; import org.sonar.home.cache.FileCache; @@ -33,26 +34,52 @@ import org.sonar.home.cache.FileCache; import java.io.File; import java.io.IOException; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; /** - * A {@link PluginsRepository} implementation that put downloaded plugins in a FS cache. + * Downloads the plugins installed on server and stores them in a local user cache + * (see {@link FileCacheProvider}). */ -public class DefaultPluginsRepository implements PluginsRepository { +public class BatchPluginInstaller implements PluginInstaller { - private static final Logger LOG = LoggerFactory.getLogger(DefaultPluginsRepository.class); + private static final Logger LOG = Loggers.get(BatchPluginInstaller.class); - private ServerClient server; - private FileCache fileCache; + private final ServerClient server; + private final FileCache fileCache; + private final BatchPluginPredicate pluginPredicate; - public DefaultPluginsRepository(FileCache fileCache, ServerClient server) { + public BatchPluginInstaller(ServerClient server, FileCache fileCache, BatchPluginPredicate pluginPredicate) { this.server = server; this.fileCache = fileCache; + this.pluginPredicate = pluginPredicate; } @Override - public File pluginFile(final RemotePlugin remote) { + public Map<String, PluginInfo> installRemotes() { + Map<String, PluginInfo> infosByKey = new HashMap<>(); + for (RemotePlugin remotePlugin : listRemotePlugins()) { + if (pluginPredicate.apply(remotePlugin.getKey())) { + File jarFile = download(remotePlugin); + PluginInfo info = PluginInfo.create(jarFile); + infosByKey.put(info.getKey(), info); + } + } + return infosByKey; + } + + /** + * Returns empty on purpose. This method is used only by tests. + * @see org.sonar.batch.mediumtest.BatchMediumTester + */ + @Override + public Map<String, Plugin> installLocals() { + return Collections.emptyMap(); + } + + @VisibleForTesting + File download(final RemotePlugin remote) { try { final RemotePluginFile file = remote.file(); return fileCache.get(file.getFilename(), file.getHash(), new FileCache.Downloader() { @@ -73,27 +100,24 @@ public class DefaultPluginsRepository implements PluginsRepository { } } - @Override - public List<RemotePlugin> pluginList() { + /** + * Gets information about the plugins installed on server (filename, checksum) + */ + @VisibleForTesting + List<RemotePlugin> listRemotePlugins() { String url = "/deploy/plugins/index.txt"; try { LOG.debug("Download index of plugins"); String indexContent = server.request(url); String[] rows = StringUtils.split(indexContent, CharUtils.LF); - List<RemotePlugin> remoteLocations = Lists.newArrayList(); + List<RemotePlugin> result = Lists.newArrayList(); for (String row : rows) { - remoteLocations.add(RemotePlugin.unmarshal(row)); + result.add(RemotePlugin.unmarshal(row)); } - return remoteLocations; + return result; } catch (Exception e) { - throw new IllegalStateException("Fail to download plugins index: " + url, e); + throw new IllegalStateException("Fail to download list of plugins: " + url, e); } } - - @Override - public Map<PluginMetadata, SonarPlugin> localPlugins() { - return Collections.emptyMap(); - } - } diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginPredicate.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginPredicate.java new file mode 100644 index 00000000000..f283dcd7247 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginPredicate.java @@ -0,0 +1,121 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.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 org.apache.commons.lang.StringUtils; +import org.sonar.api.BatchComponent; +import org.sonar.api.CoreProperties; +import org.sonar.api.config.Settings; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; + +import javax.annotation.Nonnull; +import java.text.MessageFormat; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +import static com.google.common.collect.Lists.newArrayList; +import static com.google.common.collect.Sets.newHashSet; + +/** + * Filters the plugins to be enabled during analysis + */ +public class BatchPluginPredicate implements Predicate<String>, BatchComponent { + + private static final Logger LOG = Loggers.get(BatchPluginPredicate.class); + + private static final String CORE_PLUGIN_KEY = "core"; + private static final String BUILDBREAKER_PLUGIN_KEY = "buildbreaker"; + private static final String PROPERTY_IS_DEPRECATED_MSG = "Property {0} is deprecated. Please use {1} instead."; + + private final Set<String> whites = newHashSet(), blacks = newHashSet(); + private final DefaultAnalysisMode mode; + + public BatchPluginPredicate(Settings settings, DefaultAnalysisMode mode) { + this.mode = mode; + if (settings.hasKey(CoreProperties.BATCH_INCLUDE_PLUGINS)) { + whites.addAll(Arrays.asList(settings.getStringArray(CoreProperties.BATCH_INCLUDE_PLUGINS))); + } + if (settings.hasKey(CoreProperties.BATCH_EXCLUDE_PLUGINS)) { + blacks.addAll(Arrays.asList(settings.getStringArray(CoreProperties.BATCH_EXCLUDE_PLUGINS))); + } + if (mode.isPreview()) { + // These default values are not supported by Settings because the class CorePlugin + // is not loaded yet. + if (settings.hasKey(CoreProperties.DRY_RUN_INCLUDE_PLUGINS)) { + LOG.warn(MessageFormat.format(PROPERTY_IS_DEPRECATED_MSG, CoreProperties.DRY_RUN_INCLUDE_PLUGINS, CoreProperties.PREVIEW_INCLUDE_PLUGINS)); + whites.addAll(propertyValues(settings, + CoreProperties.DRY_RUN_INCLUDE_PLUGINS, CoreProperties.PREVIEW_INCLUDE_PLUGINS_DEFAULT_VALUE)); + } else { + whites.addAll(propertyValues(settings, + CoreProperties.PREVIEW_INCLUDE_PLUGINS, CoreProperties.PREVIEW_INCLUDE_PLUGINS_DEFAULT_VALUE)); + } + if (settings.hasKey(CoreProperties.DRY_RUN_EXCLUDE_PLUGINS)) { + LOG.warn(MessageFormat.format(PROPERTY_IS_DEPRECATED_MSG, CoreProperties.DRY_RUN_EXCLUDE_PLUGINS, CoreProperties.PREVIEW_EXCLUDE_PLUGINS)); + blacks.addAll(propertyValues(settings, + CoreProperties.DRY_RUN_EXCLUDE_PLUGINS, CoreProperties.PREVIEW_EXCLUDE_PLUGINS_DEFAULT_VALUE)); + } else { + blacks.addAll(propertyValues(settings, + CoreProperties.PREVIEW_EXCLUDE_PLUGINS, CoreProperties.PREVIEW_EXCLUDE_PLUGINS_DEFAULT_VALUE)); + } + } + if (!whites.isEmpty()) { + LOG.info("Include plugins: " + Joiner.on(", ").join(whites)); + } + if (!blacks.isEmpty()) { + LOG.info("Exclude plugins: " + Joiner.on(", ").join(blacks)); + } + } + + @Override + public boolean apply(@Nonnull String pluginKey) { + if (CORE_PLUGIN_KEY.equals(pluginKey)) { + return !mode.isMediumTest(); + } + + if (BUILDBREAKER_PLUGIN_KEY.equals(pluginKey) && mode.isPreview()) { + LOG.info("Build Breaker plugin is no more supported in preview/incremental mode"); + return false; + } + + // FIXME what happens if there are only white-listed plugins ? + List<String> mergeList = newArrayList(blacks); + mergeList.removeAll(whites); + return mergeList.isEmpty() || !mergeList.contains(pluginKey); + } + + Set<String> getWhites() { + return whites; + } + + Set<String> getBlacks() { + return blacks; + } + + static List<String> propertyValues(Settings settings, String key, String defaultValue) { + String s = StringUtils.defaultIfEmpty(settings.getString(key), defaultValue); + return Lists.newArrayList(Splitter.on(",").trimResults().split(s)); + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java index b8a44c0d97c..b20c85114ed 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java @@ -19,174 +19,69 @@ */ package org.sonar.batch.bootstrap; -import com.google.common.base.Joiner; -import com.google.common.base.Splitter; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.CoreProperties; +import org.picocontainer.Startable; import org.sonar.api.Plugin; -import org.sonar.api.SonarPlugin; -import org.sonar.api.config.Settings; -import org.sonar.api.platform.PluginMetadata; -import org.sonar.api.platform.PluginRepository; -import org.sonar.core.plugins.PluginClassloaders; -import org.sonar.core.plugins.RemotePlugin; +import org.sonar.core.platform.PluginInfo; +import org.sonar.core.platform.PluginLoader; +import org.sonar.core.platform.PluginRepository; -import java.io.File; -import java.text.MessageFormat; -import java.util.*; +import java.util.Collection; +import java.util.Map; -import static com.google.common.collect.Lists.newArrayList; -import static com.google.common.collect.Sets.newHashSet; +public class BatchPluginRepository implements PluginRepository, Startable { -public class BatchPluginRepository implements PluginRepository { + private final PluginInstaller installer; + private final PluginLoader loader; - private static final Logger LOG = LoggerFactory.getLogger(BatchPluginRepository.class); - private static final String CORE_PLUGIN = "core"; + private Map<String, Plugin> pluginInstancesByKeys; + private Map<String, PluginInfo> infosByKeys; - private PluginsRepository pluginsReferential; - private Map<String, Plugin> pluginsByKey; - private Map<String, PluginMetadata> metadataByKey; - private Settings settings; - private PluginClassloaders classLoaders; - private final DefaultAnalysisMode analysisMode; - private final BatchPluginJarInstaller pluginInstaller; - - public BatchPluginRepository(PluginsRepository pluginsReferential, Settings settings, DefaultAnalysisMode analysisMode, - BatchPluginJarInstaller pluginInstaller) { - this.pluginsReferential = pluginsReferential; - this.settings = settings; - this.analysisMode = analysisMode; - this.pluginInstaller = pluginInstaller; + public BatchPluginRepository(PluginInstaller installer, PluginLoader loader) { + this.installer = installer; + this.loader = loader; } + @Override public void start() { - LOG.info("Install plugins"); - doStart(pluginsReferential.pluginList()); - - Map<PluginMetadata, SonarPlugin> localPlugins = pluginsReferential.localPlugins(); - if (!localPlugins.isEmpty()) { - LOG.info("Install local plugins"); - for (Map.Entry<PluginMetadata, SonarPlugin> pluginByMetadata : localPlugins.entrySet()) { - metadataByKey.put(pluginByMetadata.getKey().getKey(), pluginByMetadata.getKey()); - pluginsByKey.put(pluginByMetadata.getKey().getKey(), pluginByMetadata.getValue()); - } - } - } + infosByKeys = installer.installRemotes(); + pluginInstancesByKeys = loader.load(infosByKeys); - void doStart(List<RemotePlugin> remotePlugins) { - PluginFilter filter = new PluginFilter(settings, analysisMode); - metadataByKey = Maps.newHashMap(); - for (RemotePlugin remote : remotePlugins) { - if (filter.accepts(remote.getKey())) { - File pluginFile = pluginsReferential.pluginFile(remote); - PluginMetadata metadata = pluginInstaller.installToCache(pluginFile, remote.isCore()); - if (StringUtils.isBlank(metadata.getBasePlugin()) || filter.accepts(metadata.getBasePlugin())) { - metadataByKey.put(metadata.getKey(), metadata); - } else { - LOG.debug("Excluded plugin: " + metadata.getKey()); - } - } + // this part is only used by tests + for (Map.Entry<String, Plugin> entry : installer.installLocals().entrySet()) { + String pluginKey = entry.getKey(); + infosByKeys.put(pluginKey, new PluginInfo(pluginKey)); + pluginInstancesByKeys.put(pluginKey, entry.getValue()); } - classLoaders = new PluginClassloaders(Thread.currentThread().getContextClassLoader()); - pluginsByKey = classLoaders.init(metadataByKey.values()); } + @Override public void stop() { - if (classLoaders != null) { - classLoaders.clean(); - classLoaders = null; - } - } + // close plugin classloaders + loader.unload(pluginInstancesByKeys.values()); - @Override - public Plugin getPlugin(String key) { - return pluginsByKey.get(key); + pluginInstancesByKeys.clear(); + infosByKeys.clear(); } @Override - public Collection<PluginMetadata> getMetadata() { - return metadataByKey.values(); + public Collection<PluginInfo> getPluginInfos() { + return infosByKeys.values(); } @Override - public PluginMetadata getMetadata(String pluginKey) { - return metadataByKey.get(pluginKey); + public PluginInfo getPluginInfo(String key) { + // TODO check null result + return infosByKeys.get(key); } - public Map<PluginMetadata, Plugin> getPluginsByMetadata() { - Map<PluginMetadata, Plugin> result = Maps.newHashMap(); - for (Map.Entry<String, PluginMetadata> entry : metadataByKey.entrySet()) { - String pluginKey = entry.getKey(); - PluginMetadata metadata = entry.getValue(); - result.put(metadata, pluginsByKey.get(pluginKey)); - } - return result; + @Override + public Plugin getPluginInstance(String key) { + // TODO check null result + return pluginInstancesByKeys.get(key); } - static class PluginFilter { - private static final String BUILDBREAKER_PLUGIN_KEY = "buildbreaker"; - private static final String PROPERTY_IS_DEPRECATED_MSG = "Property {0} is deprecated. Please use {1} instead."; - Set<String> whites = newHashSet(), blacks = newHashSet(); - private DefaultAnalysisMode mode; - - PluginFilter(Settings settings, DefaultAnalysisMode mode) { - this.mode = mode; - if (settings.hasKey(CoreProperties.BATCH_INCLUDE_PLUGINS)) { - whites.addAll(Arrays.asList(settings.getStringArray(CoreProperties.BATCH_INCLUDE_PLUGINS))); - } - if (settings.hasKey(CoreProperties.BATCH_EXCLUDE_PLUGINS)) { - blacks.addAll(Arrays.asList(settings.getStringArray(CoreProperties.BATCH_EXCLUDE_PLUGINS))); - } - if (mode.isPreview()) { - // These default values are not supported by Settings because the class CorePlugin - // is not loaded yet. - if (settings.hasKey(CoreProperties.DRY_RUN_INCLUDE_PLUGINS)) { - LOG.warn(MessageFormat.format(PROPERTY_IS_DEPRECATED_MSG, CoreProperties.DRY_RUN_INCLUDE_PLUGINS, CoreProperties.PREVIEW_INCLUDE_PLUGINS)); - whites.addAll(propertyValues(settings, - CoreProperties.DRY_RUN_INCLUDE_PLUGINS, CoreProperties.PREVIEW_INCLUDE_PLUGINS_DEFAULT_VALUE)); - } else { - whites.addAll(propertyValues(settings, - CoreProperties.PREVIEW_INCLUDE_PLUGINS, CoreProperties.PREVIEW_INCLUDE_PLUGINS_DEFAULT_VALUE)); - } - if (settings.hasKey(CoreProperties.DRY_RUN_EXCLUDE_PLUGINS)) { - LOG.warn(MessageFormat.format(PROPERTY_IS_DEPRECATED_MSG, CoreProperties.DRY_RUN_EXCLUDE_PLUGINS, CoreProperties.PREVIEW_EXCLUDE_PLUGINS)); - blacks.addAll(propertyValues(settings, - CoreProperties.DRY_RUN_EXCLUDE_PLUGINS, CoreProperties.PREVIEW_EXCLUDE_PLUGINS_DEFAULT_VALUE)); - } else { - blacks.addAll(propertyValues(settings, - CoreProperties.PREVIEW_EXCLUDE_PLUGINS, CoreProperties.PREVIEW_EXCLUDE_PLUGINS_DEFAULT_VALUE)); - } - } - if (!whites.isEmpty()) { - LOG.info("Include plugins: " + Joiner.on(", ").join(whites)); - } - if (!blacks.isEmpty()) { - LOG.info("Exclude plugins: " + Joiner.on(", ").join(blacks)); - } - } - - static List<String> propertyValues(Settings settings, String key, String defaultValue) { - String s = StringUtils.defaultIfEmpty(settings.getString(key), defaultValue); - return Lists.newArrayList(Splitter.on(",").trimResults().split(s)); - } - - boolean accepts(String pluginKey) { - if (CORE_PLUGIN.equals(pluginKey)) { - return !mode.isMediumTest(); - } - - if (BUILDBREAKER_PLUGIN_KEY.equals(pluginKey) && mode.isPreview()) { - LOG.info("Build Breaker plugin is no more supported in preview/incremental mode"); - return false; - } - - List<String> mergeList = newArrayList(blacks); - mergeList.removeAll(whites); - return mergeList.isEmpty() || !mergeList.contains(pluginKey); - } + @Override + public boolean hasPlugin(String key) { + return infosByKeys.containsKey(key); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginUnzipper.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginUnzipper.java new file mode 100644 index 00000000000..29f554ddc89 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginUnzipper.java @@ -0,0 +1,77 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.bootstrap; + +import org.apache.commons.io.FileUtils; +import org.sonar.api.BatchComponent; +import org.sonar.api.utils.ZipUtils; +import org.sonar.core.platform.PluginInfo; +import org.sonar.core.platform.PluginUnzipper; +import org.sonar.core.platform.UnzippedPlugin; +import org.sonar.home.cache.FileCache; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +public class BatchPluginUnzipper extends PluginUnzipper implements BatchComponent { + + private final FileCache fileCache; + + public BatchPluginUnzipper(FileCache fileCache) { + this.fileCache = fileCache; + } + + @Override + public UnzippedPlugin unzip(PluginInfo info) { + try { + File dir = unzipFile(info.getFile()); + return UnzippedPlugin.createFromUnzippedDir(info.getKey(), info.getFile(), dir); + } catch (Exception e) { + throw new IllegalStateException(String.format("Fail to open plugin [%s]: %s", info.getKey(), info.getFile().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(); + FileUtils.deleteQuietly(lockFile); + } + } + return destDir; + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java index 86599f96774..165aa83e649 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java @@ -21,22 +21,22 @@ package org.sonar.batch.bootstrap; import org.sonar.api.ExtensionProvider; import org.sonar.api.Plugin; -import org.sonar.api.platform.ComponentContainer; -import org.sonar.api.platform.PluginMetadata; import org.sonar.batch.bootstrapper.EnvironmentInformation; +import org.sonar.core.platform.ComponentContainer; +import org.sonar.core.platform.PluginInfo; +import org.sonar.core.platform.PluginRepository; import javax.annotation.Nullable; import java.util.List; -import java.util.Map; public class ExtensionInstaller { - private final BatchPluginRepository pluginRepository; + private final PluginRepository pluginRepository; private final EnvironmentInformation env; private final DefaultAnalysisMode analysisMode; - public ExtensionInstaller(BatchPluginRepository pluginRepository, EnvironmentInformation env, DefaultAnalysisMode analysisMode) { + public ExtensionInstaller(PluginRepository pluginRepository, EnvironmentInformation env, DefaultAnalysisMode analysisMode) { this.pluginRepository = pluginRepository; this.env = env; this.analysisMode = analysisMode; @@ -50,11 +50,10 @@ public class ExtensionInstaller { } // plugin extensions - for (Map.Entry<PluginMetadata, Plugin> entry : pluginRepository.getPluginsByMetadata().entrySet()) { - PluginMetadata metadata = entry.getKey(); - Plugin plugin = entry.getValue(); + for (PluginInfo pluginInfo : pluginRepository.getPluginInfos()) { + Plugin plugin = pluginRepository.getPluginInstance(pluginInfo.getKey()); for (Object extension : plugin.getExtensions()) { - doInstall(container, matcher, metadata, extension); + doInstall(container, matcher, pluginInfo, extension); } } List<ExtensionProvider> providers = container.getComponentsByType(ExtensionProvider.class); @@ -71,13 +70,13 @@ public class ExtensionInstaller { return this; } - private void doInstall(ComponentContainer container, ExtensionMatcher matcher, @Nullable PluginMetadata metadata, Object extension) { + private void doInstall(ComponentContainer container, ExtensionMatcher matcher, @Nullable PluginInfo pluginInfo, Object extension) { if (ExtensionUtils.supportsEnvironment(extension, env) && (analysisMode.isDb() || !ExtensionUtils.requiresDB(extension)) && matcher.accept(extension)) { - container.addExtension(metadata, extension); + container.addExtension(pluginInfo, extension); } else { - container.declareExtension(metadata, extension); + container.declareExtension(pluginInfo, extension); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java index 7aaf0f6be32..09d217122af 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java @@ -21,28 +21,44 @@ package org.sonar.batch.bootstrap; import org.sonar.api.Plugin; import org.sonar.api.config.EmailSettings; -import org.sonar.api.platform.ComponentContainer; -import org.sonar.api.platform.PluginMetadata; import org.sonar.api.utils.Durations; -import org.sonar.core.util.DefaultHttpDownloader; import org.sonar.api.utils.System2; import org.sonar.api.utils.UriReader; import org.sonar.api.utils.internal.TempFolderCleaner; import org.sonar.batch.components.PastSnapshotFinder; -import org.sonar.batch.deprecated.components.*; +import org.sonar.batch.deprecated.components.PastSnapshotFinderByDate; +import org.sonar.batch.deprecated.components.PastSnapshotFinderByDays; +import org.sonar.batch.deprecated.components.PastSnapshotFinderByPreviousAnalysis; +import org.sonar.batch.deprecated.components.PastSnapshotFinderByPreviousVersion; +import org.sonar.batch.deprecated.components.PastSnapshotFinderByVersion; import org.sonar.batch.issue.tracking.DefaultServerLineHashesLoader; import org.sonar.batch.issue.tracking.ServerLineHashesLoader; import org.sonar.batch.platform.DefaultServer; -import org.sonar.batch.repository.*; +import org.sonar.batch.repository.DefaultGlobalRepositoriesLoader; +import org.sonar.batch.repository.DefaultProjectRepositoriesLoader; +import org.sonar.batch.repository.DefaultServerIssuesLoader; +import org.sonar.batch.repository.GlobalRepositoriesLoader; +import org.sonar.batch.repository.GlobalRepositoriesProvider; +import org.sonar.batch.repository.ProjectRepositoriesLoader; +import org.sonar.batch.repository.ServerIssuesLoader; import org.sonar.batch.repository.user.UserRepository; import org.sonar.core.cluster.NullQueue; import org.sonar.core.config.Logback; import org.sonar.core.i18n.DefaultI18n; import org.sonar.core.i18n.RuleI18nManager; -import org.sonar.core.persistence.*; +import org.sonar.core.persistence.DaoUtils; +import org.sonar.core.persistence.DatabaseVersion; +import org.sonar.core.persistence.MyBatis; +import org.sonar.core.persistence.SemaphoreUpdater; +import org.sonar.core.persistence.SemaphoresImpl; +import org.sonar.core.platform.ComponentContainer; +import org.sonar.core.platform.PluginInfo; +import org.sonar.core.platform.PluginLoader; +import org.sonar.core.platform.PluginRepository; import org.sonar.core.purge.PurgeProfiler; import org.sonar.core.rule.CacheRuleFinder; import org.sonar.core.user.HibernateUserFinder; +import org.sonar.core.util.DefaultHttpDownloader; import org.sonar.jpa.dao.MeasuresDao; import org.sonar.jpa.session.DefaultDatabaseConnector; import org.sonar.jpa.session.JpaDatabaseSession; @@ -79,11 +95,15 @@ public class GlobalContainer extends ComponentContainer { private void addBootstrapComponents() { add( + // plugins BatchPluginRepository.class, - BatchPluginJarInstaller.class, + PluginLoader.class, + BatchPluginUnzipper.class, + BatchPluginPredicate.class, + ExtensionInstaller.class, + GlobalSettings.class, ServerClient.class, - ExtensionInstaller.class, Logback.class, DefaultServer.class, new TempFolderProvider(), @@ -95,20 +115,16 @@ public class GlobalContainer extends ComponentContainer { DefaultI18n.class, new GlobalRepositoriesProvider(), UserRepository.class); - if (getComponentByType(PluginsRepository.class) == null) { - add(DefaultPluginsRepository.class); - } - if (getComponentByType(GlobalRepositoriesLoader.class) == null) { - add(DefaultGlobalRepositoriesLoader.class); - } - if (getComponentByType(ProjectRepositoriesLoader.class) == null) { - add(DefaultProjectRepositoriesLoader.class); - } - if (getComponentByType(ServerIssuesLoader.class) == null) { - add(DefaultServerIssuesLoader.class); - } - if (getComponentByType(ServerLineHashesLoader.class) == null) { - add(DefaultServerLineHashesLoader.class); + addIfMissing(BatchPluginInstaller.class, PluginInstaller.class); + addIfMissing(DefaultGlobalRepositoriesLoader.class, GlobalRepositoriesLoader.class); + addIfMissing(DefaultProjectRepositoriesLoader.class, ProjectRepositoriesLoader.class); + addIfMissing(DefaultServerIssuesLoader.class, ServerIssuesLoader.class); + addIfMissing(DefaultServerLineHashesLoader.class, ServerLineHashesLoader.class); + } + + public void addIfMissing(Object object, Class objectType) { + if (getComponentByType(objectType) == null) { + add(object); } } @@ -147,10 +163,10 @@ public class GlobalContainer extends ComponentContainer { } private void installPlugins() { - for (Map.Entry<PluginMetadata, Plugin> entry : getComponentByType(BatchPluginRepository.class).getPluginsByMetadata().entrySet()) { - PluginMetadata metadata = entry.getKey(); - Plugin plugin = entry.getValue(); - addExtension(metadata, plugin); + PluginRepository pluginRepository = getComponentByType(PluginRepository.class); + for (PluginInfo pluginInfo : pluginRepository.getPluginInfos()) { + Plugin instance = pluginRepository.getPluginInstance(pluginInfo.getKey()); + addExtension(pluginInfo, instance); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/PluginsRepository.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/PluginInstaller.java index 58473fd6af1..97eb513d4a6 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/PluginsRepository.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/PluginInstaller.java @@ -19,33 +19,24 @@ */ package org.sonar.batch.bootstrap; -import org.sonar.api.SonarPlugin; -import org.sonar.api.platform.PluginMetadata; -import org.sonar.core.plugins.RemotePlugin; +import org.sonar.api.BatchComponent; +import org.sonar.api.Plugin; +import org.sonar.core.platform.PluginInfo; -import java.io.File; -import java.util.List; import java.util.Map; -/** - * Plugin referential. - * @since 4.4 - */ -public interface PluginsRepository { +public interface PluginInstaller extends BatchComponent { /** - * Return list of remote plugins to be installed + * Gets the list of plugins installed on server and downloads them if not + * already in local cache. + * @return information about all installed plugins, grouped by key */ - List<RemotePlugin> pluginList(); + Map<String, PluginInfo> installRemotes(); /** - * Return location of a given plugin on the local FS. + * Used only by tests. + * @see org.sonar.batch.mediumtest.BatchMediumTester */ - File pluginFile(RemotePlugin remote); - - /** - * Return the list of local plugins to be installed - */ - Map<PluginMetadata, SonarPlugin> localPlugins(); - + Map<String, Plugin> installLocals(); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/TaskContainer.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/TaskContainer.java index b3fd7e46392..fce09a6cd1c 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/TaskContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/TaskContainer.java @@ -23,7 +23,7 @@ import org.sonar.batch.components.PastMeasuresLoader; import org.apache.commons.lang.StringUtils; import org.sonar.api.CoreProperties; -import org.sonar.api.platform.ComponentContainer; +import org.sonar.core.platform.ComponentContainer; import org.sonar.api.resources.ResourceTypes; import org.sonar.api.task.Task; import org.sonar.api.task.TaskComponent; diff --git a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java index e274375076b..09871955a38 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java +++ b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java @@ -28,27 +28,31 @@ import org.sonar.api.batch.bootstrap.ProjectReactor; import org.sonar.api.batch.debt.internal.DefaultDebtModel; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Metric; -import org.sonar.api.platform.PluginMetadata; -import org.sonar.batch.bootstrap.PluginsRepository; import org.sonar.batch.bootstrap.TaskProperties; import org.sonar.batch.bootstrapper.Batch; import org.sonar.batch.bootstrapper.EnvironmentInformation; import org.sonar.batch.issue.tracking.ServerLineHashesLoader; -import org.sonar.batch.protocol.input.*; +import org.sonar.batch.protocol.input.ActiveRule; import org.sonar.batch.protocol.input.BatchInput.ServerIssue; +import org.sonar.batch.protocol.input.FileData; +import org.sonar.batch.protocol.input.GlobalRepositories; +import org.sonar.batch.protocol.input.ProjectRepositories; import org.sonar.batch.report.ReportPublisher; import org.sonar.batch.repository.GlobalRepositoriesLoader; import org.sonar.batch.repository.ProjectRepositoriesLoader; import org.sonar.batch.repository.ServerIssuesLoader; import org.sonar.core.component.ComponentKeys; -import org.sonar.core.plugins.DefaultPluginMetadata; -import org.sonar.core.plugins.RemotePlugin; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; import java.io.Reader; -import java.util.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; /** * Main utility class for writing batch medium tests. @@ -70,22 +74,22 @@ public class BatchMediumTester { public static class BatchMediumTesterBuilder { private final FakeGlobalRepositoriesLoader globalRefProvider = new FakeGlobalRepositoriesLoader(); private final FakeProjectRepositoriesLoader projectRefProvider = new FakeProjectRepositoriesLoader(); - private final FakePluginsRepository pluginsReferential = new FakePluginsRepository(); + private final FakePluginInstaller pluginInstaller = new FakePluginInstaller(); private final FakeServerIssuesLoader serverIssues = new FakeServerIssuesLoader(); private final FakeServerLineHashesLoader serverLineHashes = new FakeServerLineHashesLoader(); - private final Map<String, String> bootstrapProperties = new HashMap<String, String>(); + private final Map<String, String> bootstrapProperties = new HashMap<>(); public BatchMediumTester build() { return new BatchMediumTester(this); } public BatchMediumTesterBuilder registerPlugin(String pluginKey, File location) { - pluginsReferential.addPlugin(pluginKey, location); + pluginInstaller.add(pluginKey, location); return this; } public BatchMediumTesterBuilder registerPlugin(String pluginKey, SonarPlugin instance) { - pluginsReferential.addPlugin(pluginKey, instance); + pluginInstaller.add(pluginKey, instance); return this; } @@ -164,7 +168,7 @@ public class BatchMediumTester { .setEnableLoggingConfiguration(true) .addComponents( new EnvironmentInformation("mediumTest", "1.0"), - builder.pluginsReferential, + builder.pluginInstaller, builder.globalRefProvider, builder.projectRefProvider, builder.serverIssues, @@ -280,41 +284,6 @@ public class BatchMediumTester { } - private static class FakePluginsRepository implements PluginsRepository { - - private List<RemotePlugin> pluginList = new ArrayList<RemotePlugin>(); - private Map<RemotePlugin, File> pluginFiles = new HashMap<RemotePlugin, File>(); - Map<PluginMetadata, SonarPlugin> localPlugins = new HashMap<PluginMetadata, SonarPlugin>(); - - @Override - public List<RemotePlugin> pluginList() { - return pluginList; - } - - @Override - public File pluginFile(RemotePlugin remote) { - return pluginFiles.get(remote); - } - - public FakePluginsRepository addPlugin(String pluginKey, File location) { - RemotePlugin plugin = new RemotePlugin(pluginKey, false); - pluginList.add(plugin); - pluginFiles.put(plugin, location); - return this; - } - - public FakePluginsRepository addPlugin(String pluginKey, SonarPlugin pluginInstance) { - localPlugins.put(DefaultPluginMetadata.create(pluginKey), pluginInstance); - return this; - } - - @Override - public Map<PluginMetadata, SonarPlugin> localPlugins() { - return localPlugins; - } - - } - private static class FakeServerIssuesLoader implements ServerIssuesLoader { private List<ServerIssue> serverIssues = new ArrayList<>(); diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginJarInstaller.java b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/FakePluginInstaller.java index 8866cf7fc0f..cbd837c66c9 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginJarInstaller.java +++ b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/FakePluginInstaller.java @@ -17,33 +17,38 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.batch.bootstrap; +package org.sonar.batch.mediumtest; -import org.sonar.api.BatchComponent; -import org.sonar.core.plugins.DefaultPluginMetadata; -import org.sonar.core.plugins.PluginJarInstaller; -import org.sonar.home.cache.FileCache; +import org.sonar.api.Plugin; +import org.sonar.batch.bootstrap.PluginInstaller; +import org.sonar.core.platform.PluginInfo; import java.io.File; -import java.io.IOException; +import java.util.HashMap; +import java.util.Map; -public class BatchPluginJarInstaller extends PluginJarInstaller implements BatchComponent { +public class FakePluginInstaller implements PluginInstaller { - private FileCache cache; + private final Map<String, PluginInfo> infosByKeys = new HashMap<>(); + private final Map<String, Plugin> instancesByKeys = new HashMap<>(); - public BatchPluginJarInstaller(FileCache cache) { - this.cache = cache; + public FakePluginInstaller add(String pluginKey, File jarFile) { + infosByKeys.put(pluginKey, PluginInfo.create(jarFile)); + return this; } - public DefaultPluginMetadata installToCache(File pluginFile, boolean isCore) { - DefaultPluginMetadata metadata = extractMetadata(pluginFile, isCore); - install(metadata, null, pluginFile); - return metadata; + public FakePluginInstaller add(String pluginKey, Plugin instance) { + instancesByKeys.put(pluginKey, instance); + return this; } @Override - protected File extractPluginDependencies(File pluginFile, File pluginBasedir) throws IOException { - return cache.unzip(pluginFile); + public Map<String, PluginInfo> installRemotes() { + return infosByKeys; } + @Override + public Map<String, Plugin> installLocals() { + return instancesByKeys; + } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java index 75281a9e961..f8312429543 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java @@ -27,7 +27,7 @@ import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.batch.fs.internal.FileMetadata; import org.sonar.api.batch.rule.CheckFactory; import org.sonar.api.checks.NoSonarFilter; -import org.sonar.api.platform.ComponentContainer; +import org.sonar.core.platform.ComponentContainer; import org.sonar.api.resources.Project; import org.sonar.api.scan.filesystem.FileExclusions; import org.sonar.batch.ProjectTree; diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java index ebf3d5c2d87..12a23bf62e4 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java @@ -26,7 +26,7 @@ import org.sonar.api.batch.InstantiationStrategy; import org.sonar.api.batch.bootstrap.ProjectBootstrapper; import org.sonar.api.batch.bootstrap.ProjectReactor; import org.sonar.api.config.Settings; -import org.sonar.api.platform.ComponentContainer; +import org.sonar.core.platform.ComponentContainer; import org.sonar.api.resources.Languages; import org.sonar.api.resources.Project; import org.sonar.api.scan.filesystem.PathResolver; diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ScanTask.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ScanTask.java index 0064d028ea8..bb3f0f8a021 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ScanTask.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ScanTask.java @@ -20,7 +20,7 @@ package org.sonar.batch.scan; import org.sonar.api.CoreProperties; -import org.sonar.api.platform.ComponentContainer; +import org.sonar.core.platform.ComponentContainer; import org.sonar.api.task.Task; import org.sonar.api.task.TaskDefinition; import org.sonar.batch.DefaultProjectTree; diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchExtensionDictionnaryTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchExtensionDictionnaryTest.java index 14fde3895ef..6f7e0c11e32 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchExtensionDictionnaryTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchExtensionDictionnaryTest.java @@ -24,7 +24,7 @@ import org.junit.Test; import org.sonar.api.BatchExtension; import org.sonar.api.batch.*; import org.sonar.api.batch.postjob.PostJobContext; -import org.sonar.api.platform.ComponentContainer; +import org.sonar.core.platform.ComponentContainer; import org.sonar.api.resources.Project; import org.sonar.batch.postjob.PostJobOptimizer; import org.sonar.batch.sensor.DefaultSensorContext; diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/DefaultPluginsRepositoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginInstallerTest.java index 57e940ab7ae..03c3707919b 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/DefaultPluginsRepositoryTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginInstallerTest.java @@ -36,7 +36,7 @@ import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -public class DefaultPluginsRepositoryTest { +public class BatchPluginInstallerTest { @Rule public TemporaryFolder temp = new TemporaryFolder(); @@ -44,34 +44,30 @@ public class DefaultPluginsRepositoryTest { @Rule public ExpectedException thrown = ExpectedException.none(); + FileCache fileCache = mock(FileCache.class); + BatchPluginPredicate pluginPredicate = mock(BatchPluginPredicate.class); + @Test - public void should_request_list_of_plugins() { - FileCache cache = mock(FileCache.class); + public void listRemotePlugins() { + ServerClient server = mock(ServerClient.class); - when(server.request("/deploy/plugins/index.txt")).thenReturn("checkstyle,true\nsqale,false"); - DefaultPluginsRepository downloader = new DefaultPluginsRepository(cache, server); - - List<RemotePlugin> plugins = downloader.pluginList(); - assertThat(plugins).hasSize(2); - assertThat(plugins.get(0).getKey()).isEqualTo("checkstyle"); - assertThat(plugins.get(0).isCore()).isTrue(); - assertThat(plugins.get(1).getKey()).isEqualTo("sqale"); - assertThat(plugins.get(1).isCore()).isFalse(); + when(server.request("/deploy/plugins/index.txt")).thenReturn("checkstyle,false\nsqale,false"); + BatchPluginInstaller installer = new BatchPluginInstaller(server, fileCache, pluginPredicate); + + List<RemotePlugin> remotePlugins = installer.listRemotePlugins(); + assertThat(remotePlugins).extracting("key").containsOnly("checkstyle", "sqale"); } @Test public void should_download_plugin() throws Exception { - FileCache cache = mock(FileCache.class); - File pluginJar = temp.newFile(); - when(cache.get(eq("checkstyle-plugin.jar"), eq("fakemd5_1"), any(FileCache.Downloader.class))).thenReturn(pluginJar); + when(fileCache.get(eq("checkstyle-plugin.jar"), eq("fakemd5_1"), any(FileCache.Downloader.class))).thenReturn(pluginJar); ServerClient server = mock(ServerClient.class); - DefaultPluginsRepository downloader = new DefaultPluginsRepository(cache, server); + BatchPluginInstaller installer = new BatchPluginInstaller(server, fileCache, pluginPredicate); - RemotePlugin plugin = new RemotePlugin("checkstyle", true) - .setFile("checkstyle-plugin.jar", "fakemd5_1"); - File file = downloader.pluginFile(plugin); + RemotePlugin remote = new RemotePlugin("checkstyle", true).setFile("checkstyle-plugin.jar", "fakemd5_1"); + File file = installer.download(remote); assertThat(file).isEqualTo(pluginJar); } @@ -83,6 +79,6 @@ public class DefaultPluginsRepositoryTest { ServerClient server = mock(ServerClient.class); doThrow(new IllegalStateException()).when(server).request("/deploy/plugins/index.txt"); - new DefaultPluginsRepository(mock(FileCache.class), server).pluginList(); + new BatchPluginInstaller(server, fileCache, pluginPredicate).installRemotes(); } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginPredicateTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginPredicateTest.java new file mode 100644 index 00000000000..9dcebd6d07f --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginPredicateTest.java @@ -0,0 +1,157 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.bootstrap; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sonar.api.CoreProperties; +import org.sonar.api.config.Settings; +import org.sonar.home.cache.FileCache; +import org.sonar.home.cache.FileCacheBuilder; + +import java.io.File; +import java.io.IOException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class BatchPluginPredicateTest { + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + DefaultAnalysisMode mode = mock(DefaultAnalysisMode.class); + FileCache cache; + File userHome; + + @Before + public void before() throws IOException { + userHome = temp.newFolder(); + cache = new FileCacheBuilder().setUserHome(userHome).build(); + } + + @Test + public void shouldAlwaysAcceptIfNoWhiteListAndBlackList() { + BatchPluginPredicate predicate = new BatchPluginPredicate(new Settings(), mode); + assertThat(predicate.apply("pmd")).isTrue(); + assertThat(predicate.apply("buildbreaker")).isTrue(); + } + + @Test + public void shouldBlackListBuildBreakerInPreviewMode() { + when(mode.isPreview()).thenReturn(true); + BatchPluginPredicate predicate = new BatchPluginPredicate(new Settings(), mode); + assertThat(predicate.apply("buildbreaker")).isFalse(); + } + + @Test + public void whiteListShouldTakePrecedenceOverBlackList() { + Settings settings = new Settings() + .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs") + .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura,pmd"); + BatchPluginPredicate predicate = new BatchPluginPredicate(settings, mode); + assertThat(predicate.apply("pmd")).isTrue(); + } + + @Test + public void corePluginShouldAlwaysBeInWhiteList() { + Settings settings = new Settings() + .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs"); + BatchPluginPredicate predicate = new BatchPluginPredicate(settings, mode); + assertThat(predicate.apply("core")).isTrue(); + } + + @Test + public void corePluginShouldNeverBeInBlackList() { + Settings settings = new Settings() + .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "core,findbugs"); + BatchPluginPredicate predicate = new BatchPluginPredicate(settings, mode); + assertThat(predicate.apply("core")).isTrue(); + } + + @Test + public void check_white_list_with_black_list() { + Settings settings = new Settings() + .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs") + .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura"); + BatchPluginPredicate predicate = new BatchPluginPredicate(settings, mode); + assertThat(predicate.apply("checkstyle")).isTrue(); + assertThat(predicate.apply("pmd")).isTrue(); + assertThat(predicate.apply("cobertura")).isFalse(); + } + + @Test + public void check_white_list_when_plugin_is_in_both_list() { + Settings settings = new Settings() + .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "cobertura,checkstyle,pmd,findbugs") + .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura"); + BatchPluginPredicate predicate = new BatchPluginPredicate(settings, mode); + assertThat(predicate.apply("checkstyle")).isTrue(); + assertThat(predicate.apply("pmd")).isTrue(); + assertThat(predicate.apply("cobertura")).isTrue(); + } + + @Test + public void check_black_list_if_no_white_list() { + Settings settings = new Settings() + .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd,findbugs"); + BatchPluginPredicate predicate = new BatchPluginPredicate(settings, mode); + assertThat(predicate.apply("checkstyle")).isFalse(); + assertThat(predicate.apply("pmd")).isFalse(); + assertThat(predicate.apply("cobertura")).isTrue(); + } + + @Test + public void should_concatenate_preview_predicates() { + Settings settings = new Settings() + .setProperty(CoreProperties.PREVIEW_INCLUDE_PLUGINS, "cockpit") + .setProperty(CoreProperties.PREVIEW_EXCLUDE_PLUGINS, "views") + .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd"); + when(mode.isPreview()).thenReturn(true); + BatchPluginPredicate predicate = new BatchPluginPredicate(settings, mode); + assertThat(predicate.getWhites()).containsOnly("cockpit"); + assertThat(predicate.getBlacks()).containsOnly("views", "checkstyle", "pmd"); + } + + @Test + public void should_concatenate_deprecated_dry_run_predicates() { + Settings settings = new Settings() + .setProperty(CoreProperties.DRY_RUN_INCLUDE_PLUGINS, "cockpit") + .setProperty(CoreProperties.DRY_RUN_EXCLUDE_PLUGINS, "views") + .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd"); + when(mode.isPreview()).thenReturn(true); + BatchPluginPredicate predicate = new BatchPluginPredicate(settings, mode); + assertThat(predicate.getWhites()).containsOnly("cockpit"); + assertThat(predicate.getBlacks()).containsOnly("views", "checkstyle", "pmd"); + } + + @Test + public void inclusions_and_exclusions_should_be_trimmed() { + Settings settings = new Settings() + .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle, pmd, findbugs") + .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura, pmd"); + BatchPluginPredicate predicate = new BatchPluginPredicate(settings, mode); + assertThat(predicate.apply("pmd")).isTrue(); + } + +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginRepositoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginRepositoryTest.java index 66a499b01c0..7c82edbb64f 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginRepositoryTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginRepositoryTest.java @@ -17,219 +17,237 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.batch.bootstrap; - -import com.google.common.io.Resources; -import org.apache.commons.io.FileUtils; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.sonar.api.CoreProperties; -import org.sonar.api.config.Settings; -import org.sonar.core.plugins.RemotePlugin; -import org.sonar.home.cache.FileCache; -import org.sonar.home.cache.FileCacheBuilder; - -import java.io.File; -import java.io.IOException; -import java.util.Arrays; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class BatchPluginRepositoryTest { - - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - - private BatchPluginRepository repository; - private DefaultAnalysisMode mode; - private FileCache cache; - private File userHome; - - @Before - public void before() throws IOException { - mode = mock(DefaultAnalysisMode.class); - when(mode.isPreview()).thenReturn(false); - userHome = temp.newFolder(); - cache = new FileCacheBuilder().setUserHome(userHome).build(); - } - - @After - public void tearDown() { - if (repository != null) { - repository.stop(); - } - } - - @Test - public void shouldLoadPlugin() throws Exception { - RemotePlugin checkstyle = new RemotePlugin("checkstyle", true); - - DefaultPluginsRepository downloader = mock(DefaultPluginsRepository.class); - when(downloader.pluginFile(checkstyle)).thenReturn(fileFromCache("sonar-checkstyle-plugin-2.8.jar")); - - repository = new BatchPluginRepository(downloader, new Settings(), mode, new BatchPluginJarInstaller(cache)); - - repository.doStart(Arrays.asList(checkstyle)); - - assertThat(repository.getPlugin("checkstyle")).isNotNull(); - assertThat(repository.getMetadata()).hasSize(1); - assertThat(repository.getMetadata("checkstyle").getName()).isEqualTo("Checkstyle"); - assertThat(repository.getMetadata("checkstyle").getDeployedFiles()).hasSize(4); // plugin + 3 dependencies - } - - @Test - public void shouldLoadPluginExtension() throws Exception { - RemotePlugin checkstyle = new RemotePlugin("checkstyle", true); - RemotePlugin checkstyleExt = new RemotePlugin("checkstyleextensions", false); - - DefaultPluginsRepository downloader = mock(DefaultPluginsRepository.class); - when(downloader.pluginFile(checkstyle)).thenReturn(fileFromCache("sonar-checkstyle-plugin-2.8.jar")); - when(downloader.pluginFile(checkstyleExt)).thenReturn(fileFromCache("sonar-checkstyle-extensions-plugin-0.1-SNAPSHOT.jar")); - - repository = new BatchPluginRepository(downloader, new Settings(), mode, new BatchPluginJarInstaller(cache)); - - repository.doStart(Arrays.asList(checkstyle, checkstyleExt)); - - assertThat(repository.getPlugin("checkstyle")).isNotNull(); - assertThat(repository.getPlugin("checkstyleextensions")).isNotNull(); - assertThat(repository.getMetadata()).hasSize(2); - assertThat(repository.getMetadata("checkstyle").getName()).isEqualTo("Checkstyle"); - assertThat(repository.getMetadata("checkstyleextensions").getVersion()).isEqualTo("0.1-SNAPSHOT"); - } - - @Test - public void shouldExcludePluginAndItsExtensions() throws Exception { - RemotePlugin checkstyle = new RemotePlugin("checkstyle", true); - RemotePlugin checkstyleExt = new RemotePlugin("checkstyleextensions", false); - - DefaultPluginsRepository downloader = mock(DefaultPluginsRepository.class); - when(downloader.pluginFile(checkstyle)).thenReturn(fileFromCache("sonar-checkstyle-plugin-2.8.jar")); - when(downloader.pluginFile(checkstyleExt)).thenReturn(fileFromCache("sonar-checkstyle-extensions-plugin-0.1-SNAPSHOT.jar")); - - Settings settings = new Settings(); - settings.setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle"); - repository = new BatchPluginRepository(downloader, settings, mode, new BatchPluginJarInstaller(cache)); - - repository.doStart(Arrays.asList(checkstyle, checkstyleExt)); - - assertThat(repository.getMetadata()).isEmpty(); - } - - private File fileFromCache(String filename) throws Exception { - File file = new File(Resources.getResource("org/sonar/batch/bootstrap/BatchPluginRepositoryTest/" + filename).toURI()); - File destDir = new File(userHome, "cache/foomd5"); - FileUtils.forceMkdir(destDir); - FileUtils.copyFileToDirectory(file, destDir); - return new File(destDir, filename); - } - - @Test - public void shouldAlwaysAcceptIfNoWhiteListAndBlackList() { - BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(new Settings(), mode); - assertThat(filter.accepts("pmd")).isTrue(); - assertThat(filter.accepts("buildbreaker")).isTrue(); - } - - @Test - public void shouldBlackListBuildBreakerInPreviewMode() { - when(mode.isPreview()).thenReturn(true); - BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(new Settings(), mode); - assertThat(filter.accepts("buildbreaker")).isFalse(); - } - - @Test - public void whiteListShouldTakePrecedenceOverBlackList() { - Settings settings = new Settings() - .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs") - .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura,pmd"); - BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); - assertThat(filter.accepts("pmd")).isTrue(); - } - - @Test - public void corePluginShouldAlwaysBeInWhiteList() { - Settings settings = new Settings() - .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs"); - BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); - assertThat(filter.accepts("core")).isTrue(); - } - - @Test - public void corePluginShouldNeverBeInBlackList() { - Settings settings = new Settings() - .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "core,findbugs"); - BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); - assertThat(filter.accepts("core")).isTrue(); - } - - @Test - public void check_white_list_with_black_list() { - Settings settings = new Settings() - .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs") - .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura"); - BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); - assertThat(filter.accepts("checkstyle")).isTrue(); - assertThat(filter.accepts("pmd")).isTrue(); - assertThat(filter.accepts("cobertura")).isFalse(); - } - - @Test - public void check_white_list_when_plugin_is_in_both_list() { - Settings settings = new Settings() - .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "cobertura,checkstyle,pmd,findbugs") - .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura"); - BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); - assertThat(filter.accepts("checkstyle")).isTrue(); - assertThat(filter.accepts("pmd")).isTrue(); - assertThat(filter.accepts("cobertura")).isTrue(); - } - - @Test - public void check_black_list_if_no_white_list() { - Settings settings = new Settings() - .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd,findbugs"); - BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); - assertThat(filter.accepts("checkstyle")).isFalse(); - assertThat(filter.accepts("pmd")).isFalse(); - assertThat(filter.accepts("cobertura")).isTrue(); - } - - @Test - public void should_concatenate_preview_filters() { - Settings settings = new Settings() - .setProperty(CoreProperties.PREVIEW_INCLUDE_PLUGINS, "cockpit") - .setProperty(CoreProperties.PREVIEW_EXCLUDE_PLUGINS, "views") - .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd"); - when(mode.isPreview()).thenReturn(true); - BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); - assertThat(filter.whites).containsOnly("cockpit"); - assertThat(filter.blacks).containsOnly("views", "checkstyle", "pmd"); - } - - @Test - public void should_concatenate_deprecated_dry_run_filters() { - Settings settings = new Settings() - .setProperty(CoreProperties.DRY_RUN_INCLUDE_PLUGINS, "cockpit") - .setProperty(CoreProperties.DRY_RUN_EXCLUDE_PLUGINS, "views") - .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd"); - when(mode.isPreview()).thenReturn(true); - BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); - assertThat(filter.whites).containsOnly("cockpit"); - assertThat(filter.blacks).containsOnly("views", "checkstyle", "pmd"); - } - - @Test - public void inclusions_and_exclusions_should_be_trimmed() { - Settings settings = new Settings() - .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle, pmd, findbugs") - .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura, pmd"); - BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); - assertThat(filter.accepts("pmd")).isTrue(); - } - -} +///* +// * SonarQube, open source software quality management tool. +// * Copyright (C) 2008-2014 SonarSource +// * mailto:contact AT sonarsource DOT com +// * +// * SonarQube 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. +// * +// * SonarQube is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// * Lesser General Public License for more details. +// * +// * You should have received a copy of the GNU Lesser General Public License +// * along with this program; if not, write to the Free Software Foundation, +// * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// */ +//package org.sonar.batch.bootstrap; +// +//import com.google.common.io.Resources; +//import org.apache.commons.io.FileUtils; +//import org.junit.After; +//import org.junit.Before; +//import org.junit.Rule; +//import org.junit.Test; +//import org.junit.rules.TemporaryFolder; +//import org.sonar.api.CoreProperties; +//import org.sonar.api.config.Settings; +//import org.sonar.core.plugins.RemotePlugin; +//import org.sonar.home.cache.FileCache; +//import org.sonar.home.cache.FileCacheBuilder; +// +//import java.io.File; +//import java.io.IOException; +//import java.util.Arrays; +// +//import static org.mockito.Mockito.mock; +//import static org.mockito.Mockito.when; +// +//public class BatchPluginRepositoryTest { +// +// @Rule +// public TemporaryFolder temp = new TemporaryFolder(); +// +// private BatchPluginRepository repository; +// private DefaultAnalysisMode mode; +// private FileCache cache; +// private File userHome; +// +// @Before +// public void before() throws IOException { +// mode = mock(DefaultAnalysisMode.class); +// when(mode.isPreview()).thenReturn(false); +// userHome = temp.newFolder(); +// cache = new FileCacheBuilder().setUserHome(userHome).build(); +// } +// +// @After +// public void tearDown() { +// if (repository != null) { +// repository.stop(); +// } +// } +// +// @Test +// public void shouldLoadPlugin() throws Exception { +// RemotePlugin checkstyle = new RemotePlugin("checkstyle", true); +// +// DefaultPluginRepository installer = mock(DefaultPluginsRepository.class); +// when(installer.pluginFile(checkstyle)).thenReturn(fileFromCache("sonar-checkstyle-plugin-2.8.jar")); +// +// repository = new BatchPluginRepository(installer, new Settings(), mode, new BatchPluginJarInstaller(cache)); +// +// repository.doStart(Arrays.asList(checkstyle)); +// +// assertThat(repository.getPlugin("checkstyle")).isNotNull(); +// assertThat(repository.getMetadata()).hasSize(1); +// assertThat(repository.getMetadata("checkstyle").getName()).isEqualTo("Checkstyle"); +// assertThat(repository.getMetadata("checkstyle").getDeployedFiles()).hasSize(4); // plugin + 3 dependencies +// } +// +// @Test +// public void shouldLoadPluginExtension() throws Exception { +// RemotePlugin checkstyle = new RemotePlugin("checkstyle", true); +// RemotePlugin checkstyleExt = new RemotePlugin("checkstyleextensions", false); +// +// DefaultPluginsRepository downloader = mock(DefaultPluginsRepository.class); +// when(downloader.pluginFile(checkstyle)).thenReturn(fileFromCache("sonar-checkstyle-plugin-2.8.jar")); +// when(downloader.pluginFile(checkstyleExt)).thenReturn(fileFromCache("sonar-checkstyle-extensions-plugin-0.1-SNAPSHOT.jar")); +// +// repository = new BatchPluginRepository(downloader, new Settings(), mode, new BatchPluginJarInstaller(cache)); +// +// repository.doStart(Arrays.asList(checkstyle, checkstyleExt)); +// +// assertThat(repository.getPlugin("checkstyle")).isNotNull(); +// assertThat(repository.getPlugin("checkstyleextensions")).isNotNull(); +// assertThat(repository.getMetadata()).hasSize(2); +// assertThat(repository.getMetadata("checkstyle").getName()).isEqualTo("Checkstyle"); +// assertThat(repository.getMetadata("checkstyleextensions").getVersion()).isEqualTo("0.1-SNAPSHOT"); +// } +// +// @Test +// public void shouldExcludePluginAndItsExtensions() throws Exception { +// RemotePlugin checkstyle = new RemotePlugin("checkstyle", true); +// RemotePlugin checkstyleExt = new RemotePlugin("checkstyleextensions", false); +// +// DefaultPluginsRepository downloader = mock(DefaultPluginsRepository.class); +// when(downloader.pluginFile(checkstyle)).thenReturn(fileFromCache("sonar-checkstyle-plugin-2.8.jar")); +// when(downloader.pluginFile(checkstyleExt)).thenReturn(fileFromCache("sonar-checkstyle-extensions-plugin-0.1-SNAPSHOT.jar")); +// +// Settings settings = new Settings(); +// settings.setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle"); +// repository = new BatchPluginRepository(downloader, settings, mode, new BatchPluginJarInstaller(cache)); +// +// repository.doStart(Arrays.asList(checkstyle, checkstyleExt)); +// +// assertThat(repository.getMetadata()).isEmpty(); +// } +// +// private File fileFromCache(String filename) throws Exception { +// File file = new File(Resources.getResource("org/sonar/batch/bootstrap/BatchPluginRepositoryTest/" + filename).toURI()); +// File destDir = new File(userHome, "cache/foomd5"); +// FileUtils.forceMkdir(destDir); +// FileUtils.copyFileToDirectory(file, destDir); +// return new File(destDir, filename); +// } +// +// @Test +// public void shouldAlwaysAcceptIfNoWhiteListAndBlackList() { +// BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(new Settings(), mode); +// assertThat(filter.accepts("pmd")).isTrue(); +// assertThat(filter.accepts("buildbreaker")).isTrue(); +// } +// +// @Test +// public void shouldBlackListBuildBreakerInPreviewMode() { +// when(mode.isPreview()).thenReturn(true); +// BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(new Settings(), mode); +// assertThat(filter.accepts("buildbreaker")).isFalse(); +// } +// +// @Test +// public void whiteListShouldTakePrecedenceOverBlackList() { +// Settings settings = new Settings() +// .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs") +// .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura,pmd"); +// BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); +// assertThat(filter.accepts("pmd")).isTrue(); +// } +// +// @Test +// public void corePluginShouldAlwaysBeInWhiteList() { +// Settings settings = new Settings() +// .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs"); +// BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); +// assertThat(filter.accepts("core")).isTrue(); +// } +// +// @Test +// public void corePluginShouldNeverBeInBlackList() { +// Settings settings = new Settings() +// .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "core,findbugs"); +// BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); +// assertThat(filter.accepts("core")).isTrue(); +// } +// +// @Test +// public void check_white_list_with_black_list() { +// Settings settings = new Settings() +// .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs") +// .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura"); +// BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); +// assertThat(filter.accepts("checkstyle")).isTrue(); +// assertThat(filter.accepts("pmd")).isTrue(); +// assertThat(filter.accepts("cobertura")).isFalse(); +// } +// +// @Test +// public void check_white_list_when_plugin_is_in_both_list() { +// Settings settings = new Settings() +// .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "cobertura,checkstyle,pmd,findbugs") +// .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura"); +// BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); +// assertThat(filter.accepts("checkstyle")).isTrue(); +// assertThat(filter.accepts("pmd")).isTrue(); +// assertThat(filter.accepts("cobertura")).isTrue(); +// } +// +// @Test +// public void check_black_list_if_no_white_list() { +// Settings settings = new Settings() +// .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd,findbugs"); +// BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); +// assertThat(filter.accepts("checkstyle")).isFalse(); +// assertThat(filter.accepts("pmd")).isFalse(); +// assertThat(filter.accepts("cobertura")).isTrue(); +// } +// +// @Test +// public void should_concatenate_preview_filters() { +// Settings settings = new Settings() +// .setProperty(CoreProperties.PREVIEW_INCLUDE_PLUGINS, "cockpit") +// .setProperty(CoreProperties.PREVIEW_EXCLUDE_PLUGINS, "views") +// .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd"); +// when(mode.isPreview()).thenReturn(true); +// BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); +// assertThat(filter.whites).containsOnly("cockpit"); +// assertThat(filter.blacks).containsOnly("views", "checkstyle", "pmd"); +// } +// +// @Test +// public void should_concatenate_deprecated_dry_run_filters() { +// Settings settings = new Settings() +// .setProperty(CoreProperties.DRY_RUN_INCLUDE_PLUGINS, "cockpit") +// .setProperty(CoreProperties.DRY_RUN_EXCLUDE_PLUGINS, "views") +// .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd"); +// when(mode.isPreview()).thenReturn(true); +// BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); +// assertThat(filter.whites).containsOnly("cockpit"); +// assertThat(filter.blacks).containsOnly("views", "checkstyle", "pmd"); +// } +// +// @Test +// public void inclusions_and_exclusions_should_be_trimmed() { +// Settings settings = new Settings() +// .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle, pmd, findbugs") +// .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura, pmd"); +// BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode); +// assertThat(filter.accepts("pmd")).isTrue(); +// } +// +//} diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginJarInstallerTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginUnzipperTest.java index 2209c57431a..06a25148775 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginJarInstallerTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginUnzipperTest.java @@ -24,7 +24,9 @@ import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; import org.junit.rules.TemporaryFolder; -import org.sonar.core.plugins.DefaultPluginMetadata; +import org.sonar.core.platform.PluginInfo; +import org.sonar.core.platform.UnzippedPlugin; +import org.sonar.home.cache.FileCache; import org.sonar.home.cache.FileCacheBuilder; import java.io.File; @@ -32,35 +34,37 @@ import java.io.IOException; import static org.assertj.core.api.Assertions.assertThat; -public class BatchPluginJarInstallerTest { - - private BatchPluginJarInstaller extractor; +public class BatchPluginUnzipperTest { @ClassRule - public static TemporaryFolder temporaryFolder = new TemporaryFolder(); + public static TemporaryFolder temp = new TemporaryFolder(); - private File userHome; + File userHome; + BatchPluginUnzipper underTest; @Before public void setUp() throws IOException { - userHome = temporaryFolder.newFolder(); - extractor = new BatchPluginJarInstaller(new FileCacheBuilder().setUserHome(userHome).build()); + userHome = temp.newFolder(); + FileCache fileCache = new FileCacheBuilder().setUserHome(userHome).build(); + underTest = new BatchPluginUnzipper(fileCache); } @Test - public void should_copy_and_extract_dependencies() throws IOException { + public void copy_and_extract_libs() throws IOException { File fileFromCache = getFileFromCache("sonar-checkstyle-plugin-2.8.jar"); - DefaultPluginMetadata metadata = extractor.installToCache(fileFromCache, true); + UnzippedPlugin unzipped = underTest.unzip(PluginInfo.create(fileFromCache)); - assertThat(metadata.getKey()).isEqualTo("checkstyle"); + assertThat(unzipped.getKey()).isEqualTo("checkstyle"); + assertThat(unzipped.getMain()).isFile().exists(); + assertThat(unzipped.getLibs()).extracting("name").containsOnly("antlr-2.7.6.jar", "checkstyle-5.1.jar", "commons-cli-1.0.jar"); assertThat(new File(fileFromCache.getParent(), "sonar-checkstyle-plugin-2.8.jar")).exists(); assertThat(new File(fileFromCache.getParent(), "sonar-checkstyle-plugin-2.8.jar_unzip/META-INF/lib/checkstyle-5.1.jar")).exists(); } @Test - public void should_extract_only_dependencies() throws IOException { + public void extract_only_libs() throws IOException { File fileFromCache = getFileFromCache("sonar-checkstyle-plugin-2.8.jar"); - extractor.installToCache(fileFromCache, true); + underTest.unzip(PluginInfo.create(fileFromCache)); assertThat(new File(fileFromCache.getParent(), "sonar-checkstyle-plugin-2.8.jar")).exists(); assertThat(new File(fileFromCache.getParent(), "sonar-checkstyle-plugin-2.8.jar_unzip/META-INF/MANIFEST.MF")).doesNotExist(); @@ -68,7 +72,7 @@ public class BatchPluginJarInstallerTest { } File getFileFromCache(String filename) throws IOException { - File src = FileUtils.toFile(BatchPluginJarInstallerTest.class.getResource("/org/sonar/batch/bootstrap/BatchPluginJarInstallerTest/" + filename)); + File src = FileUtils.toFile(BatchPluginUnzipperTest.class.getResource("/org/sonar/batch/bootstrap/BatchPluginUnzipperTest/" + filename)); File destFile = new File(new File(userHome, "" + filename.hashCode()), filename); FileUtils.copyFile(src, destFile); return destFile; diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionInstallerTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionInstallerTest.java index 0647b0e22ec..b01040b29cd 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionInstallerTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionInstallerTest.java @@ -19,7 +19,6 @@ */ package org.sonar.batch.bootstrap; -import com.google.common.collect.Maps; import org.apache.commons.lang.ClassUtils; import org.junit.Before; import org.junit.Test; @@ -28,13 +27,12 @@ import org.sonar.api.ExtensionProvider; import org.sonar.api.Plugin; import org.sonar.api.SonarPlugin; import org.sonar.api.batch.SupportedEnvironment; -import org.sonar.api.platform.ComponentContainer; -import org.sonar.api.platform.PluginMetadata; import org.sonar.batch.bootstrapper.EnvironmentInformation; +import org.sonar.core.platform.ComponentContainer; +import org.sonar.core.platform.PluginInfo; import java.util.Arrays; import java.util.List; -import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -42,19 +40,15 @@ import static org.mockito.Mockito.when; public class ExtensionInstallerTest { - private DefaultAnalysisMode mode; - PluginMetadata metadata = mock(PluginMetadata.class); + DefaultAnalysisMode mode; + BatchPluginRepository pluginRepository = mock(BatchPluginRepository.class); - Map<PluginMetadata, Plugin> newPlugin(final Object... extensions) { - Map<PluginMetadata, Plugin> result = Maps.newHashMap(); - result.put(metadata, - new SonarPlugin() { - public List getExtensions() { - return Arrays.asList(extensions); - } + private static Plugin newPluginInstance(final Object... extensions) { + return new SonarPlugin() { + public List getExtensions() { + return Arrays.asList(extensions); } - ); - return result; + }; } @Before @@ -64,8 +58,9 @@ public class ExtensionInstallerTest { @Test public void should_filter_extensions_to_install() { - BatchPluginRepository pluginRepository = mock(BatchPluginRepository.class); - when(pluginRepository.getPluginsByMetadata()).thenReturn(newPlugin(Foo.class, Bar.class)); + when(pluginRepository.getPluginInfos()).thenReturn(Arrays.asList(new PluginInfo("foo"))); + when(pluginRepository.getPluginInstance("foo")).thenReturn(newPluginInstance(Foo.class, Bar.class)); + ComponentContainer container = new ComponentContainer(); ExtensionInstaller installer = new ExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), mode); installer.install(container, new FooMatcher()); @@ -76,8 +71,8 @@ public class ExtensionInstallerTest { @Test public void should_execute_extension_provider() { - BatchPluginRepository pluginRepository = mock(BatchPluginRepository.class); - when(pluginRepository.getPluginsByMetadata()).thenReturn(newPlugin(new FooProvider(), new BarProvider())); + when(pluginRepository.getPluginInfos()).thenReturn(Arrays.asList(new PluginInfo("foo"))); + when(pluginRepository.getPluginInstance("foo")).thenReturn(newPluginInstance(new FooProvider(), new BarProvider())); ComponentContainer container = new ComponentContainer(); ExtensionInstaller installer = new ExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), mode); @@ -89,8 +84,8 @@ public class ExtensionInstallerTest { @Test public void should_provide_list_of_extensions() { - BatchPluginRepository pluginRepository = mock(BatchPluginRepository.class); - when(pluginRepository.getPluginsByMetadata()).thenReturn(newPlugin(new FooBarProvider())); + when(pluginRepository.getPluginInfos()).thenReturn(Arrays.asList(new PluginInfo("foo"))); + when(pluginRepository.getPluginInstance("foo")).thenReturn(newPluginInstance(new FooBarProvider())); ComponentContainer container = new ComponentContainer(); ExtensionInstaller installer = new ExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), mode); @@ -102,9 +97,8 @@ public class ExtensionInstallerTest { @Test public void should_not_install_on_unsupported_environment() { - BatchPluginRepository pluginRepository = mock(BatchPluginRepository.class); - when(pluginRepository.getPluginsByMetadata()).thenReturn(newPlugin(Foo.class, MavenExtension.class, AntExtension.class, new BarProvider())); - + when(pluginRepository.getPluginInfos()).thenReturn(Arrays.asList(new PluginInfo("foo"))); + when(pluginRepository.getPluginInstance("foo")).thenReturn(newPluginInstance(Foo.class, MavenExtension.class, AntExtension.class, new BarProvider())); ComponentContainer container = new ComponentContainer(); ExtensionInstaller installer = new ExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), mode); diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/GlobalContainerTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/GlobalContainerTest.java index 9fce2c7a951..ac87c52fa51 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/GlobalContainerTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/GlobalContainerTest.java @@ -19,25 +19,15 @@ */ package org.sonar.batch.bootstrap; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import org.junit.Test; import org.sonar.api.BatchExtension; -import org.sonar.api.Plugin; -import org.sonar.api.SonarPlugin; -import org.sonar.api.platform.PluginMetadata; import org.sonar.api.utils.TempFolder; import org.sonar.core.config.Logback; -import java.util.Arrays; import java.util.Collections; -import java.util.List; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; public class GlobalContainerTest { @Test @@ -58,22 +48,6 @@ public class GlobalContainerTest { assertThat(container.getComponentByType(Bar.class)).isNotNull(); } - @Test - public void should_install_plugins() { - PluginMetadata metadata = mock(PluginMetadata.class); - FakePlugin plugin = new FakePlugin(); - BatchPluginRepository pluginRepository = mock(BatchPluginRepository.class); - when(pluginRepository.getPluginsByMetadata()).thenReturn(ImmutableMap.<PluginMetadata, Plugin>of( - metadata, plugin - )); - - GlobalContainer container = spy(GlobalContainer.create(Collections.<String, String>emptyMap(), Lists.<Object>newArrayList(pluginRepository))); - doNothing().when(container).executeTask(Collections.<String, String>emptyMap()); - container.doAfterStart(); - - assertThat(container.getComponentsByType(Plugin.class)).containsOnly(plugin); - } - public static class Foo implements BatchExtension { } @@ -82,10 +56,4 @@ public class GlobalContainerTest { } - public static class FakePlugin extends SonarPlugin { - - public List getExtensions() { - return Arrays.asList(Foo.class, Bar.class); - } - } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/deprecated/decorator/DecoratorsSelectorTest.java b/sonar-batch/src/test/java/org/sonar/batch/deprecated/decorator/DecoratorsSelectorTest.java index fd9a9ed3727..3b7340689db 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/deprecated/decorator/DecoratorsSelectorTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/deprecated/decorator/DecoratorsSelectorTest.java @@ -25,7 +25,7 @@ import org.sonar.api.batch.Decorator; import org.sonar.api.batch.DecoratorContext; import org.sonar.api.batch.DependedUpon; import org.sonar.api.measures.*; -import org.sonar.api.platform.ComponentContainer; +import org.sonar.core.platform.ComponentContainer; import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; import org.sonar.batch.bootstrap.BatchExtensionDictionnary; diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectScanContainerTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectScanContainerTest.java index 5c98be19187..b4f7dc49ce3 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectScanContainerTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectScanContainerTest.java @@ -30,7 +30,7 @@ import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.batch.bootstrap.ProjectReactor; import org.sonar.api.config.PropertyDefinitions; import org.sonar.api.config.Settings; -import org.sonar.api.platform.ComponentContainer; +import org.sonar.core.platform.ComponentContainer; import org.sonar.api.task.TaskExtension; import org.sonar.api.utils.System2; import org.sonar.api.utils.TempFolder; diff --git a/sonar-batch/src/test/resources/org/sonar/batch/bootstrap/BatchPluginJarInstallerTest/sonar-checkstyle-plugin-2.8.jar b/sonar-batch/src/test/resources/org/sonar/batch/bootstrap/BatchPluginUnzipperTest/sonar-checkstyle-plugin-2.8.jar Binary files differindex f937399bec5..f937399bec5 100644 --- a/sonar-batch/src/test/resources/org/sonar/batch/bootstrap/BatchPluginJarInstallerTest/sonar-checkstyle-plugin-2.8.jar +++ b/sonar-batch/src/test/resources/org/sonar/batch/bootstrap/BatchPluginUnzipperTest/sonar-checkstyle-plugin-2.8.jar |