/* * Created on 14 mai 2005 * * Copyright (c) 2005, PMD for Eclipse Development Team All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions * in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other * materials provided with the distribution. * The end-user documentation * included with the redistribution, if any, must include the following * acknowledgement: "This product includes software developed in part by * support from the Defense Advanced Research Project Agency (DARPA)" * * Neither the name of "PMD for Eclipse Development Team" nor the names of * its contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package net.sourceforge.pmd.eclipse; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import java.util.Collection; import java.util.Hashtable; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.CountDownLatch; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.eclipse.runtime.PMDRuntimeConstants; import net.sourceforge.pmd.eclipse.runtime.builder.PMDNature; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; /** * This is a utility class for Eclipse various operations * * @author Philippe Herlin * @author Brian Remedios */ public class EclipseUtils { static class OpenMonitor extends NullProgressMonitor { private final CountDownLatch latch; public OpenMonitor(final CountDownLatch latch) { this.latch = latch; } @Override public void done() { super.done(); latch.countDown(); } } /** * Because this class is a utility class, it cannot be instantiated */ private EclipseUtils() { super(); } /** * Test if 2 sets of rules are equals * * @param ruleSet1 * @param ruleSet2 * @return */ public static boolean assertRuleSetEquals(final Collection<Rule> ruleSet1, final Collection<Rule> ruleSet2, final PrintStream out) { boolean equals = true; for (final Iterator<Rule> i = ruleSet1.iterator(); i.hasNext() && equals;) { final Rule rule = i.next(); if (!searchRule(rule, ruleSet2, out)) { equals = false; System.out.println("Rule " + rule.getName() + " is not in the second ruleset"); } } for (final Iterator<Rule> i = ruleSet2.iterator(); i.hasNext() && equals;) { final Rule rule = i.next(); if (!searchRule(rule, ruleSet1, out)) { equals = false; System.out.println("Rule " + rule.getName() + " is not in the first ruleset"); } } return equals; } /** * Create a new java project * * @param projectName a project name * @return newProject a new project resource handle */ public static IProject createJavaProject(final String projectName) throws CoreException { final IProject newProject = createProject(projectName); // 4. Make it a Java Project addJavaNature(newProject); return newProject; } public static IProject createProject(final String projectName) throws CoreException { // 1. Get the project from the workspace final IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); final IProject newProject = root.getProject(projectName); final IProjectDescription description = newProject.getWorkspace().newProjectDescription(projectName); // 2. Create a project if it does not already exist if (!newProject.exists()) { description.setLocation(null); newProject.create(description, null); } if (!newProject.isOpen()) { newProject.open(null); } return newProject; } /** * Create a test source file * * @param project a project where to create that file; this project is * expected to be empty */ public static IFile createTestSourceFile(final IProject project) throws JavaModelException, CoreException, IOException { // 1. Locate the test java source template final InputStream is = EclipseUtils.class.getResourceAsStream("/test.template"); // 2. Copy the template inside the source directory final IFile sourceFile = project.getFile("/src/Test.java"); if (sourceFile.exists() && sourceFile.isAccessible()) { sourceFile.setContents(is, true, false, null); } else { sourceFile.create(is, true, null); } is.close(); project.refreshLocal(IResource.DEPTH_INFINITE, null); return sourceFile; } /** * Get the content of a project resource. * * @param project a project reference * @param resourceName the name of the resource (@see IProject) * @return the resource content as an InputStream or null * @throws CoreException */ public static InputStream getResourceStream(final IProject project, final String resourceName) throws CoreException { final IFile file = project.getFile(resourceName); return file != null && file.exists() && file.isAccessible() ? file.getContents(true) : null; } /** * Remove the PMD Nature from a project * * @param project a project to remove the PMD Nature * @param monitor a progress monitor * @return success true if the nature has been removed; false means the * project already had not the PMD Nature. * @throws CoreException if any error occurs. */ public static boolean removePMDNature(final IProject project) throws CoreException { final boolean success = false; if (project.hasNature(PMDNature.PMD_NATURE)) { final IProjectDescription description = project.getDescription(); final String[] natureIds = description.getNatureIds(); final String[] newNatureIds = new String[natureIds.length - 1]; for (int i = 0, j = 0; i < natureIds.length; i++) { if (!natureIds[i].equals(PMDNature.PMD_NATURE)) { newNatureIds[j++] = natureIds[i]; } } description.setNatureIds(newNatureIds); project.setDescription(description, null); project.deleteMarkers(PMDRuntimeConstants.PMD_MARKER, true, IResource.DEPTH_INFINITE); final IFile file = project.getFile(".pmd"); if (file.exists() && file.isAccessible()) { file.delete(true, false, null); } } return success; } /** * Add a Java Nature to a project when creating * * @param project * @throws CoreException */ private static void addJavaNature(final IProject project) throws CoreException { if (!project.hasNature(JavaCore.NATURE_ID)) { final IProjectDescription description = project.getDescription(); final String[] prevNatures = description.getNatureIds(); final String[] newNatures = new String[prevNatures.length + 1]; System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length); newNatures[prevNatures.length] = JavaCore.NATURE_ID; description.setNatureIds(newNatures); project.setDescription(description, null); IFolder sourceFolder = project.getFolder("/src"); sourceFolder.create(true, true, null); IJavaProject javaProject = JavaCore.create(project); javaProject.setRawClasspath(new IClasspathEntry[] { JavaCore.newSourceEntry(sourceFolder.getFullPath()), JavaCore.newContainerEntry(new Path("org.eclipse.jdt.launching.JRE_CONTAINER")) }, null); @SuppressWarnings("unchecked") Hashtable<String, String> javaOptions = JavaCore.getOptions(); javaOptions.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_5); javaOptions.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_5); javaOptions.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_5); javaProject.setOptions(javaOptions); } } /** * Print rule details * * @param rule */ private static void dumpRule(final Rule rule, final PrintStream out) { out.println("Rule: " + rule.getName()); out.println("Priority: " + rule.getPriority()); final Map<PropertyDescriptor< ? >, Object> properties = rule.getPropertiesByPropertyDescriptor(); final Set<Entry<PropertyDescriptor< ? >, Object>> keys = properties.entrySet(); for (final Entry<PropertyDescriptor< ? >, Object> entry : keys) { out.println(" " + entry.getKey().name() + " = " + entry.getValue()); } } private static boolean propertiesMatchFor(final Rule ruleA, final Rule ruleB) { return ruleA.getPropertiesByPropertyDescriptor().equals(ruleB.getPropertiesByPropertyDescriptor()); } /** * Search a rule in a set of rules * * @param rule * @param set * @return */ private static boolean searchRule(final Rule rule, final Collection<Rule> set, final PrintStream out) { boolean found = false; for (final Iterator<Rule> i = set.iterator(); i.hasNext() && !found;) { final Rule r = i.next(); if (r.getClass().getName().equals(rule.getClass().getName())) { found = r.getName().equals(rule.getName()) && propertiesMatchFor(r, rule) && r.getPriority() == rule.getPriority(); if (!found && r.getName().equals(rule.getName())) { out.println("Rules " + r.getName() + " are different because:"); out.println("Priorities are different: " + (r.getPriority() != rule.getPriority())); out.println("Properties are different: " + !propertiesMatchFor(r, rule)); out.println(); out.println("Rule to search"); dumpRule(rule, out); out.println(); out.println("Rule from set"); dumpRule(r, out); out.println(); } } } return found; } /** * @param testProject * @param string * @param string2 * @return * @throws CoreException * @throws IOException */ public static IFile createTestSourceFile(IProject testProject, String fileName, String content) throws CoreException, IOException { IFile sourceFile = testProject.getFile(fileName); InputStream is = new ByteArrayInputStream(content.getBytes("UTF-8")); if (sourceFile.exists() && sourceFile.isAccessible()) { sourceFile.setContents(is, true, false, null); } else { sourceFile.create(is, true, null); } is.close(); return sourceFile; } }