package jenkins.model; import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.core.JVM; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import com.thoughtworks.xstream.mapper.Mapper; import hudson.ExtensionPoint; import hudson.model.AbstractDescribableImpl; import hudson.model.Job; import hudson.model.Run; import hudson.tasks.LogRotator; import hudson.util.RobustReflectionConverter; import java.io.IOException; /** * Implementation of "Discard old build records" feature. * * <p> * This extension point allows plugins to implement a different strategy to decide what builds to discard * and what builds to keep. * * @author Kohsuke Kawaguchi * @since 1.503 */ public abstract class BuildDiscarder extends AbstractDescribableImpl<BuildDiscarder> implements ExtensionPoint { /** * Called to perform "garbage collection" on the job to discard old build records. * * <p> * Normally invoked automatically jobs when new builds occur. * The general expectation is that those marked as {@link Run#isKeepLog()} will be kept untouched. * To delete the build record, call {@link Run#delete()}. * * @see Job#logRotate() */ public abstract void perform(Job<?,?> job) throws IOException, InterruptedException; @Override public BuildDiscarderDescriptor getDescriptor() { return (BuildDiscarderDescriptor)super.getDescriptor(); } /** * {@link AbstractProject#logRotator} used to be typed as {@link LogRotator}, * so such configuration file ends up trying to unmarshal {@link BuildDiscarder} and * not its subtype. * * This converter makes this work by unmarshalling a {@link LogRotator}. */ public static class ConverterImpl implements Converter { private RobustReflectionConverter ref; public ConverterImpl(Mapper m) { ref = new RobustReflectionConverter(m,new JVM().bestReflectionProvider()) { @Override protected Object instantiateNewInstance(HierarchicalStreamReader reader, UnmarshallingContext context) { return reflectionProvider.newInstance(LogRotator.class); } }; } public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { // abstract class, so there shouldn't be any instance. throw new UnsupportedOperationException(); } public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { // force unmarshal as LogRotator return ref.unmarshal(reader,context); } public boolean canConvert(Class type) { return type==BuildDiscarder.class; } } }