Java tutorial
/* * 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.server.plugins; import com.google.common.base.Joiner; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.platform.PluginMetadata; import org.sonar.api.platform.Server; import org.sonar.api.platform.ServerUpgradeStatus; import org.sonar.api.utils.MessageException; import org.sonar.api.utils.TimeProfiler; import org.sonar.core.plugins.DefaultPluginMetadata; import org.sonar.server.platform.DefaultServerFileSystem; import org.sonar.updatecenter.common.PluginReferential; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; public class ServerPluginJarsInstaller { private static final Logger LOG = LoggerFactory.getLogger(ServerPluginJarsInstaller.class); private final Server server; private final DefaultServerFileSystem fs; private final ServerPluginJarInstaller installer; private final Map<String, PluginMetadata> pluginByKeys = Maps.newHashMap(); private final ServerUpgradeStatus serverUpgradeStatus; private static final Set<String> BLACKLISTED_PLUGINS = new HashSet<String>(Arrays.asList("scmactivity")); public ServerPluginJarsInstaller(Server server, ServerUpgradeStatus serverUpgradeStatus, DefaultServerFileSystem fs, ServerPluginJarInstaller installer) { this.server = server; this.serverUpgradeStatus = serverUpgradeStatus; this.fs = fs; this.installer = installer; } public void install() { TimeProfiler profiler = new TimeProfiler().start("Install plugins"); deleteTrash(); loadInstalledPlugins(); copyBundledPlugins(); moveDownloadedPlugins(); loadCorePlugins(); deployPlugins(); profiler.stop(); } private void deleteTrash() { File trashDir = fs.getTrashPluginsDir(); try { if (trashDir.exists()) { FileUtils.deleteDirectory(trashDir); } } catch (IOException e) { throw new IllegalStateException("Fail to clean the plugin trash directory: " + trashDir, e); } } private void loadInstalledPlugins() { for (File file : fs.getUserPlugins()) { DefaultPluginMetadata metadata = installer.extractMetadata(file, false); if (StringUtils.isNotBlank(metadata.getKey())) { loadInstalledPlugin(metadata); } } } private void loadInstalledPlugin(DefaultPluginMetadata metadata) { if (BLACKLISTED_PLUGINS.contains(metadata.getKey())) { LOG.warn("Plugin {} is blacklisted. Please uninstall it.", metadata.getName()); } else { PluginMetadata existing = pluginByKeys.put(metadata.getKey(), metadata); if (existing != null) { throw MessageException.of(String.format("Found two files for the same plugin '%s': %s and %s", metadata.getKey(), metadata.getFile().getName(), existing.getFile().getName())); } } } private void moveDownloadedPlugins() { if (fs.getDownloadedPluginsDir().exists()) { Collection<File> sourceFiles = FileUtils.listFiles(fs.getDownloadedPluginsDir(), new String[] { "jar" }, false); for (File sourceFile : sourceFiles) { overridePlugin(sourceFile, true); } } } private void copyBundledPlugins() { if (serverUpgradeStatus.isFreshInstall()) { for (File sourceFile : fs.getBundledPlugins()) { DefaultPluginMetadata metadata = installer.extractMetadata(sourceFile, false); // lib/bundled-plugins should be copied only if the plugin is not already // available in extensions/plugins if (!pluginByKeys.containsKey(metadata.getKey())) { overridePlugin(sourceFile, false); } } } } private void overridePlugin(File sourceFile, boolean deleteSource) { File destDir = fs.getUserPluginsDir(); File destFile = new File(destDir, sourceFile.getName()); if (destFile.exists()) { // plugin with same filename already installed FileUtils.deleteQuietly(destFile); } try { if (deleteSource) { FileUtils.moveFile(sourceFile, destFile); } else { FileUtils.copyFile(sourceFile, destFile, true); } } catch (IOException e) { LOG.error(String.format("Fail to move or copy plugin: %s to %s", sourceFile.getAbsolutePath(), destFile.getAbsolutePath()), e); } DefaultPluginMetadata metadata = installer.extractMetadata(destFile, false); if (StringUtils.isNotBlank(metadata.getKey())) { PluginMetadata existing = pluginByKeys.put(metadata.getKey(), metadata); if (existing != null) { if (!existing.getFile().getName().equals(destFile.getName())) { FileUtils.deleteQuietly(existing.getFile()); } LOG.info("Plugin " + metadata.getKey() + " replaced by new version"); } } } private void loadCorePlugins() { for (File file : fs.getCorePlugins()) { DefaultPluginMetadata metadata = installer.extractMetadata(file, true); PluginMetadata existing = pluginByKeys.put(metadata.getKey(), metadata); if (existing != null) { throw new IllegalStateException("Found two plugins with the same key '" + metadata.getKey() + "': " + metadata.getFile().getName() + " and " + existing.getFile().getName()); } } } public void uninstall(String pluginKey) { for (String key : getPluginReferential().findLastReleasesWithDependencies(pluginKey)) { uninstallPlugin(key); } } private void uninstallPlugin(String pluginKey) { PluginMetadata metadata = pluginByKeys.get(pluginKey); if (metadata != null && !metadata.isCore()) { try { File masterFile = new File(fs.getUserPluginsDir(), metadata.getFile().getName()); FileUtils.moveFileToDirectory(masterFile, fs.getTrashPluginsDir(), true); } catch (IOException e) { throw new IllegalStateException("Fail to uninstall plugin: " + pluginKey, e); } } } public List<String> getUninstalls() { List<String> names = Lists.newArrayList(); if (fs.getTrashPluginsDir().exists()) { List<File> files = (List<File>) FileUtils.listFiles(fs.getTrashPluginsDir(), new String[] { "jar" }, false); for (File file : files) { names.add(file.getName()); } } return names; } public void cancelUninstalls() { if (fs.getTrashPluginsDir().exists()) { List<File> files = (List<File>) FileUtils.listFiles(fs.getTrashPluginsDir(), new String[] { "jar" }, false); for (File file : files) { try { FileUtils.moveFileToDirectory(file, fs.getUserPluginsDir(), false); } catch (IOException e) { throw new IllegalStateException("Fail to cancel plugin uninstalls", e); } } } } private void deployPlugins() { for (PluginMetadata metadata : pluginByKeys.values()) { deploy((DefaultPluginMetadata) metadata); } } private void deploy(DefaultPluginMetadata plugin) { LOG.info("Deploy plugin {}", Joiner.on(" / ").skipNulls().join(plugin.getName(), plugin.getVersion(), plugin.getImplementationBuild())); if (!plugin.isCompatibleWith(server.getVersion())) { throw MessageException.of(String.format( "Plugin %s needs a more recent version of SonarQube than %s. At least %s is expected", plugin.getKey(), server.getVersion(), plugin.getSonarVersion())); } try { File pluginDeployDir = new File(fs.getDeployedPluginsDir(), plugin.getKey()); FileUtils.forceMkdir(pluginDeployDir); FileUtils.cleanDirectory(pluginDeployDir); installer.installToDir(plugin, pluginDeployDir); } catch (IOException e) { throw new IllegalStateException("Fail to deploy the plugin " + plugin, e); } } public Collection<PluginMetadata> getMetadata() { return pluginByKeys.values(); } public PluginMetadata getMetadata(String pluginKey) { return pluginByKeys.get(pluginKey); } private PluginReferential getPluginReferential() { return PluginReferentialMetadataConverter.getInstalledPluginReferential(getMetadata()); } }