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.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.resources.Project;
029    import org.sonar.api.resources.Resource;
030    import org.sonar.api.utils.SonarException;
031    import org.sonar.batch.DecoratorsSelector;
032    import org.sonar.batch.DefaultDecoratorContext;
033    import org.sonar.batch.events.EventBus;
034    
035    import java.util.Collection;
036    import java.util.List;
037    
038    public class DecoratorsExecutor implements BatchComponent {
039    
040      private DecoratorsSelector decoratorsSelector;
041      private SonarIndex index;
042      private EventBus eventBus;
043      private Project project;
044    
045      public DecoratorsExecutor(BatchExtensionDictionnary extensionDictionnary, Project project, SonarIndex index, EventBus eventBus) {
046        this.decoratorsSelector = new DecoratorsSelector(extensionDictionnary);
047        this.index = index;
048        this.eventBus = eventBus;
049        this.project = project;
050      }
051    
052      public void execute() {
053        Collection<Decorator> decorators = decoratorsSelector.select(project);
054        eventBus.fireEvent(new DecoratorsPhaseEvent(Lists.newArrayList(decorators), true));
055        decorateResource(project, decorators, true);
056        eventBus.fireEvent(new DecoratorsPhaseEvent(Lists.newArrayList(decorators), false));
057      }
058    
059      DecoratorContext decorateResource(Resource resource, Collection<Decorator> decorators, boolean executeDecorators) {
060        List<DecoratorContext> childrenContexts = Lists.newArrayList();
061        for (Resource child : index.getChildren(resource)) {
062          boolean isModule = (child instanceof Project);
063          DefaultDecoratorContext childContext = (DefaultDecoratorContext) decorateResource(child, decorators, !isModule);
064          childrenContexts.add(childContext.setReadOnly(true));
065        }
066    
067        DefaultDecoratorContext context = new DefaultDecoratorContext(resource, index, childrenContexts);
068        if (executeDecorators) {
069          for (Decorator decorator : decorators) {
070            executeDecorator(decorator, context, resource);
071          }
072        }
073        return context;
074      }
075    
076      void executeDecorator(Decorator decorator, DefaultDecoratorContext context, Resource resource) {
077        try {
078          eventBus.fireEvent(new DecoratorExecutionEvent(decorator, true));
079          decorator.decorate(resource, context);
080          eventBus.fireEvent(new DecoratorExecutionEvent(decorator, false));
081          
082        } catch (Exception e) {
083          // SONAR-2278 the resource should not be lost in exception stacktrace.
084          throw new SonarException("Fail to decorate '" + resource + "'", e);
085        }
086      }
087    
088    }