提交 0af104d2 编写于 作者: K kohsuke

making more progress in TaskThread/TaskAction and maven artifact redeployment.


git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@7457 71c3de6d-444a-0410-be80-ed276b4c234a
上级 fe419847
......@@ -4,10 +4,17 @@ import hudson.maven.MavenEmbedder;
import hudson.maven.MavenUtil;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BallColor;
import hudson.model.LargeText;
import hudson.model.Result;
import hudson.model.TaskAction;
import hudson.model.TaskListener;
import hudson.model.TaskThread;
import hudson.model.TaskAction;
import hudson.model.TaskThread.ListenerAndText;
import hudson.security.Permission;
import hudson.util.Iterators;
import hudson.widgets.HistoryWidget;
import hudson.widgets.HistoryWidget.Adapter;
import org.apache.maven.artifact.deployer.ArtifactDeploymentException;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
......@@ -19,7 +26,11 @@ import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import javax.servlet.ServletException;
import java.io.File;
import java.io.IOException;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* UI to redeploy artifacts after the fact.
......@@ -31,6 +42,73 @@ import java.io.IOException;
* @author Kohsuke Kawaguchi
*/
public abstract class MavenAbstractArtifactRecord<T extends AbstractBuild<?,?>> extends TaskAction {
public final class Record {
/**
* Repository URL that artifacts were deployed.
*/
public final String url;
/**
* Log file name. Relative to {@link AbstractBuild#getRootDir()}.
*/
private final String fileName;
/**
* Status of this record.
*/
private Result result;
private final Calendar timeStamp;
public Record(String url, String fileName) {
this.url = url;
this.fileName = fileName;
timeStamp = new GregorianCalendar();
}
/**
* Returns the log of this deployment record.
*/
public LargeText getLog() {
return new LargeText(new File(getBuild().getRootDir(),fileName),true);
}
/**
* Result of the deployment. During the build, this value is null.
*/
public Result getResult() {
return result;
}
public int getNumber() {
return records.indexOf(this);
}
public boolean isBuilding() {
return result==null;
}
public Calendar getTimestamp() {
return (Calendar) timeStamp.clone();
}
public String getBuildStatusUrl() {
return getIconColor().getImage();
}
public BallColor getIconColor() {
if(result==null)
return BallColor.GREY_ANIME;
else
return result.color;
}
}
/**
* Records of a deployment.
*/
public final CopyOnWriteArrayList<Record> records = new CopyOnWriteArrayList<Record>();
/**
* Gets the parent build object to which this record is registered.
*/
......@@ -52,6 +130,10 @@ public abstract class MavenAbstractArtifactRecord<T extends AbstractBuild<?,?>>
return REDEPLOY;
}
public HistoryWidgetImpl getHistoryWidget() {
return new HistoryWidgetImpl();
}
/**
* Performs a redeployment.
*/
......@@ -61,20 +143,32 @@ public abstract class MavenAbstractArtifactRecord<T extends AbstractBuild<?,?>>
@QueryParameter("uniqueVersion") final boolean uniqueVersion) throws ServletException, IOException {
getBuild().checkPermission(REDEPLOY);
new TaskThread(this) {
protected void perform(TaskListener listener) throws Exception {
MavenEmbedder embedder = MavenUtil.createEmbedder(listener, null);
ArtifactRepositoryLayout layout =
(ArtifactRepositoryLayout) embedder.getContainer().lookup( ArtifactRepositoryLayout.ROLE,"default");
ArtifactRepositoryFactory factory =
(ArtifactRepositoryFactory) embedder.lookup(ArtifactRepositoryFactory.ROLE);
File logFile = new File(getBuild().getRootDir(),"maven-deployment."+records.size()+".log");
final Record record = new Record(repositoryUrl, logFile.getName());
records.add(record);
ArtifactRepository repository = factory.createDeploymentArtifactRepository(
id, repositoryUrl, layout, uniqueVersion);
deploy(embedder,repository,listener);
embedder.stop();
new TaskThread(this,ListenerAndText.forFile(logFile)) {
protected void perform(TaskListener listener) throws Exception {
try {
MavenEmbedder embedder = MavenUtil.createEmbedder(listener, null);
ArtifactRepositoryLayout layout =
(ArtifactRepositoryLayout) embedder.getContainer().lookup( ArtifactRepositoryLayout.ROLE,"default");
ArtifactRepositoryFactory factory =
(ArtifactRepositoryFactory) embedder.lookup(ArtifactRepositoryFactory.ROLE);
ArtifactRepository repository = factory.createDeploymentArtifactRepository(
id, repositoryUrl, layout, uniqueVersion);
deploy(embedder,repository,listener);
embedder.stop();
record.result = Result.SUCCESS;
} finally {
if(record.result==null)
record.result = Result.FAILURE;
// persist the record
getBuild().save();
}
}
}.start();
......@@ -93,6 +187,30 @@ public abstract class MavenAbstractArtifactRecord<T extends AbstractBuild<?,?>>
*/
public abstract void deploy(MavenEmbedder embedder, ArtifactRepository deploymentRepository, TaskListener listener) throws MavenEmbedderException, IOException, ComponentLookupException, ArtifactDeploymentException;
private final class HistoryWidgetImpl extends HistoryWidget<MavenAbstractArtifactRecord,Record> {
private HistoryWidgetImpl() {
super(MavenAbstractArtifactRecord.this, Iterators.reverse(records), ADAPTER);
}
}
private static final Adapter<MavenAbstractArtifactRecord<?>.Record> ADAPTER = new Adapter<MavenAbstractArtifactRecord<?>.Record>() {
public int compare(MavenAbstractArtifactRecord<?>.Record record, String key) {
return record.getNumber()-Integer.parseInt(key);
}
public String getKey(MavenAbstractArtifactRecord<?>.Record record) {
return String.valueOf(record.getNumber());
}
public boolean isBuilding(MavenAbstractArtifactRecord<?>.Record record) {
return record.isBuilding();
}
public String getNextKey(String key) {
return String.valueOf(Integer.parseInt(key)+1);
}
};
/**
* Permission for redeploying artifacts.
......
......@@ -3,9 +3,10 @@ package hudson.model;
import hudson.util.ByteBuffer;
import hudson.util.StreamTaskListener;
import java.lang.ref.WeakReference;
import java.io.Reader;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.lang.ref.WeakReference;
/**
* {@link Thread} for performing one-off task.
......@@ -14,15 +15,28 @@ import java.io.IOException;
* @since 1.191
*/
public abstract class TaskThread extends Thread {
// StringWriter is synchronized
protected final ByteBuffer log = new ByteBuffer();
protected final LargeText text = new LargeText(log,false);
/**
* Represents the output from this task thread.
*/
private final LargeText text;
/**
* Represents the interface to produce output.
*/
private TaskListener listener;
private final TaskAction owner;
protected TaskThread(TaskAction owner) {
/**
*
* @param output
* Determines where the output from this task thread goes.
*/
protected TaskThread(TaskAction owner, ListenerAndText output) {
super(owner.getBuild().toString()+' '+owner.getDisplayName());
this.owner = owner;
this.text = output.text;
this.listener = output.listener;
}
public Reader readAll() throws IOException {
......@@ -45,8 +59,16 @@ public abstract class TaskThread extends Thread {
super.start();
}
/**
* Determines where the output of this {@link TaskThread} goes.
* <p>
* Subclass can override this to send the output to a file, for example.
*/
protected ListenerAndText createListener() throws IOException {
return ListenerAndText.forMemory();
}
public final void run() {
TaskListener listener = new StreamTaskListener(log);
try {
perform(listener);
listener.getLogger().println("Completed");
......@@ -55,6 +77,8 @@ public abstract class TaskThread extends Thread {
listener.getLogger().println("Aborted");
} catch (Exception e) {
e.printStackTrace(listener.getLogger());
} finally {
listener = null;
}
text.markAsComplete();
}
......@@ -66,4 +90,41 @@ public abstract class TaskThread extends Thread {
* The exception is recorded and reported as a failure.
*/
protected abstract void perform(TaskListener listener) throws Exception;
/**
* Tuple of {@link TaskListener} and {@link LargeText}, representing
* the interface for producing output and how to retrieve it later.
*/
public static final class ListenerAndText {
final TaskListener listener;
final LargeText text;
public ListenerAndText(TaskListener listener, LargeText text) {
this.listener = listener;
this.text = text;
}
/**
* Creates one that's backed by memory.
*/
public static ListenerAndText forMemory() {
// StringWriter is synchronized
ByteBuffer log = new ByteBuffer();
return new ListenerAndText(
new StreamTaskListener(log),
new LargeText(log,false)
);
}
/**
* Creates one that's backed by a file.
*/
public static ListenerAndText forFile(File f) throws IOException {
return new ListenerAndText(
new StreamTaskListener(f),
new LargeText(f,false)
);
}
}
}
......@@ -1370,7 +1370,7 @@ public class CVSSCM extends SCM implements Serializable {
private final Map<AbstractBuild,String> tagSet;
public TagWorkerThread(TagAction owner,Map<AbstractBuild,String> tagSet) {
super(owner);
super(owner,ListenerAndText.forMemory());
this.tagSet = tagSet;
}
......
......@@ -139,7 +139,7 @@ public class SubversionTagAction extends AbstractScmTagAction {
private final Map<SvnInfo,String> tagSet;
public TagWorkerThread(Map<SvnInfo,String> tagSet) {
super(SubversionTagAction.this);
super(SubversionTagAction.this,ListenerAndText.forMemory());
this.tagSet = tagSet;
}
......
......@@ -17,6 +17,10 @@ import java.util.List;
/**
* Displays the history of records (normally {@link Run}s) on the side panel.
*
* @param <O>
* Owner of the widget.
* @param <T>
* Type individual record.
* @author Kohsuke Kawaguchi
*/
public class HistoryWidget<O extends ModelObject,T> extends Widget {
......
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:test="/lib/test">
<l:layout permission="${it.REDEPLOY}">
<st:include it="${it.parent}" page="sidepanel.jelly" />
<l:side-panel>
<st:include it="${it.historyWidget}" page="index.jelly" />
</l:side-panel>
<l:main-panel>
<h1>
<img src="${imagesURL}/48x48/redo.gif" width="48" height="48" />
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册