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 // TODO reactivate somewhere else: LOG.info("Execution environment: {} {}", environment.getKey(), environment.getVersion()); 065 } 066 067 public void start() { 068 doStart(artifactDownloader.downloadPluginIndex()); 069 } 070 071 void doStart(List<RemotePlugin> remotePlugins) { 072 PluginFileExtractor extractor = new PluginFileExtractor(); 073 metadataByKey = Maps.newHashMap(); 074 for (RemotePlugin remote : remotePlugins) { 075 if (isAccepted(remote.getKey())) { 076 List<File> pluginFiles = artifactDownloader.downloadPlugin(remote); 077 List<File> extensionFiles = pluginFiles.subList(1, pluginFiles.size()); 078 PluginMetadata metadata = extractor.installInSameLocation(pluginFiles.get(0), remote.isCore(), extensionFiles); 079 if (StringUtils.isBlank(metadata.getBasePlugin()) || isAccepted(metadata.getBasePlugin())) { 080 // TODO log when excluding plugin 081 metadataByKey.put(metadata.getKey(), metadata); 082 } 083 } 084 } 085 classLoaders = new PluginClassloaders(Thread.currentThread().getContextClassLoader()); 086 pluginsByKey = classLoaders.init(metadataByKey.values()); 087 } 088 089 public void stop() { 090 if (classLoaders != null) { 091 classLoaders.clean(); 092 classLoaders = null; 093 } 094 } 095 096 public Collection<Plugin> getPlugins() { 097 return pluginsByKey.values(); 098 } 099 100 public Plugin getPlugin(String key) { 101 return pluginsByKey.get(key); 102 } 103 104 public Map<String, Plugin> getPluginsByKey() { 105 return Collections.unmodifiableMap(pluginsByKey); 106 } 107 108 // TODO remove this method. Not used in batch. 109 public Property[] getProperties(Plugin plugin) { 110 if (plugin != null) { 111 Class<? extends Plugin> classInstance = plugin.getClass(); 112 if (classInstance.isAnnotationPresent(Properties.class)) { 113 return classInstance.getAnnotation(Properties.class).value(); 114 } 115 } 116 return new Property[0]; 117 } 118 119 public Collection<PluginMetadata> getMetadata() { 120 return metadataByKey.values(); 121 } 122 123 public PluginMetadata getMetadata(String pluginKey) { 124 return metadataByKey.get(pluginKey); 125 } 126 127 boolean isAccepted(String pluginKey) { 128 if (CORE_PLUGIN.equals(pluginKey)) { 129 return true; 130 } 131 if (whiteList != null) { 132 return whiteList.contains(pluginKey); 133 } 134 return blackList == null || !blackList.contains(pluginKey); 135 } 136 137 public Map<PluginMetadata,Plugin> getPluginsByMetadata() { 138 Map<PluginMetadata, Plugin> result = Maps.newHashMap(); 139 for (Map.Entry<String, PluginMetadata> entry : metadataByKey.entrySet()) { 140 String pluginKey = entry.getKey(); 141 PluginMetadata metadata = entry.getValue(); 142 result.put(metadata, pluginsByKey.get(pluginKey)); 143 } 144 return result; 145 } 146 }