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 org.apache.commons.lang.ArrayUtils;
023 import org.apache.commons.lang.StringUtils;
024 import org.sonar.api.BatchComponent;
025 import org.sonar.api.CoreProperties;
026 import org.sonar.api.ExtensionProvider;
027 import org.sonar.api.Plugin;
028 import org.sonar.api.batch.AbstractCoverageExtension;
029 import org.sonar.api.batch.CoverageExtension;
030 import org.sonar.api.batch.InstantiationStrategy;
031 import org.sonar.api.config.Settings;
032 import org.sonar.api.resources.Java;
033 import org.sonar.api.resources.Project;
034 import org.sonar.batch.bootstrapper.EnvironmentInformation;
035 import org.sonar.batch.config.ProjectSettings;
036
037 import java.util.List;
038 import java.util.Map;
039
040 public final class ProjectExtensionInstaller implements BatchComponent {
041
042 private BatchPluginRepository pluginRepository;
043 private EnvironmentInformation environment;
044 private DryRun dryRun;
045 private Project project;
046 private ProjectSettings settings;
047
048 public ProjectExtensionInstaller(BatchPluginRepository pluginRepository, EnvironmentInformation environment, DryRun dryRun, Project project, ProjectSettings settings) {
049 this.pluginRepository = pluginRepository;
050 this.environment = environment;
051 this.dryRun = dryRun;
052 this.project = project;
053 this.settings = settings;
054 }
055
056 public void install(Module module) {
057 for (Map.Entry<String, Plugin> entry : pluginRepository.getPluginsByKey().entrySet()) {
058 for (Object extension : entry.getValue().getExtensions()) {
059 installExtension(module, extension, entry.getKey());
060 }
061 }
062 installExtensionProviders(module);
063 }
064
065 void installExtensionProviders(Module module) {
066 List<ExtensionProvider> providers = module.getComponents(ExtensionProvider.class);
067 for (ExtensionProvider provider : providers) {
068 Object obj = provider.provide();
069 if (obj instanceof Iterable) {
070 for (Object extension : (Iterable) obj) {
071 installExtension(module, extension, "");
072 }
073 } else {
074 installExtension(module, obj, "");
075 }
076 }
077 }
078
079 private Object installExtension(Module module, Object extension, String pluginKey) {
080 if (ExtensionUtils.isBatchExtension(extension) &&
081 ExtensionUtils.isSupportedEnvironment(extension, environment) &&
082 ExtensionUtils.isInstantiationStrategy(extension, InstantiationStrategy.PER_PROJECT) &&
083 ExtensionUtils.checkDryRun(extension, dryRun.isEnabled()) &&
084 !isDeactivatedCoverageExtension(extension, pluginKey, project, settings) &&
085 !isMavenExtensionOnEmulatedMavenProject(extension, project)) {
086 module.addCoreSingleton(extension);
087 return extension;
088 }
089 return null;
090 }
091
092 /**
093 * Special use-case: the extension point ProjectBuilder is used in a Maven environment to define some
094 * new sub-projects without pom.
095 * Example : C# plugin adds sub-projects at runtime, even if they are not defined in root pom.
096 */
097 static boolean isMavenExtensionOnEmulatedMavenProject(Object extension, Project project) {
098 return ExtensionUtils.isMavenExtensionOnly(extension) && project.getPom() == null;
099 }
100
101 /**
102 * TODO this code is specific to Java projects and should be moved somewhere else
103 */
104 static boolean isDeactivatedCoverageExtension(Object extension, String pluginKey, Project project, Settings settings) {
105 if (!ExtensionUtils.isType(extension, CoverageExtension.class)) {
106 return false;
107 }
108
109 if (!project.getAnalysisType().isDynamic(true)) {
110 // not dynamic and not reuse reports
111 return true;
112 }
113
114 if (StringUtils.equals(project.getLanguageKey(), Java.KEY)) {
115 String[] selectedPluginKeys = settings.getStringArray(CoreProperties.CORE_COVERAGE_PLUGIN_PROPERTY);
116 if (ArrayUtils.isEmpty(selectedPluginKeys)) {
117 selectedPluginKeys = new String[]{AbstractCoverageExtension.DEFAULT_PLUGIN};
118 }
119 return !ArrayUtils.contains(selectedPluginKeys, pluginKey);
120 }
121 return false;
122 }
123 }