001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2008-2011 SonarSource 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * Sonar is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020 package org.sonar.batch.bootstrap; 021 022 import com.google.common.base.Joiner; 023 import com.google.common.collect.Maps; 024 import com.google.common.collect.Sets; 025 import org.apache.commons.lang.StringUtils; 026 import org.slf4j.Logger; 027 import org.slf4j.LoggerFactory; 028 import org.sonar.api.CoreProperties; 029 import org.sonar.api.Plugin; 030 import org.sonar.api.Properties; 031 import org.sonar.api.Property; 032 import org.sonar.api.config.Settings; 033 import org.sonar.api.platform.PluginMetadata; 034 import org.sonar.api.platform.PluginRepository; 035 import org.sonar.core.plugins.PluginClassloaders; 036 import org.sonar.core.plugins.PluginFileExtractor; 037 import org.sonar.core.plugins.RemotePlugin; 038 039 import java.io.File; 040 import java.util.*; 041 042 public class BatchPluginRepository implements PluginRepository { 043 044 private static final Logger LOG = LoggerFactory.getLogger(BatchPluginRepository.class); 045 private static final String CORE_PLUGIN = "core"; 046 047 private ArtifactDownloader artifactDownloader; 048 private Map<String, Plugin> pluginsByKey; 049 private Map<String, PluginMetadata> metadataByKey; 050 private Set<String> whiteList = null; 051 private Set<String> blackList = null; 052 private PluginClassloaders classLoaders; 053 054 public BatchPluginRepository(ArtifactDownloader artifactDownloader, Settings settings) { 055 this.artifactDownloader = artifactDownloader; 056 if (settings.hasKey(CoreProperties.BATCH_INCLUDE_PLUGINS)) { 057 whiteList = Sets.newTreeSet(Arrays.asList(settings.getStringArray(CoreProperties.BATCH_INCLUDE_PLUGINS))); 058 LOG.info("Include plugins: " + Joiner.on(", ").join(whiteList)); 059 } 060 if (settings.hasKey(CoreProperties.BATCH_EXCLUDE_PLUGINS)) { 061 blackList = Sets.newTreeSet(Arrays.asList(settings.getStringArray(CoreProperties.BATCH_EXCLUDE_PLUGINS))); 062 LOG.info("Exclude plugins: " + Joiner.on(", ").join(blackList)); 063 } 064 } 065 066 public void start() { 067 doStart(artifactDownloader.downloadPluginIndex()); 068 } 069 070 void doStart(List<RemotePlugin> remotePlugins) { 071 PluginFileExtractor extractor = new PluginFileExtractor(); 072 metadataByKey = Maps.newHashMap(); 073 for (RemotePlugin remote : remotePlugins) { 074 if (isAccepted(remote.getKey())) { 075 List<File> pluginFiles = artifactDownloader.downloadPlugin(remote); 076 List<File> extensionFiles = pluginFiles.subList(1, pluginFiles.size()); 077 PluginMetadata metadata = extractor.installInSameLocation(pluginFiles.get(0), remote.isCore(), extensionFiles); 078 if (StringUtils.isBlank(metadata.getBasePlugin()) || isAccepted(metadata.getBasePlugin())) { 079 LOG.debug("Excluded plugin: " + metadata.getKey()); 080 metadataByKey.put(metadata.getKey(), metadata); 081 } 082 } 083 } 084 classLoaders = new PluginClassloaders(Thread.currentThread().getContextClassLoader()); 085 pluginsByKey = classLoaders.init(metadataByKey.values()); 086 } 087 088 public void stop() { 089 if (classLoaders != null) { 090 classLoaders.clean(); 091 classLoaders = null; 092 } 093 } 094 095 public Collection<Plugin> getPlugins() { 096 return pluginsByKey.values(); 097 } 098 099 public Plugin getPlugin(String key) { 100 return pluginsByKey.get(key); 101 } 102 103 public Map<String, Plugin> getPluginsByKey() { 104 return Collections.unmodifiableMap(pluginsByKey); 105 } 106 107 // TODO remove this method. Not used in batch. 108 public Property[] getProperties(Plugin plugin) { 109 if (plugin != null) { 110 Class<? extends Plugin> classInstance = plugin.getClass(); 111 if (classInstance.isAnnotationPresent(Properties.class)) { 112 return classInstance.getAnnotation(Properties.class).value(); 113 } 114 } 115 return new Property[0]; 116 } 117 118 public Collection<PluginMetadata> getMetadata() { 119 return metadataByKey.values(); 120 } 121 122 public PluginMetadata getMetadata(String pluginKey) { 123 return metadataByKey.get(pluginKey); 124 } 125 126 boolean isAccepted(String pluginKey) { 127 if (CORE_PLUGIN.equals(pluginKey)) { 128 return true; 129 } 130 if (whiteList != null) { 131 return whiteList.contains(pluginKey); 132 } 133 return blackList == null || !blackList.contains(pluginKey); 134 } 135 136 public Map<PluginMetadata,Plugin> getPluginsByMetadata() { 137 Map<PluginMetadata, Plugin> result = Maps.newHashMap(); 138 for (Map.Entry<String, PluginMetadata> entry : metadataByKey.entrySet()) { 139 String pluginKey = entry.getKey(); 140 PluginMetadata metadata = entry.getValue(); 141 result.put(metadata, pluginsByKey.get(pluginKey)); 142 } 143 return result; 144 } 145 }