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    }