package hudson.plugins.build_publisher; import hudson.Util; import hudson.model.AbstractBuild; import java.io.PrintWriter; import java.io.StringWriter; import java.io.IOException; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.Header; import org.kohsuke.stapler.StaplerResponse; import org.kohsuke.stapler.StaplerRequest; import javax.servlet.http.HttpServletResponse; /** * The current state of {@link PublisherThread}. * * <p> * The state is bundled into this immutable object so that * {@link PublisherThread} could update the state atomically * without locking. * * <p> * Even the singleton states don't use anonymous class so * that Jelly views can be associated with each state. * * @author Kohsuke Kawaguchi */ public abstract class ThreadState { private ThreadState() { } /** * {@link PublisherThread} encountered an error and is waiting before * it attempts the tranmission again. */ public static class ErrorRecoveryWait extends ThreadState { /** * If {@link System#currentTimeMillis()} gets bigger than this value * the time out will be over. */ public final long timeout; /** * Cause of the problem. */ public final Throwable cause; /** * Failed while sending this record. */ public final AbstractBuild build; /** * Failed {@link HttpMethod}, if the failure was due to an error on the server. Possibly null. */ public final HttpMethod method; /*package*/ ErrorRecoveryWait(long timeout,AbstractBuild build,Throwable cause, HttpMethod method) { this.timeout = timeout; this.build = build; this.cause = cause; this.method = method; } public String getTimeoutString() { return Util.getTimeSpanString(timeout-System.currentTimeMillis()); } public String getStackTrace() { return printStackTrace(cause); } /** * Dumps the server output. */ public void doOutput(StaplerRequest req, StaplerResponse rsp) throws IOException { if(method==null) rsp.sendError(HttpServletResponse.SC_NOT_FOUND); else { Header ct = method.getResponseHeader("Content-type"); if(ct!=null) rsp.setContentType(ct.getValue()); else rsp.setContentType("text/plain;charset=UTF-8"); rsp.getWriter().write(method.getResponseBodyAsString()); } } } /** * {@link PublisherThread} is doing nothing and looking for something to work on. */ public static class Idle extends ThreadState { private Idle() {} } /** * {@link PublisherThread} is dead. */ public static class Dead extends ThreadState { /** * Cause of the death. */ public final Throwable cause; /*package*/ Dead(Throwable cause) { this.cause = cause; } public String getStackTrace() { return printStackTrace(cause); } } /** * {@link PublisherThread} is publishing a build. */ public static class Publishing extends ThreadState { public final AbstractBuild build; /*package*/ Publishing(AbstractBuild build) { this.build = build; } } public static final ThreadState IDLE = new Idle(); static String printStackTrace(Throwable cause) { StringWriter sw = new StringWriter(); cause.printStackTrace(new PrintWriter(sw)); return sw.toString(); } }