/*******************************************************************************
* Copyright (c) 2000, 2010 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River) - [198591] Allow Builder to specify scheduling rule
* Anton Leherbauer (Wind River) - [305858] Allow Builder to return null rule
* James Blackburn (Broadcom) - [306822] Provide Context for Builder getRule()
*******************************************************************************/
package org.eclipse.core.resources;
import java.util.Map;
import org.eclipse.core.internal.events.InternalBuilder;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
/**
* The abstract base class for all incremental project builders. This class provides the
* infrastructure for defining a builder and fulfills the contract specified by the
* <code>org.eclipse.core.resources.builders</code> standard extension point.
* <p>
* All builders must subclass this class according to the following guidelines:
* <ul>
* <li>must re-implement at least <code>build</code></li>
* <li>may implement other methods</li>
* <li>must supply a public, no-argument constructor</li>
* </ul>
* On creation, the <code>setInitializationData</code> method is called with any parameter data
* specified in the declaring plug-in's manifest.
*/
public abstract class IncrementalProjectBuilder extends InternalBuilder implements IExecutableExtension {
/**
* Build kind constant (value 6) indicating a full build request. A full build discards all
* previously built state and builds all resources again. Resource deltas are not applicable for
* this kind of build.
*
* @see IProject#build(int, IProgressMonitor)
* @see IProject#build(int, String, Map, IProgressMonitor)
* @see IWorkspace#build(int, IProgressMonitor)
*/
public static final int FULL_BUILD= 6;
/**
* Build kind constant (value 9) indicating an automatic build request. When autobuild is turned
* on, these builds are triggered automatically whenever resources change. Apart from the method
* by which autobuilds are triggered, they otherwise operate like an incremental build.
*
* @see IWorkspaceDescription#setAutoBuilding(boolean)
* @see IWorkspace#isAutoBuilding()
*/
public static final int AUTO_BUILD= 9;
/**
* Build kind constant (value 10) indicating an incremental build request. Incremental builds
* use an {@link IResourceDelta} that describes what resources have changed since the last
* build. The builder calculates what resources are affected by the delta, and rebuilds the
* affected resources.
*
* @see IProject#build(int, IProgressMonitor)
* @see IProject#build(int, String, Map, IProgressMonitor)
* @see IWorkspace#build(int, IProgressMonitor)
*/
public static final int INCREMENTAL_BUILD= 10;
/**
* Build kind constant (value 15) indicating a clean build request. A clean build discards any
* additional state that has been computed as a result of previous builds, and returns the
* project to a clean slate. Resource deltas are not applicable for this kind of build.
*
* @see IProject#build(int, IProgressMonitor)
* @see IProject#build(int, String, Map, IProgressMonitor)
* @see IWorkspace#build(int, IProgressMonitor)
* @see #clean(IProgressMonitor)
* @since 3.0
*/
public static final int CLEAN_BUILD= 15;
/**
* Runs this builder in the specified manner. Subclasses should implement this method to do the
* processing they require.
* <p>
* If the build kind is {@link #INCREMENTAL_BUILD} or {@link #AUTO_BUILD}, the
* <code>getDelta</code> method can be used during the invocation of this method to obtain
* information about what changes have occurred since the last invocation of this method. Any
* resource delta acquired is valid only for the duration of the invocation of this method.
* </p>
* <p>
* After completing a build, this builder may return a list of projects for which it requires a
* resource delta the next time it is run. This builder's project is implicitly included and
* need not be specified. The build mechanism will attempt to maintain and compute deltas
* relative to the identified projects when asked the next time this builder is run. Builders
* must re-specify the list of interesting projects every time they are run as this is not
* carried forward beyond the next build. Projects mentioned in return value but which do not
* exist will be ignored and no delta will be made available for them.
* </p>
* <p>
* This method is long-running; progress and cancellation are provided by the given progress
* monitor. All builders should report their progress and honor cancel requests in a timely
* manner. Cancelation requests should be propagated to the caller by throwing
* <code>OperationCanceledException</code>.
* </p>
* <p>
* All builders should try to be robust in the face of trouble. In situations where failing the
* build by throwing <code>CoreException</code> is the only option, a builder has a choice of
* how best to communicate the problem back to the caller. One option is to use the
* {@link IResourceStatus#BUILD_FAILED} status code along with a suitable message; another is to
* use a {@link MultiStatus} containing finer-grained problem diagnoses.
* </p>
*
* @param kind the kind of build being requested. Valid values are
* <ul>
* <li>{@link #FULL_BUILD} - indicates a full build.</li>
* <li>{@link #INCREMENTAL_BUILD}- indicates an incremental build.</li>
* <li>{@link #AUTO_BUILD} - indicates an automatically triggered incremental build
* (autobuilding on).</li>
* </ul>
* @param args a table of builder-specific arguments keyed by argument name (key type:
* <code>String</code>, value type: <code>String</code>); <code>null</code> is
* equivalent to an empty map
* @param monitor a progress monitor, or <code>null</code> if progress reporting and
* cancellation are not desired
* @return the list of projects for which this builder would like deltas the next time it is run
* or <code>null</code> if none
* @exception CoreException if this build fails.
* @see IProject#build(int, String, Map, IProgressMonitor)
*/
protected abstract IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException;
/**
* Clean is an opportunity for a builder to discard any additional state that has been computed
* as a result of previous builds. It is recommended that builders override this method to
* delete all derived resources created by previous builds, and to remove all markers of type
* {@link IMarker#PROBLEM} that were created by previous invocations of the builder. The
* platform will take care of discarding the builder's last built state (there is no need to
* call <code>forgetLastBuiltState</code>). </p>
* <p>
* This method is called as a result of invocations of <code>IWorkspace.build</code> or
* <code>IProject.build</code> where the build kind is {@link #CLEAN_BUILD}.
* <p>
* This default implementation does nothing. Subclasses may override.
* <p>
* This method is long-running; progress and cancellation are provided by the given progress
* monitor. All builders should report their progress and honor cancel requests in a timely
* manner. Cancelation requests should be propagated to the caller by throwing
* <code>OperationCanceledException</code>.
* </p>
*
* @param monitor a progress monitor, or <code>null</code> if progress reporting and
* cancellation are not desired
* @exception CoreException if this build fails.
* @see IWorkspace#build(int, IProgressMonitor)
* @see #CLEAN_BUILD
* @since 3.0
*/
protected void clean(IProgressMonitor monitor) throws CoreException {
//default implementation does nothing
//thwart compiler warning
}
/**
* Requests that this builder forget any state it may be retaining regarding previously built
* states. Typically this means that the next time the builder runs, it will have to do a full
* build since it does not have any state upon which to base an incremental build.
*/
public final void forgetLastBuiltState() {
super.forgetLastBuiltState();
}
/**
* Returns the build command associated with this builder. The returned command may or may not
* be in the build specification for the project on which this builder operates.
* <p>
* Any changes made to the returned command will only take effect if the modified command is
* installed on a project build spec.
* </p>
*
* @see IProjectDescription#setBuildSpec(ICommand [])
* @see IProject#setDescription(IProjectDescription, int, IProgressMonitor)
* @since 3.1
*/
public final ICommand getCommand() {
return super.getCommand();
}
/**
* Returns the resource delta recording the changes in the given project since the last time
* this builder was run. <code>null</code> is returned if no such delta is available. An empty
* delta is returned if no changes have occurred, or if deltas are not applicable for the
* current build kind. If <code>null</code> is returned, clients should assume that unspecified
* changes have occurred and take the appropriate action.
* <p>
* The system reserves the right to trim old state in an effort to conserve space. As such,
* callers should be prepared to receive <code>null</code> even if they previously requested a
* delta for a particular project by returning that project from a <code>build</code> call.
* </p>
* <p>
* A non- <code>null</code> delta will only be supplied for the given project if either the
* result returned from the previous <code>build</code> included the project or the project is
* the one associated with this builder.
* </p>
* <p>
* If the given project was mentioned in the previous <code>build</code> and subsequently
* deleted, a non- <code>null</code> delta containing the deletion will be returned. If the
* given project was mentioned in the previous <code>build</code> and was subsequently created,
* the returned value will be <code>null</code>.
* </p>
* <p>
* A valid delta will be returned only when this method is called during a build. The delta
* returned will be valid only for the duration of the enclosing build execution.
* </p>
* <p>
* The delta does not include changes made while this builder is running. If
* {@link #getRule(int, Map)} is overridden to return a scheduling rule other than the workspace
* root, changes performed in other threads during the build will not appear in the resource
* delta.
* </p>
*
* @return the resource delta for the project or <code>null</code>
*/
public final IResourceDelta getDelta(IProject project) {
return super.getDelta(project);
}
/**
* Returns the project for which this builder is defined.
*
* @return the project
*/
public final IProject getProject() {
return super.getProject();
}
/**
* Returns whether the given project has already been built during this build iteration.
* <p>
* When the entire workspace is being built, the projects are built in linear sequence. This
* method can be used to determine if another project precedes this builder's project in that
* build sequence. If only a single project is being built, then there is no build order and
* this method will always return <code>false</code>.
* </p>
*
* @param project the project to check against in the current build order
* @return <code>true</code> if the given project has been built in this iteration, and
* <code>false</code> otherwise.
* @see #needRebuild()
* @since 2.1
*/
public final boolean hasBeenBuilt(IProject project) {
return super.hasBeenBuilt(project);
}
/**
* Returns whether an interrupt request has been made for this build. Background autobuild is
* interrupted when another thread tries to modify the workspace concurrently with the build
* thread. When this occurs, the build cycle is flagged as interrupted and the build will be
* terminated at the earliest opportunity. This method allows long running builders to respond
* to this interruption in a timely manner. Builders are not required to respond to interruption
* requests.
* <p>
*
* @return <code>true</code> if the build cycle has been interrupted, and <code>false</code>
* otherwise.
* @since 3.0
*/
public final boolean isInterrupted() {
return super.isInterrupted();
}
/**
* Indicates that this builder made changes that affect a project that precedes this project in
* the currently executing build order, and thus a rebuild will be necessary.
* <p>
* This is an advanced feature that builders should use with caution. This can cause workspace
* builds to iterate until no more builders require rebuilds.
* </p>
*
* @see #hasBeenBuilt(IProject)
* @since 2.1
*/
public final void needRebuild() {
super.needRebuild();
}
/**
* Sets initialization data for this builder.
* <p>
* This method is part of the {@link IExecutableExtension} interface.
* </p>
* <p>
* Subclasses are free to extend this method to pick up initialization parameters from the
* plug-in plug-in manifest (<code>plugin.xml</code>) file, but should be sure to invoke this
* method on their superclass.
* <p>
* For example, the following method looks for a boolean-valued parameter named "trace":
*
* <pre>
* public void setInitializationData(IConfigurationElement cfig, String propertyName, Object data) throws CoreException {
* super.setInitializationData(cfig, propertyName, data);
* if (data instanceof Hashtable) {
* Hashtable args= (Hashtable)data;
* String traceValue= (String)args.get("trace");
* TRACING= (traceValue != null && traceValue.equals("true"));
* }
* }
* </pre>
*
* </p>
*
* @throws CoreException if fails.
*/
public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
//default implementation does nothing
//thwart compiler warning
}
/**
* Informs this builder that it is being started by the build management infrastructure. By the
* time this method is run, the builder's project is available and
* <code>setInitializationData</code> has been called. The default implementation should be
* called by all overriding methods.
*
* @see #setInitializationData(IConfigurationElement, String, Object)
*/
protected void startupOnInitialize() {
// reserved for future use
}
/**
* Returns the scheduling rule that is required for building the project for which this builder
* is defined. The default is the workspace root rule.
*
* @return a scheduling rule which is contained in the workspace root rule or <code>null</code>
* @since 3.5
* @see #getRule(int, Map)
* @deprecated clients should call and override {@link #getRule(int, Map)} instead.
*/
public ISchedulingRule getRule() {
return ResourcesPlugin.getWorkspace().getRoot();
}
/**
* Returns the scheduling rule that is required for building the project for which this builder
* is defined. The default is {@link #getRule()}, which returns the workspace root rule unless
* overridden.
* <p>
* The scheduling rule determines which resources in the workspace are protected from being
* modified by other threads while the builder is running. Up until Eclipse 3.5, the entire
* workspace was always locked during a build; since Eclipse 3.6, builders can allow resources
* outside their scheduling rule to be modified.
* <p>
* <strong>Notes:</strong>
* <ul>
* <li>
* If the builder rule is non-<code>null</code> it must be "contained" in the workspace root
* rule. I.e. {@link ISchedulingRule#contains(ISchedulingRule)} must return <code>true</code>
* when invoked on the workspace root with the builder rule.</li>
* <li>
* The rule returned here may have no effect if the build is invoked within the scope of another
* operation that locks the entire workspace.</li>
* <li>
* If this method returns any rule other than the workspace root, resources outside of the rule
* scope can be modified concurrently with the build. The delta returned by
* {@link #getDelta(IProject)} for any project outside the scope of the builder's rule may not
* contain changes that occurred concurrently with the build.
* </ul>
* </p>
* <p>
* Subclasses may override this method.
* </p>
*
* @noreference This method is not intended to be referenced by clients.
*
* @param kind the kind of build being requested. Valid values include:
* <ul>
* <li>{@link #FULL_BUILD} - indicates a full build.</li>
* <li>{@link #INCREMENTAL_BUILD} - indicates an incremental build.</li>
* <li>{@link #AUTO_BUILD} - indicates an automatically triggered incremental build
* (autobuilding on).</li>
* <li>{@link #CLEAN_BUILD} - indicates a clean request.</li>
* </ul>
* @param args a table of builder-specific arguments keyed by argument name (key type:
* <code>String</code>, value type: <code>String</code>); <code>null</code> is
* equivalent to an empty map.
* @return a scheduling rule which is contained in the workspace root rule or <code>null</code>
* to indicate that no protection against resource modification during the build is
* needed.
*
* @since 3.6
*/
public ISchedulingRule getRule(int kind, Map args) {
return getRule();
}
}