001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2008-2011 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.api.batch.bootstrap; 021 022 import com.google.common.collect.Lists; 023 import org.apache.commons.lang.StringUtils; 024 import org.sonar.api.BatchComponent; 025 import org.sonar.api.CoreProperties; 026 027 import java.io.File; 028 import java.util.Arrays; 029 import java.util.List; 030 import java.util.Properties; 031 032 /** 033 * Defines project metadata (key, name, source directories, ...). It's generally used by the 034 * {@link org.sonar.api.batch.bootstrap.ProjectBuilder extension point} and must not be used 035 * by other standard extensions. 036 * 037 * @since 2.9 038 */ 039 public final class ProjectDefinition implements BatchComponent { 040 041 public static final String SOURCE_DIRS_PROPERTY = "sonar.sources"; 042 public static final String SOURCE_FILES_PROPERTY = "sonar.sourceFiles"; 043 public static final String TEST_DIRS_PROPERTY = "sonar.tests"; 044 public static final String TEST_FILES_PROPERTY = "sonar.testFiles"; 045 public static final String BINARIES_PROPERTY = "sonar.binaries"; 046 public static final String LIBRARIES_PROPERTY = "sonar.libraries"; 047 048 private static final char SEPARATOR = ','; 049 050 private File baseDir; 051 private File workDir; 052 private Properties properties = new Properties(); 053 private ProjectDefinition parent = null; 054 private List<ProjectDefinition> subProjects = Lists.newArrayList(); 055 private List<Object> containerExtensions = Lists.newArrayList(); 056 057 private ProjectDefinition(Properties p) { 058 this.properties = p; 059 } 060 061 public static ProjectDefinition create(Properties properties) { 062 return new ProjectDefinition(properties); 063 } 064 065 public static ProjectDefinition create() { 066 return new ProjectDefinition(new Properties()); 067 } 068 069 public ProjectDefinition setBaseDir(File baseDir) { 070 this.baseDir = baseDir; 071 return this; 072 } 073 074 public File getBaseDir() { 075 return baseDir; 076 } 077 public ProjectDefinition setWorkDir(File workDir) { 078 this.workDir = workDir; 079 return this; 080 } 081 082 public File getWorkDir() { 083 return workDir; 084 } 085 086 public Properties getProperties() { 087 return properties; 088 } 089 090 public ProjectDefinition setProperty(String key, String value) { 091 properties.setProperty(key, value); 092 return this; 093 } 094 095 public ProjectDefinition setKey(String key) { 096 properties.setProperty(CoreProperties.PROJECT_KEY_PROPERTY, key); 097 return this; 098 } 099 100 public ProjectDefinition setVersion(String s) { 101 properties.setProperty(CoreProperties.PROJECT_VERSION_PROPERTY, StringUtils.defaultString(s)); 102 return this; 103 } 104 105 public ProjectDefinition setName(String s) { 106 properties.setProperty(CoreProperties.PROJECT_NAME_PROPERTY, StringUtils.defaultString(s)); 107 return this; 108 } 109 110 public ProjectDefinition setDescription(String s) { 111 properties.setProperty(CoreProperties.PROJECT_DESCRIPTION_PROPERTY, StringUtils.defaultString(s)); 112 return this; 113 } 114 115 public String getKey() { 116 return properties.getProperty(CoreProperties.PROJECT_KEY_PROPERTY); 117 } 118 119 public String getVersion() { 120 return properties.getProperty(CoreProperties.PROJECT_VERSION_PROPERTY); 121 } 122 123 public String getName() { 124 String name = properties.getProperty(CoreProperties.PROJECT_NAME_PROPERTY); 125 if (StringUtils.isBlank(name)) { 126 name = "Unnamed - " + getKey(); 127 } 128 return name; 129 } 130 131 public String getDescription() { 132 return properties.getProperty(CoreProperties.PROJECT_DESCRIPTION_PROPERTY); 133 } 134 135 private void appendProperty(String key, String value) { 136 String newValue = properties.getProperty(key, "") + SEPARATOR + value; 137 properties.put(key, newValue); 138 } 139 140 public List<String> getSourceDirs() { 141 String sources = properties.getProperty(SOURCE_DIRS_PROPERTY, ""); 142 return Arrays.asList(StringUtils.split(sources, SEPARATOR)); 143 } 144 145 /** 146 * @param paths paths to directory with main sources. 147 * They can be absolute or relative to project base directory. 148 */ 149 public ProjectDefinition addSourceDirs(String... paths) { 150 for (String path : paths) { 151 appendProperty(SOURCE_DIRS_PROPERTY, path); 152 } 153 return this; 154 } 155 156 public ProjectDefinition addSourceDirs(File... dirs) { 157 for (File dir : dirs) { 158 addSourceDirs(dir.getAbsolutePath()); 159 } 160 return this; 161 } 162 163 public ProjectDefinition resetSourceDirs() { 164 properties.remove(SOURCE_DIRS_PROPERTY); 165 return this; 166 } 167 168 public ProjectDefinition setSourceDirs(String... paths) { 169 resetSourceDirs(); 170 return addSourceDirs(paths); 171 } 172 173 public ProjectDefinition setSourceDirs(File... dirs) { 174 resetSourceDirs(); 175 for (File dir : dirs) { 176 addSourceDirs(dir.getAbsolutePath()); 177 } 178 return this; 179 } 180 181 /** 182 * Adding source files is possible only if no source directories have been set. 183 * Absolute path or relative path from project base dir. 184 */ 185 public ProjectDefinition addSourceFiles(String... paths) { 186 for (String path : paths) { 187 appendProperty(SOURCE_FILES_PROPERTY, path); 188 } 189 return this; 190 } 191 192 /** 193 * Adding source files is possible only if no source directories have been set. 194 */ 195 public ProjectDefinition addSourceFiles(File... files) { 196 for (File file : files) { 197 addSourceFiles(file.getAbsolutePath()); 198 } 199 return this; 200 } 201 202 public List<String> getSourceFiles() { 203 String sources = properties.getProperty(SOURCE_FILES_PROPERTY, ""); 204 return Arrays.asList(StringUtils.split(sources, SEPARATOR)); 205 } 206 207 208 public List<String> getTestDirs() { 209 String sources = properties.getProperty(TEST_DIRS_PROPERTY, ""); 210 return Arrays.asList(StringUtils.split(sources, SEPARATOR)); 211 } 212 213 /** 214 * @param paths path to directory with test sources. 215 * It can be absolute or relative to project directory. 216 */ 217 public ProjectDefinition addTestDirs(String... paths) { 218 for (String path : paths) { 219 appendProperty(TEST_DIRS_PROPERTY, path); 220 } 221 return this; 222 } 223 224 public ProjectDefinition addTestDirs(File... dirs) { 225 for (File dir : dirs) { 226 addTestDirs(dir.getAbsolutePath()); 227 } 228 return this; 229 } 230 231 public ProjectDefinition setTestDirs(String... paths) { 232 resetTestDirs(); 233 return addTestDirs(paths); 234 } 235 236 public ProjectDefinition setTestDirs(File... dirs) { 237 resetTestDirs(); 238 for (File dir : dirs) { 239 addTestDirs(dir.getAbsolutePath()); 240 } 241 return this; 242 } 243 244 public ProjectDefinition resetTestDirs() { 245 properties.remove(TEST_DIRS_PROPERTY); 246 return this; 247 } 248 249 250 /** 251 * Adding source files is possible only if no source directories have been set. 252 * Absolute path or relative path from project base dir. 253 */ 254 public ProjectDefinition addTestFiles(String... paths) { 255 for (String path : paths) { 256 appendProperty(TEST_FILES_PROPERTY, path); 257 } 258 return this; 259 } 260 261 /** 262 * Adding source files is possible only if no source directories have been set. 263 */ 264 public ProjectDefinition addTestFiles(File... files) { 265 for (File file : files) { 266 addTestFiles(file.getAbsolutePath()); 267 } 268 return this; 269 } 270 271 public List<String> getTestFiles() { 272 String sources = properties.getProperty(TEST_FILES_PROPERTY, ""); 273 return Arrays.asList(StringUtils.split(sources, SEPARATOR)); 274 } 275 276 277 public List<String> getBinaries() { 278 String sources = properties.getProperty(BINARIES_PROPERTY, ""); 279 return Arrays.asList(StringUtils.split(sources, SEPARATOR)); 280 } 281 282 /** 283 * @param path path to directory with compiled source. In case of Java this is directory with class files. 284 * It can be absolute or relative to project directory. 285 * @TODO currently Sonar supports only one such directory due to dependency on MavenProject 286 */ 287 public ProjectDefinition addBinaryDir(String path) { 288 appendProperty(BINARIES_PROPERTY, path); 289 return this; 290 } 291 292 public ProjectDefinition addBinaryDir(File f) { 293 return addBinaryDir(f.getAbsolutePath()); 294 } 295 296 297 public List<String> getLibraries() { 298 String sources = properties.getProperty(LIBRARIES_PROPERTY, ""); 299 return Arrays.asList(StringUtils.split(sources, SEPARATOR)); 300 } 301 302 /** 303 * @param path path to file with third-party library. In case of Java this is path to jar file. 304 * It can be absolute or relative to project directory. 305 */ 306 public void addLibrary(String path) { 307 appendProperty(LIBRARIES_PROPERTY, path); 308 } 309 310 /** 311 * Adds an extension, which would be available in PicoContainer during analysis of this project. 312 * 313 * @since 2.8 314 */ 315 public ProjectDefinition addContainerExtension(Object extension) { 316 containerExtensions.add(extension); 317 return this; 318 } 319 320 /** 321 * @since 2.8 322 */ 323 public List<Object> getContainerExtensions() { 324 return containerExtensions; 325 } 326 327 /** 328 * @since 2.8 329 */ 330 public ProjectDefinition addSubProject(ProjectDefinition child) { 331 subProjects.add(child); 332 child.setParent(this); 333 return this; 334 } 335 336 public ProjectDefinition getParent() { 337 return parent; 338 } 339 340 private void setParent(ProjectDefinition parent) { 341 this.parent = parent; 342 } 343 344 /** 345 * @since 2.8 346 */ 347 public List<ProjectDefinition> getSubProjects() { 348 return subProjects; 349 } 350 }