001 /*
002 * SonarQube, open source software quality management tool.
003 * Copyright (C) 2008-2014 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * SonarQube 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 * SonarQube 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 License
017 * along with this program; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
019 */
020 package org.sonar.batch.bootstrap;
021
022 import com.google.common.collect.Lists;
023 import org.apache.commons.lang.ClassUtils;
024 import org.sonar.api.batch.CheckProject;
025 import org.sonar.api.batch.Phase;
026 import org.sonar.api.batch.sensor.Sensor;
027 import org.sonar.api.batch.sensor.SensorContext;
028 import org.sonar.api.platform.ComponentContainer;
029 import org.sonar.api.resources.Project;
030 import org.sonar.batch.scan.SensorWrapper;
031 import org.sonar.batch.scan2.AnalyzerOptimizer;
032
033 import javax.annotation.Nullable;
034
035 import java.util.Collection;
036 import java.util.List;
037
038 /**
039 * @since 2.6
040 */
041 public class BatchExtensionDictionnary extends org.sonar.api.batch.BatchExtensionDictionnary {
042
043 private SensorContext context;
044 private AnalyzerOptimizer analyzerOptimizer;
045
046 public BatchExtensionDictionnary(ComponentContainer componentContainer, SensorContext context, AnalyzerOptimizer analyzerOptimizer) {
047 super(componentContainer);
048 this.context = context;
049 this.analyzerOptimizer = analyzerOptimizer;
050 }
051
052 public <T> Collection<T> select(Class<T> type, @Nullable Project project, boolean sort, @Nullable ExtensionMatcher matcher) {
053 List<T> result = getFilteredExtensions(type, project, matcher);
054 if (sort) {
055 return sort(result);
056 }
057 return result;
058 }
059
060 @Override
061 protected Phase.Name evaluatePhase(Object extension) {
062 if (extension instanceof SensorWrapper) {
063 return super.evaluatePhase(((SensorWrapper) extension).wrappedSensor());
064 } else {
065 return super.evaluatePhase(extension);
066 }
067 }
068
069 private <T> List<T> getFilteredExtensions(Class<T> type, @Nullable Project project, @Nullable ExtensionMatcher matcher) {
070 List<T> result = Lists.newArrayList();
071 for (Object extension : getExtensions(type)) {
072 if (org.sonar.api.batch.Sensor.class.equals(type) && extension instanceof Sensor) {
073 extension = new SensorWrapper((Sensor) extension, context, analyzerOptimizer);
074 }
075 if (shouldKeep(type, extension, project, matcher)) {
076 result.add((T) extension);
077 }
078 }
079 if (org.sonar.api.batch.Sensor.class.equals(type)) {
080 // Retrieve new Sensors and wrap then in SensorWrapper
081 for (Object extension : getExtensions(Sensor.class)) {
082 extension = new SensorWrapper((Sensor) extension, context, analyzerOptimizer);
083 if (shouldKeep(type, extension, project, matcher)) {
084 result.add((T) extension);
085 }
086 }
087 }
088 return result;
089 }
090
091 private boolean shouldKeep(Class type, Object extension, @Nullable Project project, @Nullable ExtensionMatcher matcher) {
092 boolean keep = (ClassUtils.isAssignable(extension.getClass(), type)
093 || (org.sonar.api.batch.Sensor.class.equals(type) && ClassUtils.isAssignable(extension.getClass(), Sensor.class)))
094 && (matcher == null || matcher.accept(extension));
095 if (keep && project != null && ClassUtils.isAssignable(extension.getClass(), CheckProject.class)) {
096 keep = ((CheckProject) extension).shouldExecuteOnProject(project);
097 }
098 return keep;
099 }
100 }