package hudson.plugins.fitnesse; import hudson.Extension; import hudson.FilePath; import hudson.Launcher; import hudson.model.AbstractBuild; import hudson.model.AbstractProject; import hudson.model.Action; import hudson.model.BuildListener; import hudson.model.ModelObject; import hudson.model.Result; import hudson.tasks.BuildStep; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.BuildStepMonitor; import hudson.tasks.Publisher; import hudson.tasks.Recorder; import hudson.util.FormValidation; import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import java.nio.charset.Charset; import java.util.Collection; import java.util.Collections; import javax.servlet.ServletException; import javax.xml.transform.TransformerException; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.QueryParameter; public class FitnesseResultsRecorder extends Recorder { private final String fitnessePathToXmlResultsIn; @DataBoundConstructor public FitnesseResultsRecorder(String fitnessePathToXmlResultsIn) { this.fitnessePathToXmlResultsIn = fitnessePathToXmlResultsIn; } /** * referenced in config.jelly */ public String getFitnessePathToXmlResultsIn() { return fitnessePathToXmlResultsIn; } /** * {@link Recorder} */ @Override public Collection<Action> getProjectActions(AbstractProject<?, ?> project) { return Collections.<Action>singleton(new FitnesseProjectAction(project)); } /** * {@link BuildStep} */ public BuildStepMonitor getRequiredMonitorService() { return BuildStepMonitor.BUILD; } /** * {@link BuildStep} */ @Override public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { try { FilePath workingDirectory = FitnesseExecutor.getWorkingDirectory(build); FilePath resultsFile = FitnesseExecutor.getResultsFilePath(workingDirectory, fitnessePathToXmlResultsIn); FitnesseResults results = getResults(listener.getLogger(), resultsFile); FitnesseResultsAction action = new FitnesseResultsAction(build, results); if (results.getBuildResult() != null) build.setResult(results.getBuildResult()); build.addAction(action); return true; } catch (Throwable t) { t.printStackTrace(listener.getLogger()); if (t instanceof InterruptedException) throw (InterruptedException) t; build.setResult(Result.FAILURE); return false; } } public FitnesseResults getResults(PrintStream logger, FilePath resultsFile) throws IOException, TransformerException { InputStream resultsInputStream = null; try { logger.println("Reading results as " + Charset.defaultCharset().displayName() + " from " + resultsFile.getRemote()); resultsInputStream = resultsFile.read(); logger.println("Parsing results... "); NativePageCountsParser pageCountsParser = new NativePageCountsParser(); NativePageCounts pageCounts = pageCountsParser.parse(resultsInputStream); logger.println("Got results: " + pageCounts.getSummary()); return new FitnesseResults(pageCounts); } finally { if (resultsInputStream != null) { try { resultsInputStream.close(); } catch (Exception e) { // swallow } } } } /** * {@link Publisher} */ @Override public DescriptorImpl getDescriptor() { return (DescriptorImpl) super.getDescriptor(); } /** * See <tt>src/main/resources/hudson/plugins/fitnesse/FitnesseResultsRecorder/config.jelly</tt> */ @Extension public static final class DescriptorImpl extends BuildStepDescriptor<Publisher> { public FormValidation doCheckFitnessePathToXmlResultsIn(@QueryParameter String value) throws IOException, ServletException { if (value.length()==0) return FormValidation.error("Please specify where to read fitnesse results from."); if (!value.endsWith("xml")) return FormValidation.warning("File does not end with 'xml': is that correct?"); return FormValidation.ok(); } /** * {@link BuildStepDescriptor} */ @Override public boolean isApplicable(Class<? extends AbstractProject> jobType) { // works with any kind of project return true; } /** * {@link ModelObject} */ @Override public String getDisplayName() { return "Publish Fitnesse results report"; } } }