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.phases;
021
022 import com.google.common.collect.Lists;
023 import org.sonar.api.BatchComponent;
024 import org.sonar.api.batch.BatchExtensionDictionnary;
025 import org.sonar.api.batch.Decorator;
026 import org.sonar.api.batch.DecoratorContext;
027 import org.sonar.api.batch.SonarIndex;
028 import org.sonar.api.measures.MetricFinder;
029 import org.sonar.api.resources.Project;
030 import org.sonar.api.resources.Resource;
031 import org.sonar.api.utils.MessageException;
032 import org.sonar.api.utils.SonarException;
033 import org.sonar.batch.DecoratorsSelector;
034 import org.sonar.batch.DefaultDecoratorContext;
035 import org.sonar.batch.duplication.DuplicationCache;
036 import org.sonar.batch.events.EventBus;
037 import org.sonar.batch.scan.measure.MeasureCache;
038 import org.sonar.core.measure.MeasurementFilters;
039
040 import java.util.Collection;
041 import java.util.List;
042
043 public class DecoratorsExecutor implements BatchComponent {
044
045 private DecoratorsSelector decoratorsSelector;
046 private SonarIndex index;
047 private EventBus eventBus;
048 private Project project;
049 private MeasurementFilters measurementFilters;
050 private MeasureCache measureCache;
051 private MetricFinder metricFinder;
052 private final DuplicationCache duplicationCache;
053
054 public DecoratorsExecutor(BatchExtensionDictionnary batchExtDictionnary,
055 Project project, SonarIndex index, EventBus eventBus, MeasurementFilters measurementFilters, MeasureCache measureCache, MetricFinder metricFinder,
056 DuplicationCache duplicationCache) {
057 this.measureCache = measureCache;
058 this.metricFinder = metricFinder;
059 this.duplicationCache = duplicationCache;
060 this.decoratorsSelector = new DecoratorsSelector(batchExtDictionnary);
061 this.index = index;
062 this.eventBus = eventBus;
063 this.project = project;
064 this.measurementFilters = measurementFilters;
065 }
066
067 public void execute() {
068 Collection<Decorator> decorators = decoratorsSelector.select(project);
069 eventBus.fireEvent(new DecoratorsPhaseEvent(Lists.newArrayList(decorators), true));
070 ((DefaultDecoratorContext) decorateResource(project, decorators, true)).end();
071 eventBus.fireEvent(new DecoratorsPhaseEvent(Lists.newArrayList(decorators), false));
072 }
073
074 DecoratorContext decorateResource(Resource resource, Collection<Decorator> decorators, boolean executeDecorators) {
075 List<DecoratorContext> childrenContexts = Lists.newArrayList();
076 for (Resource child : index.getChildren(resource)) {
077 boolean isModule = child instanceof Project;
078 DefaultDecoratorContext childContext = (DefaultDecoratorContext) decorateResource(child, decorators, !isModule);
079 childrenContexts.add(childContext.end());
080 }
081
082 DefaultDecoratorContext context = new DefaultDecoratorContext(resource, index, childrenContexts, measurementFilters, measureCache, metricFinder, duplicationCache);
083 context.init();
084 if (executeDecorators) {
085 for (Decorator decorator : decorators) {
086 executeDecorator(decorator, context, resource);
087 }
088 }
089 return context;
090 }
091
092 void executeDecorator(Decorator decorator, DefaultDecoratorContext context, Resource resource) {
093 try {
094 eventBus.fireEvent(new DecoratorExecutionEvent(decorator, true));
095 decorator.decorate(resource, context);
096 eventBus.fireEvent(new DecoratorExecutionEvent(decorator, false));
097
098 } catch (MessageException e) {
099 throw e;
100
101 } catch (Exception e) {
102 // SONAR-2278 the resource should not be lost in exception stacktrace.
103 throw new SonarException("Fail to decorate '" + resource + "'", e);
104 }
105 }
106
107 }