Skip to content

Commit

Permalink
Merge pull request #10 from jglick/LogActionImpl-encapsulation
Browse files Browse the repository at this point in the history
Moving some code relating to LogActionImpl into that source for better encapsulation
  • Loading branch information
jglick committed Sep 17, 2016
2 parents 5ca2e3b + 07e67ee commit d23cb43
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 30 deletions.
Expand Up @@ -28,17 +28,12 @@
import hudson.Launcher;
import hudson.LauncherDecorator;
import hudson.console.ConsoleLogFilter;
import hudson.model.AbstractBuild;
import hudson.model.Computer;
import hudson.model.Job;
import hudson.model.Node;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.util.StreamTaskListener;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
import java.util.logging.Logger;
Expand Down Expand Up @@ -66,7 +61,6 @@ public abstract class DefaultStepContext extends StepContext {
* Uses {@link #doGet} but automatically translates certain kinds of objects into others.
* <p>{@inheritDoc}
*/
@edu.umd.cs.findbugs.annotations.SuppressWarnings("OBL_UNSATISFIED_OBLIGATION_EXCEPTION_EDGE") // stream closed later
@Override public final <T> T get(Class<T> key) throws IOException, InterruptedException {
T value = doGet(key);
if (key == EnvVars.class) {
Expand All @@ -80,23 +74,13 @@ public abstract class DefaultStepContext extends StepContext {
return value;
} else if (key == TaskListener.class) {
if (listener == null) {
LogActionImpl la = getNode().getAction(LogActionImpl.class);
if (la == null) {
// TODO: use the default charset of the contextual Computer object
la = new LogActionImpl(getNode(), Charset.defaultCharset());
getNode().addAction(la);
}
ConsoleLogFilter filter = get(ConsoleLogFilter.class);
OutputStream os = new FileOutputStream(la.getLogFile(), true);
if (filter != null) {
os = filter.decorateLogger((AbstractBuild) null, os);
}
listener = new StreamTaskListener(os);
final FlowNode node = getNode();
listener = LogActionImpl.stream(node, get(ConsoleLogFilter.class));
final AtomicReference<GraphListener> graphListener = new AtomicReference<GraphListener>();
graphListener.set(new GraphListener.Synchronous() {
@Override public void onNewHead(FlowNode node) {
@Override public void onNewHead(FlowNode newNode) {
try {
if (!getNode().isRunning()) {
if (!node.isRunning()) {
getExecution().removeListener(graphListener.get());
listener.getLogger().close();
}
Expand Down
Expand Up @@ -25,38 +25,72 @@
package org.jenkinsci.plugins.workflow.support.actions;

import com.google.common.base.Charsets;
import org.apache.commons.jelly.XMLOutput;
import org.jenkinsci.plugins.workflow.flow.FlowExecutionOwner;
import org.jenkinsci.plugins.workflow.graph.FlowNode;
import org.jenkinsci.plugins.workflow.actions.FlowNodeAction;
import org.jenkinsci.plugins.workflow.actions.LogAction;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.console.AnnotatedLargeText;
import org.kohsuke.stapler.framework.io.ByteBuffer;

import hudson.console.ConsoleLogFilter;
import hudson.model.AbstractBuild;
import hudson.model.TaskListener;
import hudson.util.StreamTaskListener;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import org.apache.commons.jelly.XMLOutput;
import org.jenkinsci.plugins.workflow.actions.FlowNodeAction;
import org.jenkinsci.plugins.workflow.actions.LogAction;
import org.jenkinsci.plugins.workflow.flow.FlowExecutionOwner;
import org.jenkinsci.plugins.workflow.graph.FlowNode;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.DoNotUse;
import org.kohsuke.stapler.framework.io.ByteBuffer;

/**
* {@link LogAction} implementation that stores per-node log file under {@link FlowExecutionOwner#getRootDir()}.
*
* @author Kohsuke Kawaguchi
*/
public class LogActionImpl extends LogAction implements FlowNodeAction {

/**
* Get or create the streaming log handle for a given flow node.
* @param node the node
* @param filter
* @return a listener
*/
@SuppressFBWarnings("OBL_UNSATISFIED_OBLIGATION_EXCEPTION_EDGE") // stream closed later
public static @Nonnull TaskListener stream(@Nonnull FlowNode node, @CheckForNull ConsoleLogFilter filter) throws IOException, InterruptedException {
LogActionImpl la = node.getAction(LogActionImpl.class);
if (la == null) {
// TODO: use UTF-8
la = new LogActionImpl(node, Charset.defaultCharset());
node.addAction(la);
}
OutputStream os = new FileOutputStream(la.getLogFile(), true);
if (filter != null) {
os = filter.decorateLogger((AbstractBuild) null, os);
}
StreamTaskListener result = new StreamTaskListener(os);
return result;
}

private transient FlowNode parent;
private transient volatile File log;
private String charset;

public LogActionImpl(FlowNode parent, Charset charset) {
private LogActionImpl(FlowNode parent, Charset charset) {
if (!parent.isRunning()) {
throw new IllegalStateException("cannot start writing logs to a finished node " + parent);
}
this.parent = parent;
this.charset = charset.name();
}

@Restricted(DoNotUse.class) // Jelly
public FlowNode getParent() {
return parent;
}
Expand Down Expand Up @@ -87,7 +121,7 @@ public AnnotatedLargeText<? extends FlowNode> getLogText() {
/**
* The actual log file.
*/
public File getLogFile() throws IOException {
private File getLogFile() throws IOException {
if (log==null)
log = new File(parent.getExecution().getOwner().getRootDir(), parent.getId() + ".log");
return log;
Expand All @@ -96,6 +130,7 @@ public File getLogFile() throws IOException {
/**
* Used from <tt>console.jelly</tt> to write annotated log to the given output.
*/
@Restricted(DoNotUse.class) // Jelly
public void writeLogTo(long offset, XMLOutput out) throws IOException {
AnnotatedLargeText l = getLogText();
if (l!=null)
Expand All @@ -107,7 +142,7 @@ public void onLoad(FlowNode parent) {
this.parent = parent;
}

public Charset getCharset() {
private Charset getCharset() {
if(charset==null) return Charset.defaultCharset(); // just being defensive
return Charset.forName(charset);
}
Expand Down

0 comments on commit d23cb43

Please sign in to comment.