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.batch; 021 022 import java.io.File; 023 import java.io.IOException; 024 import java.util.List; 025 import java.util.Map; 026 027 import org.apache.maven.project.MavenProject; 028 import org.sonar.api.batch.bootstrap.ProjectDefinition; 029 import org.sonar.api.utils.SonarException; 030 031 import com.google.common.collect.Maps; 032 033 public final class MavenProjectConverter { 034 035 private static final String UNABLE_TO_DETERMINE_PROJECT_STRUCTURE_EXCEPTION_MESSAGE = "Unable to determine structure of project." + 036 " Probably you use Maven Advanced Reactor Options, which is not supported by Sonar and should not be used."; 037 038 public static ProjectDefinition convert(List<MavenProject> poms, MavenProject root) { 039 Map<String, MavenProject> paths = Maps.newHashMap(); // projects by canonical path to pom.xml 040 Map<MavenProject, ProjectDefinition> defs = Maps.newHashMap(); 041 042 try { 043 for (MavenProject pom : poms) { 044 paths.put(pom.getFile().getCanonicalPath(), pom); 045 defs.put(pom, convert(pom)); 046 } 047 048 for (Map.Entry<String, MavenProject> entry : paths.entrySet()) { 049 MavenProject pom = entry.getValue(); 050 for (Object m : pom.getModules()) { 051 String moduleId = (String) m; 052 File modulePath = new File(pom.getBasedir(), moduleId); 053 if (modulePath.exists() && modulePath.isDirectory()) { 054 modulePath = new File(modulePath, "pom.xml"); 055 } 056 MavenProject module = paths.get(modulePath.getCanonicalPath()); 057 058 ProjectDefinition parentProject = defs.get(pom); 059 ProjectDefinition subProject = defs.get(module); 060 if (parentProject == null) { 061 throw new IllegalStateException(UNABLE_TO_DETERMINE_PROJECT_STRUCTURE_EXCEPTION_MESSAGE); 062 } 063 if (subProject == null) { 064 throw new IllegalStateException(UNABLE_TO_DETERMINE_PROJECT_STRUCTURE_EXCEPTION_MESSAGE); 065 } 066 parentProject.addSubProject(subProject); 067 } 068 } 069 } catch (IOException e) { 070 throw new SonarException(e); 071 } 072 073 ProjectDefinition rootProject = defs.get(root); 074 if (rootProject == null) { 075 throw new IllegalStateException(UNABLE_TO_DETERMINE_PROJECT_STRUCTURE_EXCEPTION_MESSAGE); 076 } 077 078 return rootProject; 079 } 080 081 /** 082 * Visibility has been relaxed for tests. 083 */ 084 static ProjectDefinition convert(MavenProject pom) { 085 String key = new StringBuilder().append(pom.getGroupId()).append(":").append(pom.getArtifactId()).toString(); 086 ProjectDefinition definition = ProjectDefinition.create(); 087 // IMPORTANT NOTE : reference on properties from POM model must not be saved, instead they should be copied explicitly - see SONAR-2896 088 definition 089 .setProperties(pom.getModel().getProperties()) 090 .setKey(key) 091 .setVersion(pom.getVersion()) 092 .setName(pom.getName()) 093 .setDescription(pom.getDescription()) 094 .addContainerExtension(pom); 095 synchronizeFileSystem(pom, definition); 096 return definition; 097 } 098 099 public static void synchronizeFileSystem(MavenProject pom, ProjectDefinition into) { 100 into.setBaseDir(pom.getBasedir()); 101 into.setWorkDir(new File(resolvePath(pom.getBuild().getDirectory(), pom.getBasedir()), "sonar")); 102 into.setSourceDirs((String[]) pom.getCompileSourceRoots().toArray(new String[pom.getCompileSourceRoots().size()])); 103 into.setTestDirs((String[]) pom.getTestCompileSourceRoots().toArray(new String[pom.getTestCompileSourceRoots().size()])); 104 } 105 106 static File resolvePath(String path, File basedir) { 107 File file = new File(path); 108 if (!file.isAbsolute()) { 109 try { 110 file = new File(basedir, path).getCanonicalFile(); 111 } catch (IOException e) { 112 throw new SonarException("Unable to resolve path '" + path + "'", e); 113 } 114 } 115 return file; 116 } 117 118 private MavenProjectConverter() { 119 // only static methods 120 } 121 }