Skip to content

Instantly share code, notes, and snippets.

@virtuald
Created November 16, 2015 19:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save virtuald/fda8e589c741cf20c510 to your computer and use it in GitHub Desktop.
Save virtuald/fda8e589c741cf20c510 to your computer and use it in GitHub Desktop.
package io.takari.incrementalbuild.spi;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.maven.execution.scope.MojoExecutionScoped;
import io.takari.incrementalbuild.Output;
import io.takari.incrementalbuild.ResourceStatus;
import io.takari.incrementalbuild.aggregator.InputAggregator;
import io.takari.incrementalbuild.aggregator.internal.DefaultAggregatorBuildContext;
@Named
@MojoExecutionScoped
public class EnhancedAggregateBuildContext extends DefaultAggregatorBuildContext{
protected static final String AGGREGATE_PREFIX = "agg://";
protected static final String AGGREGATE_DATA = "aggregate-data";
static File addPostfix(File f) {
try {
return new File(f.getCanonicalPath() + "_agg");
} catch (IOException e) {
return new File(f.getAbsolutePath() + "_agg");
}
}
@Inject
public EnhancedAggregateBuildContext(BuildContextEnvironment env) {
// have to change the statefile, as the same statefile is used for each context
// and that leads to some really strange errors
super(env.getWorkspace(), addPostfix(env.getStateFile()), env.getParameters(), env.getFinalizer());
//super(configuration);
}
/**
* Associates metadata for an input with with an output file
*/
public void setOutputInputAttribute(File outputFile, File inputFile, Serializable s) {
markProcessedResource(inputFile);
setResourceAttribute(inputFile, getAttributeKey(outputFile), s);
}
public <T extends Serializable> T getOutputInputAttribute(File outputFile, File inputFile, Class<T> clazz) {
// always returns from new state
return getResourceAttribute(state, inputFile, getAttributeKey(outputFile), clazz);
}
/**
* Associates metadata with an output file
*/
public void setOutputAggregateAttribute(File outputFile, Serializable s) {
setResourceAttribute(outputFile, AGGREGATE_DATA, s);
}
/**
* Retrieves metadata associated with an output file
*/
public <T extends Serializable> T getOutputAggregateAttribute(Output<File> outputFile, Class<T> clazz) {
return getAttribute(outputFile.getResource(), AGGREGATE_DATA, clazz);
}
/**
* Retrieves metadata associated with input files as set by
* setOutputInputAttribute
*/
public <T extends Serializable> Collection<T> getOutputMetadata(Output<File> output, Iterable<File> inputs, Class<T> clazz) {
String key = getAttributeKey(output.getResource());
Collection<T> metadata = new ArrayList<>();
for (File input: inputs) {
metadata.add(getAttribute(input, key, clazz));
}
return metadata;
}
@Override
public boolean aggregateIfNecessary(Collection<File> inputs, File outputFile, InputAggregator creator)
throws IOException {
String attrKey = getAttributeKey(outputFile);
// old inputs that haven't changed should be registered and added to
// the input set, and their attribute copied over
if (!isEscalated()) {
for (Object input: getOutputInputs(oldState, outputFile)) {
if (getResourceStatus(input) == ResourceStatus.UNMODIFIED) {
File inputFile = (File)input;
registerInput(inputFile);
inputs.add(inputFile);
// don't overwrite new metadata
Serializable attr = state.getResourceAttribute(input, attrKey);
if (attr == null) {
// carry it over
attr = oldState.getResourceAttribute(input, attrKey);
if (attr != null)
state.putResourceAttribute(input, attrKey, attr);
}
}
}
}
return super.aggregateIfNecessary(inputs, outputFile, creator);
}
protected boolean processingWasRequired(File oldOutput) {
for (Object input : getOutputInputs(oldState, oldOutput)) {
ResourceStatus st = getResourceStatus(input);
if (st != ResourceStatus.UNMODIFIED) {
return true;
}
}
return false;
}
@Override
public void commit(MessageSinkAdaptor messager) throws IOException {
try {
assertOpen();
} catch (IllegalStateException e) {
return;
}
// if the input files to an output haven't been updated, then
// assume that the output doesn't need to be changed
if (!isEscalated()) {
for (File oldOutput: oldState.getOutputs()) {
if (!isRegisteredResource(oldOutput) && !processingWasRequired(oldOutput)) {
aggregateIfNecessary(new HashSet<File>(), oldOutput, NullInputAggregator);
}
}
}
super.commit(messager);
}
protected String getAttributeKey(File outputFile) {
return AGGREGATE_PREFIX + normalize(outputFile).toString();
}
protected Collection<Object> getOutputInputs(DefaultBuildContextState state, File outputFile) {
Collection<Object> inputs = state.getOutputInputs(outputFile);
return inputs != null && !inputs.isEmpty() ? inputs : Collections.emptyList();
}
protected static InputAggregator NullInputAggregator = new InputAggregator(){
@Override
public void aggregate(Output<File> output, Iterable<File> inputs) throws IOException {
throw new IllegalStateException("processing should not be required");
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment