package hudson.plugins.analysis.core; import java.io.File; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import org.kohsuke.stapler.StaplerProxy; import edu.umd.cs.findbugs.annotations.SuppressWarnings; import hudson.FilePath; import hudson.maven.MavenBuild; import hudson.maven.MavenModule; import hudson.model.HealthReport; import hudson.model.HealthReportingAction; import hudson.model.AbstractBuild; import hudson.plugins.analysis.util.ToolTipProvider; import hudson.plugins.analysis.util.model.AbstractAnnotation; /** * Controls the live cycle of Hudson results. This action persists the results * of a build and displays them on the build page. The actual visualization of * the results is defined in the matching <code>summary.jelly</code> file. * <p> * Moreover, this class renders the results trend. * </p> * * @param <T> * type of the result of this action * @author Ulli Hafner */ //CHECKSTYLE:COUPLING-OFF public abstract class AbstractResultAction<T extends BuildResult> implements StaplerProxy, HealthReportingAction, ToolTipProvider, ResultAction<T> { /** The associated build of this action. */ private final AbstractBuild<?, ?> owner; /** Parameters for the health report. */ private final AbstractHealthDescriptor healthDescriptor; /** The actual result of this action. */ private T result; /** * Creates a new instance of <code>AbstractResultAction</code>. * * @param owner * the associated build of this action * @param healthDescriptor * health descriptor * @param result * the result of the action */ public AbstractResultAction(final AbstractBuild<?, ?> owner, final AbstractHealthDescriptor healthDescriptor, final T result) { this.owner = owner; this.result = result; this.healthDescriptor = healthDescriptor; } /** * Creates a new instance of <code>AbstractResultAction</code>. * * @param owner * the associated build of this action * @param healthDescriptor * health descriptor */ public AbstractResultAction(final AbstractBuild<?, ?> owner, final AbstractHealthDescriptor healthDescriptor) { this.owner = owner; this.healthDescriptor = healthDescriptor; } /** * Returns the healthDescriptor. * * @return the healthDescriptor */ public AbstractHealthDescriptor getHealthDescriptor() { if (healthDescriptor == null) { return NullHealthDescriptor.NULL_HEALTH_DESCRIPTOR; // for old serialized actions } else { return healthDescriptor; } } /** * Returns the descriptor of the associated plug-in. * * @return the descriptor of the associated plug-in */ protected abstract PluginDescriptor getDescriptor(); /** {@inheritDoc} */ public String getUrlName() { return getDescriptor().getPluginResultUrlName(); } /** {@inheritDoc} */ public final HealthReport getBuildHealth() { return new HealthReportBuilder(getHealthDescriptor()).computeHealth(getResult()); } /** {@inheritDoc} */ public ToolTipProvider getToolTipProvider() { return this; } /** * Returns the associated build of this action. * * @return the associated build of this action */ public final AbstractBuild<?, ?> getOwner() { return owner; } /** {@inheritDoc} */ public final AbstractBuild<?, ?> getBuild() { return owner; } /** {@inheritDoc} */ public final Object getTarget() { return getResult(); } /** {@inheritDoc} */ public final T getResult() { return result; } /** {@inheritDoc} */ public final void setResult(final T result) { this.result = result; } /** {@inheritDoc} */ public String getIconFileName() { if (getResult().getNumberOfAnnotations() > 0) { return getDescriptor().getIconUrl(); } return null; } /** * Aggregates the results of the specified maven module builds. * * @param moduleBuilds * the module builds to aggregate * @return the aggregated result */ protected ParserResult createAggregatedResult(final Map<MavenModule, List<MavenBuild>> moduleBuilds) { ParserResult project = createResult(); for (List<MavenBuild> builds : moduleBuilds.values()) { if (!builds.isEmpty()) { addModule(project, builds); } } return project; } /** * Factory method to create the result of this action. * * @return the result of this action */ protected ParserResult createResult() { return new ParserResult(); } /** * Adds a new module to the specified project. The new module is obtained * from the specified list of builds. * * @param aggregatedResult * the result to add the module to * @param builds * the builds for a module */ // FIXME: this method is always invoked with all available builds, check this for hierarchies @java.lang.SuppressWarnings("unchecked") protected void addModule(final ParserResult aggregatedResult, final List<MavenBuild> builds) { MavenBuild mavenBuild = builds.get(0); AbstractResultAction<T> action = mavenBuild.getAction(getClass()); if (action != null) { aggregatedResult.addAnnotations(action.getResult().getAnnotations()); aggregatedResult.addModules(action.getResult().getModules()); aggregatedResult.addErrors(action.getResult().getErrors()); FilePath filePath = new FilePath(new File(mavenBuild.getRootDir(), AbstractAnnotation.WORKSPACE_FILES)); try { filePath.copyRecursiveTo("*.tmp", new FilePath(new File(getOwner().getRootDir(), AbstractAnnotation.WORKSPACE_FILES))); } catch (IOException exception) { Logger.getLogger(getClass().getName()).log(Level.SEVERE, "Can't copy workspace files: ", exception); } catch (InterruptedException exception) { // ignore, user canceled the operation } } } /** * Updates the build status if the number of annotations exceeds one of the * thresholds. * * @param build * the build to change the status from * @param buildResult * the build result */ protected void updateBuildHealth(final MavenBuild build, final BuildResult buildResult) { // FIXME: See http://issues.hudson-ci.org/browse/HUDSON-4912 // PluginLogger logger = new PluginLogger(System.out, "[" + getDisplayName() + "] "); // Result hudsonResult = new BuildResultEvaluator().evaluateBuildResult( // logger, getHealthDescriptor(), buildResult.getAnnotations(), buildResult.getNewWarnings()); // if (hudsonResult != Result.SUCCESS) { // build.setResult(hudsonResult); // } } /** {@inheritDoc} */ public String getTooltip(final int numberOfItems) { if (numberOfItems == 1) { return getSingleItemTooltip(); } else { return getMultipleItemsTooltip(numberOfItems); } } /** * Returns the tooltip for several items. * * @param numberOfItems * the number of items to display the tooltip for * @return the tooltip for several items */ protected abstract String getMultipleItemsTooltip(int numberOfItems); /** * Returns the tooltip for exactly one item. * * @return the tooltip for exactly one item */ protected abstract String getSingleItemTooltip(); /** {@inheritDoc} */ public boolean isSuccessful() { return getResult().isSuccessful(); } /** Backward compatibility. @deprecated */ @Deprecated @java.lang.SuppressWarnings("unused") @SuppressWarnings("UuF") private transient HealthReportBuilder healthReportBuilder; // NOPMD }