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 */ 020package org.sonar.batch.bootstrap; 021 022import org.apache.commons.lang.ArrayUtils; 023import org.apache.commons.lang.StringUtils; 024import org.sonar.api.BatchComponent; 025import org.sonar.api.CoreProperties; 026import org.sonar.api.ExtensionProvider; 027import org.sonar.api.Plugin; 028import org.sonar.api.batch.AbstractCoverageExtension; 029import org.sonar.api.batch.CoverageExtension; 030import org.sonar.api.batch.InstantiationStrategy; 031import org.sonar.api.config.Settings; 032import org.sonar.api.resources.Java; 033import org.sonar.api.resources.Project; 034import org.sonar.batch.bootstrapper.EnvironmentInformation; 035import org.sonar.batch.config.ProjectSettings; 036 037import java.util.List; 038import java.util.Map; 039 040public 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}