/*****************************************************************************
* Copyright (c) 2006-2013, Cloudsmith Inc.
* The code, documentation and other materials contained herein have been
* licensed under the Eclipse Public License - v 1.0 by the copyright holder
* listed above, as the Initial Contributor under such license. The text of
* such license is available at www.eclipse.org.
*****************************************************************************/
package org.eclipse.buckminster.core.internal.actor;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import org.eclipse.buckminster.core.CorePlugin;
import org.eclipse.buckminster.core.Messages;
import org.eclipse.buckminster.core.actor.AbstractActor;
import org.eclipse.buckminster.core.actor.IActionContext;
import org.eclipse.buckminster.core.cspec.WellknownActions;
import org.eclipse.buckminster.core.metadata.WorkspaceInfo;
import org.eclipse.buckminster.runtime.MonitorUtils;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.osgi.util.NLS;
/**
* @author kolwing
*
*/
public abstract class AbstractBuildIntegrationActor extends AbstractActor {
public static final String PROPERTY_IGNORE_PROBLEMS = "buckminster.problems.ignore"; //$NON-NLS-1$
public static final String PROPERTY_EXCLUDE_BUILDERS = "buckminster.builders.exclude"; //$NON-NLS-1$
public static final String PROPERTY_INCLUDE_BUILDERS = "buckminster.builders.include"; //$NON-NLS-1$
private static void build(IProject project, int buildKind, ICommand[] buildSpec, IProgressMonitor buildMonitor) throws CoreException {
if (buildSpec == null) {
project.build(buildKind, buildMonitor);
} else {
buildMonitor.beginTask(NLS.bind(Messages.Building_0, project.getName()), buildSpec.length);
for (ICommand buildCommand : buildSpec) {
IProgressMonitor commandMonitor = MonitorUtils.subMonitor(buildMonitor, 1);
project.build(buildKind, buildCommand.getBuilderName(), buildCommand.getArguments(), commandMonitor);
commandMonitor.done();
}
buildMonitor.done();
}
}
private static ICommand[] filterBuildSpec(IProject project, Pattern[] includeBuilders, Pattern[] skipBuilders) throws CoreException {
if (includeBuilders == null && skipBuilders == null) {
return null;
}
ICommand[] buildSpec = project.getDescription().getBuildSpec();
int skipped = 0;
for (int i = 0; i < buildSpec.length; i++) {
ICommand buildCommand = buildSpec[i];
String builderName = buildCommand.getBuilderName();
if ((includeBuilders != null && !matches(builderName, includeBuilders)) || (skipBuilders != null && matches(builderName, skipBuilders))) {
skipped++;
} else if (skipped != 0) {
buildSpec[i - skipped] = buildCommand;
}
}
if (skipped != 0) {
ICommand[] filteredSpec = new ICommand[buildSpec.length - skipped];
System.arraycopy(buildSpec, 0, filteredSpec, 0, filteredSpec.length);
return filteredSpec;
}
return null;
}
private static Pattern[] getFilterPatterns(IActionContext ctx, String key) {
String filterSpecification = (String) ctx.getProperties().get(key);
if (filterSpecification == null)
return null;
String[] filterStrings = filterSpecification.split(","); //$NON-NLS-1$
Pattern[] filterPatterns = new Pattern[filterStrings.length];
for (int i = 0; i < filterStrings.length; i++) {
String filter = filterStrings[i].trim();
Pattern pattern = Pattern.compile(filter);
filterPatterns[i] = pattern;
}
return filterPatterns;
}
private static boolean isMarkerIgnored(IMarker problem, Pattern[] ignoreMarkerPatterns, Set<String> ignoreMarkerCache) throws CoreException {
if (ignoreMarkerPatterns == null) {
return false;
}
String markerType = problem.getType();
if (ignoreMarkerCache == null) {
return matches(markerType, ignoreMarkerPatterns);
}
if (ignoreMarkerCache.contains(markerType)) {
return true;
}
if (matches(markerType, ignoreMarkerPatterns)) {
ignoreMarkerCache.add(markerType);
return true;
}
return false;
}
private static boolean matches(String name, Pattern[] filterPatterns) {
for (Pattern pattern : filterPatterns) {
if (pattern.matcher(name).matches())
return true;
}
return false;
}
protected String getNameForKind(IActionContext ctx) {
return ctx.getAction().getName();
}
@Override
protected IStatus internalPerform(IActionContext ctx, IProgressMonitor monitor) throws CoreException {
monitor.beginTask(null, 300);
try {
IProject project = WorkspaceInfo.getProject(ctx.getCSpec().getComponentIdentifier());
if (project == null)
return Status.OK_STATUS;
project.refreshLocal(IResource.DEPTH_INFINITE, MonitorUtils.subMonitor(monitor, 100));
ICommand[] buildSpec = filterBuildSpec(project, getFilterPatterns(ctx, PROPERTY_INCLUDE_BUILDERS),
getFilterPatterns(ctx, PROPERTY_EXCLUDE_BUILDERS));
build(project, WellknownActions.ECLIPSE.name2Kind(getNameForKind(ctx)), buildSpec, MonitorUtils.subMonitor(monitor, 200));
Pattern[] ignoreMarkerPatterns = getFilterPatterns(ctx, PROPERTY_IGNORE_PROBLEMS);
Set<String> ignoreMarkerCache = ignoreMarkerPatterns == null ? null : new HashSet<String>();
for (IMarker problem : project.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE)) {
switch (problem.getAttribute(IMarker.SEVERITY, IMarker.SEVERITY_INFO)) {
case IMarker.SEVERITY_ERROR:
if (isMarkerIgnored(problem, ignoreMarkerPatterns, ignoreMarkerCache))
continue;
throw new CoreException(new Status(IStatus.ERROR, CorePlugin.getID(), IStatus.OK,
problem.getAttribute(IMarker.MESSAGE, ""), null)); //$NON-NLS-1$
case IMarker.SEVERITY_WARNING:
if (isMarkerIgnored(problem, ignoreMarkerPatterns, ignoreMarkerCache))
continue;
return new Status(IStatus.WARNING, CorePlugin.getID(), IStatus.OK, problem.getAttribute(IMarker.MESSAGE, ""), null); //$NON-NLS-1$
}
}
return Status.OK_STATUS;
} finally {
monitor.done();
}
}
}