/******************************************************************************* * Copyright (c) 2008-2010 Sonatype, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Sonatype, Inc. - initial API and implementation *******************************************************************************/ package org.eclipse.m2e.core.project; import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.osgi.util.NLS; import org.apache.maven.model.Model; import org.apache.maven.model.Profile; import org.eclipse.m2e.core.embedder.MavenModelManager; import org.eclipse.m2e.core.internal.IMavenConstants; import org.eclipse.m2e.core.internal.Messages; /** * @author Eugene Kuleshov */ public class LocalProjectScanner extends AbstractProjectScanner<MavenProjectInfo> { private final File workspaceRoot; private final List<String> folders; private final boolean basedirRemameRequired; private Set<File> scannedFolders = new HashSet<File>(); private final MavenModelManager modelManager; public LocalProjectScanner(File workspaceRoot, String folder, boolean needsRename, MavenModelManager modelManager) { this(workspaceRoot, Collections.singletonList(folder), needsRename, modelManager); } public LocalProjectScanner(File workspaceRoot, List<String> folders, boolean basedirRemameRequired, MavenModelManager modelManager) { this.workspaceRoot = workspaceRoot; this.folders = folders; this.basedirRemameRequired = basedirRemameRequired; this.modelManager = modelManager; } public void run(IProgressMonitor monitor) throws InterruptedException { SubMonitor subMonitor = SubMonitor.convert(monitor, Messages.LocalProjectScanner_task_scanning, 1); subMonitor.beginTask(Messages.LocalProjectScanner_task_scanning, IProgressMonitor.UNKNOWN); try { for(String folderName : folders) { try { File folder = new File(folderName).getCanonicalFile(); scanFolder(folder, "", new SubProgressMonitor(subMonitor, IProgressMonitor.UNKNOWN)); //$NON-NLS-1$ } catch(IOException ex) { addError(ex); } } } finally { subMonitor.done(); } } private void scanFolder(File baseDir, String rootRelPath, IProgressMonitor monitor) throws InterruptedException { if(monitor.isCanceled()) { throw new InterruptedException(); } monitor.subTask(baseDir.toString()); monitor.worked(1); // Don't scan the .metadata folder if(!baseDir.exists() || !baseDir.isDirectory() || IMavenConstants.METADATA_FOLDER.equals(baseDir.getName())) { return; } try { if(scannedFolders.contains(baseDir.getCanonicalFile())) { return; } } catch(IOException ex1) { addError(ex1); return; } MavenProjectInfo projectInfo = readMavenProjectInfo(baseDir, rootRelPath, null); //$NON-NLS-1$ if(projectInfo != null) { addProject(projectInfo); return; // don't scan subfolders of the Maven project } File[] files = baseDir.listFiles(); if(files == null) { addError(new Exception(NLS.bind(Messages.LocalProjectScanner_accessDeniedFromFolder, baseDir.getAbsolutePath()))); return; } for(int i = 0; i < files.length; i++ ) { File file; try { file = files[i].getCanonicalFile(); if(file.isDirectory()) { scanFolder(file, rootRelPath + "/" + file.getName(), monitor); //$NON-NLS-1$ } } catch(IOException ex) { addError(ex); } } } private MavenProjectInfo readMavenProjectInfo(File baseDir, String modulePath, MavenProjectInfo parentInfo) { try { baseDir = baseDir.getCanonicalFile(); File pomFile = new File(baseDir, IMavenConstants.POM_FILE_NAME); if(!pomFile.exists()) { return null; } if(!scannedFolders.add(baseDir)) { return null; // we already know this project //mkleint: well, if the project is first scanned standalone and later scanned via parent reference, the parent ref gets thrown away?? } Model model = modelManager.readMavenModel(pomFile); String pomName = modulePath + "/" + IMavenConstants.POM_FILE_NAME; //$NON-NLS-1$ MavenProjectInfo projectInfo = newMavenProjectInfo(pomName, pomFile, model, parentInfo); //We only want to optionally rename the base directory not any sub directory if(parentInfo == null) { projectInfo.setBasedirRename(getBasedirRename(projectInfo)); } Map<String, Set<String>> modules = new LinkedHashMap<String, Set<String>>(); for(String module : model.getModules()) { if(module.endsWith("/pom.xml")) { //$NON-NLS-1$ module = module.substring(0, module.length() - "/pom.xml".length()); //$NON-NLS-1$ } modules.put(module, new HashSet<String>()); } for(Profile profile : model.getProfiles()) { for(String module : profile.getModules()) { if(module.endsWith("/pom.xml")) { //$NON-NLS-1$ module = module.substring(0, module.length() - "/pom.xml".length()); //$NON-NLS-1$ } Set<String> profiles = modules.get(module); if(profiles == null) { profiles = new HashSet<String>(); modules.put(module, profiles); } profiles.add(profile.getId()); } } for(Map.Entry<String, Set<String>> e : modules.entrySet()) { String module = e.getKey(); Set<String> profiles = e.getValue(); File moduleBaseDir = new File(baseDir, module); MavenProjectInfo moduleInfo = readMavenProjectInfo(moduleBaseDir, module, projectInfo); if(moduleInfo != null) { moduleInfo.addProfiles(profiles); projectInfo.add(moduleInfo); } } return projectInfo; } catch(CoreException ex) { addError(ex); } catch(IOException ex) { addError(ex); } return null; } protected MavenProjectInfo newMavenProjectInfo(String label, File pomFile, Model model, MavenProjectInfo parent) { return new MavenProjectInfo(label, pomFile, model, parent); } public String getDescription() { return folders.toString(); } private int getBasedirRename(MavenProjectInfo mavenProjectInfo) throws IOException { if(basedirRemameRequired) { return MavenProjectInfo.RENAME_REQUIRED; } return MavenProjectInfo.RENAME_NO; } }