/********************************************************************** * Copyright (c) 2005-2009 ant4eclipse project team. * * 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: * Nils Hartmann, Daniel Kasmeroglu, Gerd Wuetherich **********************************************************************/ package org.ant4eclipse.lib.pde.tools; import java.io.File; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import org.ant4eclipse.lib.core.Assure; import org.ant4eclipse.lib.pde.model.buildproperties.PluginBuildProperties; import org.ant4eclipse.lib.pde.model.buildproperties.PluginBuildProperties.Library; import org.ant4eclipse.lib.pde.model.pluginproject.PluginProjectRole; import org.ant4eclipse.lib.pde.tools.PluginProjectChecker.Issue.IssueLevel; import org.ant4eclipse.lib.platform.model.resource.EclipseProject; /** * <p> * The {@link PluginProjectChecker} can be used to check if a plug-in project contains inconsistent or erroneous build * property entries. * </p> * * @author Gerd Wütherich (gerd@gerd-wuetherich.de) */ public class PluginProjectChecker { /** the ERRONEOUS_PROJECT_DEFINITION_MSG */ private static String ERRONEOUS_PROJECT_DEFINITION_MSG = "Inconsistent or erroneous plug-in project definition for project '%1$s'. Reason:\n"; /** the MISSING_MANIFEST_FILE_MSG */ private static String MISSING_MANIFEST_FILE_MSG = ERRONEOUS_PROJECT_DEFINITION_MSG + "- Project must contain a bundle manifest file,\n" + "- e.g. '%2$s" + File.separator + "META-INF" + File.separator + "MANIFEST.MF'."; /** the MISSING_BIN_INCLUDE_ENTRY_FOR_MANIFEST_FILE_MSG */ private static String MISSING_BIN_INCLUDE_ENTRY_FOR_MANIFEST_FILE_MSG = ERRONEOUS_PROJECT_DEFINITION_MSG + "- Inconsistent build properties file '%2$s'.\n" + "- The build properties file must contain a 'bin.includes' entry for the META-INF directory ('META-INF/'). To fix this issue, please add an entry for the META-INF directory to the bin.includes list (e.g. 'bin.includes = META-INF/').\n"; /** the BIN_EXCLUDE_ENTRY_FOR_MANIFEST_FILE_MSG */ private static String BIN_EXCLUDE_ENTRY_FOR_MANIFEST_FILE_MSG = ERRONEOUS_PROJECT_DEFINITION_MSG + "- Inconsistent build properties file '%2$s'.\n" + "- The build properties must not contain a 'bin.excludes' entry for the manifest file ('bin.excludes = META-INF/MANIFEST.MF'). To fix this issue, please remove the META-INF/MANIFEST.MF entry from the bin.excludes list.\n"; /** the LIBRARY_WITHOUT_SOURCE_DIRECTORY */ private static final String LIBRARY_WITHOUT_SOURCE_DIRECTORY = ERRONEOUS_PROJECT_DEFINITION_MSG + "- Inconsistent build properties file '%2$s'.\n" + "- The build properties contains a library '%3$s' that doesn't contain a source directory. To fix this issue, please add a source directory to the library's source list 'source.%3$s'.\n"; /** the LIBRARY_WITHOUT_OUTPUT_DIRECTORY */ @SuppressWarnings("unused") private static final String LIBRARY_WITHOUT_OUTPUT_DIRECTORY = ERRONEOUS_PROJECT_DEFINITION_MSG + "- Inconsistent build properties file '%2$s'.\n" + "- The build properties contains a library '%3$s' that doesn't contain a output directory. To fix this issue, please add a output directory to the library's output list 'output.%3$s'.\n"; /** the eclipse project to check */ private EclipseProject _eclipseProject; /** the list of issues */ private List<Issue> _issues; private String _projectName; /** * <p> * Creates a new instance of type {@link PluginProjectChecker}. * </p> * * @param eclipseProject * the eclipse project to check. */ public PluginProjectChecker(EclipseProject eclipseProject) { Assure.notNull("eclipseProject", eclipseProject); this._eclipseProject = eclipseProject; this._issues = new LinkedList<Issue>(); this._projectName = this._eclipseProject.getSpecifiedName(); } /** * <p> * Checks the given eclipse plug-in project and returns a list of issues. * </p> * * @return a list of issues. */ public List<Issue> checkPluginProject() { // does the project has the PluginProjectRole? final boolean hasPluginProjectRole = this._eclipseProject.hasRole(PluginProjectRole.class); errorAssert(hasPluginProjectRole, "Project '%s' must have role 'PluginProjectRole'.", this._projectName); if (hasPluginProjectRole) { // it only makes sense to validate more, if the current project is a plug-in project PluginProjectRole pluginProjectRole = this._eclipseProject.getRole(PluginProjectRole.class); // make sure we have a build.properties-file final boolean hasBuildProperties = pluginProjectRole.hasBuildProperties(); errorAssert(hasBuildProperties, "Project '%s' must have a 'build.properties' file in it's root folder", this._projectName); if (hasBuildProperties) { final PluginBuildProperties buildProperties = pluginProjectRole.getBuildProperties(); validateManifestRelatedEntries(buildProperties); validateLibrariesRelatedEntries(buildProperties); } } // return the issue list return this._issues; } /** * */ private void validateManifestRelatedEntries(PluginBuildProperties buildProperties) { // does the project contain a manifest? errorAssert(this._eclipseProject.hasChild("META-INF/MANIFEST.MF"), MISSING_MANIFEST_FILE_MSG, this._projectName, this._eclipseProject.getFolder()); final List<String> binaryIncludesList = Arrays.asList(buildProperties.getBinaryIncludes()); final List<String> binaryExcludesList = Arrays.asList(buildProperties.getBinaryExcludes()); // does the build property file contain an entry for the META-INF directory? errorAssert(binaryIncludesList.contains("META-INF"), MISSING_BIN_INCLUDE_ENTRY_FOR_MANIFEST_FILE_MSG, this._projectName, this._eclipseProject.getChild("build.properties").getAbsolutePath()); // doesn't the binary excludes list contain an entry for the META-INF/MANIFEST.MF directory? errorAssert(!binaryExcludesList.contains("META-INF/MANIFEST.MF"), BIN_EXCLUDE_ENTRY_FOR_MANIFEST_FILE_MSG, this._projectName, this._eclipseProject.getChild("build.properties").getAbsolutePath()); } /** * <p> * </p> */ private void validateLibrariesRelatedEntries(PluginBuildProperties buildProperties) { // get all libraries Library[] libraries = buildProperties.getLibraries(); // iterate over the libraries for (Library library : libraries) { warningAssert(library.hasSource(), LIBRARY_WITHOUT_SOURCE_DIRECTORY, this._projectName, this._eclipseProject .getChild("build.properties").getAbsolutePath(), library.getName()); // warningAssert(library.hasOutput(), LIBRARY_WITHOUT_OUTPUT_DIRECTORY, _projectName, _eclipseProject.getChild( // "build.properties").getAbsolutePath(), library.getName()); } } /** * @param condition * @param msg * @param args */ private void errorAssert(boolean condition, String msg, Object... args) { validate(IssueLevel.ERROR, condition, msg, args); } /** * <p> * Adds an issue to the issue list if the given condition is false. * <p> * * @param condition * the condition * @param msg * the message * @param args * the args */ private void warningAssert(boolean condition, String msg, Object... args) { validate(IssueLevel.WARNING, condition, msg, args); } /** * @param level * @param condition * @param msg * @param args */ private void validate(IssueLevel level, boolean condition, String msg, Object... args) { if (!condition) { this._issues.add(new Issue(level, String.format(msg, args))); } } /** * <p> * Represents an issue. * </p> * * @author Gerd Wütherich (gerd@gerd-wuetherich.de) */ public static class Issue { /** * @author GWUETHER */ enum IssueLevel { WARNING, ERROR; } /** the message */ private String _message; /** the level */ @SuppressWarnings("unused") private IssueLevel _level; /** * <p> * Creates a new instance of type {@link Issue}. * </p> * * @param message * the message. */ public Issue(IssueLevel issueLevel, String message) { this._level = issueLevel; this._message = message; } /** * <p> * The message of the issue. * </p> * * @return the message. */ public String getMessage() { return this._message; } } }