001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2012 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.PluginInstaller;
037 import org.sonar.core.plugins.RemotePlugin;
038
039 import java.io.File;
040 import java.util.Arrays;
041 import java.util.Collection;
042 import java.util.Collections;
043 import java.util.List;
044 import java.util.Map;
045 import java.util.Set;
046
047 public class BatchPluginRepository implements PluginRepository {
048
049 private static final Logger LOG = LoggerFactory.getLogger(BatchPluginRepository.class);
050 private static final String CORE_PLUGIN = "core";
051 private static final String ENGLISH_PACK_PLUGIN = "l10nen";
052
053 private ArtifactDownloader artifactDownloader;
054 private Map<String, Plugin> pluginsByKey;
055 private Map<String, PluginMetadata> metadataByKey;
056 private Set<String> whiteList = null;
057 private Set<String> blackList = null;
058 private PluginClassloaders classLoaders;
059
060 public BatchPluginRepository(ArtifactDownloader artifactDownloader, Settings settings) {
061 this.artifactDownloader = artifactDownloader;
062 if (settings.hasKey(CoreProperties.BATCH_INCLUDE_PLUGINS)) {
063 whiteList = Sets.newTreeSet(Arrays.asList(settings.getStringArray(CoreProperties.BATCH_INCLUDE_PLUGINS)));
064 LOG.info("Include plugins: " + Joiner.on(", ").join(whiteList));
065 }
066 if (settings.hasKey(CoreProperties.BATCH_EXCLUDE_PLUGINS)) {
067 blackList = Sets.newTreeSet(Arrays.asList(settings.getStringArray(CoreProperties.BATCH_EXCLUDE_PLUGINS)));
068 LOG.info("Exclude plugins: " + Joiner.on(", ").join(blackList));
069 }
070 }
071
072 public void start() {
073 doStart(artifactDownloader.downloadPluginIndex());
074 }
075
076 void doStart(List<RemotePlugin> remotePlugins) {
077 PluginInstaller extractor = new PluginInstaller();
078 metadataByKey = Maps.newHashMap();
079 for (RemotePlugin remote : remotePlugins) {
080 if (isAccepted(remote.getKey())) {
081 List<File> pluginFiles = artifactDownloader.downloadPlugin(remote);
082 List<File> extensionFiles = pluginFiles.subList(1, pluginFiles.size());
083 PluginMetadata metadata = extractor.installInSameLocation(pluginFiles.get(0), remote.isCore(), extensionFiles);
084 if (StringUtils.isBlank(metadata.getBasePlugin()) || isAccepted(metadata.getBasePlugin())) {
085 LOG.debug("Excluded plugin: " + metadata.getKey());
086 metadataByKey.put(metadata.getKey(), metadata);
087 }
088 }
089 }
090 classLoaders = new PluginClassloaders(Thread.currentThread().getContextClassLoader());
091 pluginsByKey = classLoaders.init(metadataByKey.values());
092 }
093
094 public void stop() {
095 if (classLoaders != null) {
096 classLoaders.clean();
097 classLoaders = null;
098 }
099 }
100
101 public Collection<Plugin> getPlugins() {
102 return pluginsByKey.values();
103 }
104
105 public Plugin getPlugin(String key) {
106 return pluginsByKey.get(key);
107 }
108
109 public Map<String, Plugin> getPluginsByKey() {
110 return Collections.unmodifiableMap(pluginsByKey);
111 }
112
113 // TODO remove this method. Not used in batch.
114 public Property[] getProperties(Plugin plugin) {
115 if (plugin != null) {
116 Class<? extends Plugin> classInstance = plugin.getClass();
117 if (classInstance.isAnnotationPresent(Properties.class)) {
118 return classInstance.getAnnotation(Properties.class).value();
119 }
120 }
121 return new Property[0];
122 }
123
124 public Collection<PluginMetadata> getMetadata() {
125 return metadataByKey.values();
126 }
127
128 public PluginMetadata getMetadata(String pluginKey) {
129 return metadataByKey.get(pluginKey);
130 }
131
132 boolean isAccepted(String pluginKey) {
133 if (CORE_PLUGIN.equals(pluginKey) || ENGLISH_PACK_PLUGIN.equals(pluginKey)) {
134 return true;
135 }
136 if (whiteList != null) {
137 return whiteList.contains(pluginKey);
138 }
139 return blackList == null || !blackList.contains(pluginKey);
140 }
141
142 public Map<PluginMetadata, Plugin> getPluginsByMetadata() {
143 Map<PluginMetadata, Plugin> result = Maps.newHashMap();
144 for (Map.Entry<String, PluginMetadata> entry : metadataByKey.entrySet()) {
145 String pluginKey = entry.getKey();
146 PluginMetadata metadata = entry.getValue();
147 result.put(metadata, pluginsByKey.get(pluginKey));
148 }
149 return result;
150 }
151 }