/******************************************************************************* * Copyright (c) 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.internal; import java.io.File; import java.util.Collection; import java.util.ConcurrentModificationException; import java.util.HashSet; import java.util.Properties; import java.util.Set; import java.util.Stack; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.apache.maven.model.Plugin; import org.apache.maven.project.MavenProject; import org.eclipse.m2e.core.project.configurator.MojoExecutionKey; public class M2EUtils { /** * Helper method which creates a folder and, recursively, all its parent folders. * * @param folder The folder to create. * @param derived true if folder should be marked as derived * @throws CoreException if creating the given <code>folder</code> or any of its parents fails. * @deprecated use {@link #createFolder(IFolder, boolean, IProgressMonitor)} */ public static void createFolder(IFolder folder, boolean derived) throws CoreException { createFolder(folder, derived, new NullProgressMonitor()); } /** * Helper method which creates a folder and, recursively, all its parent folders. * * @param folder The folder to create. * @param derived true if folder should be marked as derived * @param monitor the progress monitor * @throws CoreException if creating the given <code>folder</code> or any of its parents fails. */ public static void createFolder(IFolder folder, boolean derived, IProgressMonitor monitor) throws CoreException { // Recurse until we find a parent folder which already exists. if(!folder.exists()) { IContainer parent = folder.getParent(); // First, make sure that all parent folders exist. if(parent != null && !parent.exists()) { createFolder((IFolder) parent, false, monitor); } folder.create(true, true, null); } if(folder.isAccessible() && derived) { folder.setDerived(true, monitor); } } public static String getRootCauseMessage(Throwable t) { Throwable root = getRootCause(t); if(t == null) { return null; } return root.getMessage(); } public static Throwable getRootCause(Throwable ex) { if(ex == null) { return null; } Throwable rootCause = ex; Throwable cause = rootCause.getCause(); while(cause != null && cause != rootCause) { rootCause = cause; cause = cause.getCause(); } return cause == null ? rootCause : cause; } /* * Find the pom associated with a MavenProject */ public static IFile getPomFile(MavenProject project) { if(project == null || project.getFile() == null) { return null; } //XXX copied from XmlUtils.extractProject() File file = new File(project.getFile().toURI()); IPath path = Path.fromOSString(file.getAbsolutePath()); Stack<IFile> stack = new Stack<IFile>(); //here we need to find the most inner project to the path. //we do so by shortening the path and remembering all the resources identified. // at the end we pick the last one from the stack. is there a catch to it? IFile ifile = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(path); if(ifile != null) { stack.push(ifile); } while(path.segmentCount() > 1) { IResource ires = ResourcesPlugin.getWorkspace().getRoot().findMember(path); if(ires != null && ires instanceof IFile) { stack.push((IFile) ires); } path = path.removeFirstSegments(1); } return stack.empty() ? null : stack.pop(); } public static Collection<MavenProject> getDefiningProjects(MojoExecutionKey key, Collection<MavenProject> projects) { Set<MavenProject> sourceProjects = new HashSet<MavenProject>(); for(MavenProject project : projects) { if(definesPlugin(project, key)) { sourceProjects.add(project); continue; } for(MavenProject parent = project.getParent(); parent != null; parent = parent.getParent()) { if(definesPlugin(parent, key)) { sourceProjects.add(parent); // Only the first instance is necessary break; } } } return sourceProjects; } public static boolean definesPlugin(MavenProject project, MojoExecutionKey key) { if(project.getOriginalModel().getBuild() == null) { return false; } for(Plugin p : project.getOriginalModel().getBuild().getPlugins()) { if(p.getGroupId().equals(key.getGroupId()) && p.getArtifactId().equals(key.getArtifactId())) { return true; } } return false; } /** * Thread-safe properties copy implementation. * <p> * {@link Properties#entrySet()} iterator is not thread safe and fails with {@link ConcurrentModificationException} if * the source properties "is structurally modified at any time after the iterator is created". The solution is to use * thread-safe {@link Properties#stringPropertyNames()} enumerate and copy properties. * * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=440696 * @since 1.6 */ public static void copyProperties(Properties to, Properties from) { for(String key : from.stringPropertyNames()) { String value = from.getProperty(key); if(value != null) { to.put(key, value); } } } }