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;
021
022import com.google.common.collect.ImmutableList;
023import com.google.common.collect.Iterables;
024import org.apache.commons.io.FileUtils;
025import org.apache.maven.project.MavenProject;
026import org.sonar.api.batch.FileFilter;
027import org.sonar.api.batch.bootstrap.ProjectDefinition;
028import org.sonar.api.resources.DefaultProjectFileSystem;
029import org.sonar.api.resources.Languages;
030import org.sonar.api.resources.Project;
031import org.sonar.api.utils.SonarException;
032
033import java.io.File;
034import java.io.IOException;
035import java.util.List;
036
037/**
038 * Implementation of {@link org.sonar.api.resources.ProjectFileSystem} based on {@link ProjectDefinition} and {@link MavenProject}.
039 */
040public class DefaultProjectFileSystem2 extends DefaultProjectFileSystem {
041
042  private ProjectDefinition def;
043  private MavenProject pom;
044
045  public DefaultProjectFileSystem2(Project project, Languages languages, ProjectDefinition def, FileFilter[] fileFilters) {
046    super(project, languages, fileFilters);
047    this.def = def;
048  }
049
050  /**
051   * For Maven.
052   */
053  public DefaultProjectFileSystem2(Project project, Languages languages, ProjectDefinition def, MavenProject pom, FileFilter[] fileFilters) {
054    this(project, languages, def, fileFilters);
055    this.pom = pom;
056  }
057
058  public DefaultProjectFileSystem2(Project project, Languages languages, ProjectDefinition def) {
059    this(project, languages, def, new FileFilter[0]);
060  }
061
062  /**
063   * For Maven.
064   */
065  public DefaultProjectFileSystem2(Project project, Languages languages, ProjectDefinition def, MavenProject pom) {
066    this(project, languages, def, pom, new FileFilter[0]);
067  }
068
069  @Override
070  public File getBasedir() {
071    return def.getBaseDir();
072  }
073
074  @Override
075  public File getBuildDir() {
076    if (pom != null) {
077      return resolvePath(pom.getBuild().getDirectory());
078    } else {
079      // TODO workaround
080      return new File(getSonarWorkingDirectory(), "target");
081    }
082  }
083
084  @Override
085  public File getBuildOutputDir() {
086    if (pom != null) {
087      return resolvePath(pom.getBuild().getOutputDirectory());
088    } else {
089      if (def.getBinaries().isEmpty()) {
090        // workaround for IndexOutOfBoundsException
091        return new File(getBuildDir(), "classes");
092      }
093      // TODO we assume that there is only one directory which contains compiled code
094      return resolvePath(def.getBinaries().get(0));
095    }
096  }
097
098  @Override
099  public List<File> getSourceDirs() {
100    List<File> unfiltered = resolvePaths(def.getSourceDirs());
101    return ImmutableList.copyOf(Iterables.filter(unfiltered, DIRECTORY_EXISTS));
102  }
103
104  /**
105   * @deprecated since 2.6, because should be immutable
106   */
107  @Override
108  @Deprecated
109  public DefaultProjectFileSystem addSourceDir(File dir) {
110    if (dir == null) {
111      throw new IllegalArgumentException("Can not add null to project source dirs");
112    }
113    if (pom != null) {
114      pom.getCompileSourceRoots().add(0, dir.getAbsolutePath());
115    }
116    def.addSourceDirs(dir.getAbsolutePath());
117    return this;
118  }
119
120  /**
121   * Maven can modify test directories during Sonar execution - see MavenPhaseExecutor.
122   */
123  @Override
124  public List<File> getTestDirs() {
125    List<File> unfiltered = resolvePaths(def.getTestDirs());
126    return ImmutableList.copyOf(Iterables.filter(unfiltered, DIRECTORY_EXISTS));
127  }
128
129  /**
130   * @deprecated since 2.6, because should be immutable
131   */
132  @Override
133  @Deprecated
134  public DefaultProjectFileSystem addTestDir(File dir) {
135    if (dir == null) {
136      throw new IllegalArgumentException("Can not add null to project test dirs");
137    }
138    if (pom != null) {
139      pom.getTestCompileSourceRoots().add(0, dir.getAbsolutePath());
140    }
141    def.addTestDirs(dir.getAbsolutePath());
142    return this;
143  }
144
145  /**
146   * TODO Godin: seems that used only by Cobertura and Clover
147   */
148  @Override
149  public File getReportOutputDir() {
150    if (pom != null) {
151      return resolvePath(pom.getReporting().getOutputDirectory());
152    } else {
153      return new File(getBuildDir(), "site");
154    }
155  }
156
157  @Override
158  public File getSonarWorkingDirectory() {
159    try {
160      FileUtils.forceMkdir(def.getWorkDir());
161      return def.getWorkDir();
162    } catch (IOException e) {
163      throw new SonarException("Unable to retrieve Sonar working directory.", e);
164    }
165  }
166
167  @Override
168  protected List<File> getInitialSourceFiles() {
169    return resolvePaths(def.getSourceFiles());
170  }
171
172  @Override
173  protected List<File> getInitialTestFiles() {
174    return resolvePaths(def.getTestFiles());
175  }
176}