提交 c1c97974 编写于 作者: R Ryan Campbell

API for updating update sites programatically, enabling automated plugin updates and installation.

上级 9a95d233
......@@ -41,6 +41,7 @@ import hudson.model.UpdateSite.Plugin;
import hudson.model.listeners.SaveableListener;
import hudson.security.ACL;
import hudson.util.DaemonThreadFactory;
import hudson.util.FormValidation;
import hudson.util.HttpResponses;
import hudson.util.IOException2;
import hudson.util.PersistedList;
......@@ -76,6 +77,7 @@ import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.Vector;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
......@@ -130,6 +132,18 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas
}
}));
/**
* An {@link ExecutorService} for updating UpdateSites.
*/
protected final ExecutorService updateService = Executors.newCachedThreadPool(
new DaemonThreadFactory(new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("Update site data downloader");
return t;
}
}));
/**
* List of created {@link UpdateCenterJob}s. Access needs to be synchronized.
*/
......@@ -602,6 +616,32 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas
return new ArrayList<Plugin>(pluginMap.values());
}
/**
* Ensure that all UpdateSites are up to date, without requiring a user to
* browse to the instance.
*
* @return a list of {@link FormValidation} for each updated Update Site
* @throws ExecutionException
* @throws InterruptedException
* @since 1.501
*
*/
public List<FormValidation> updateAllSites() throws InterruptedException, ExecutionException {
List <Future<FormValidation>> futures = new ArrayList<Future<FormValidation>>();
for (UpdateSite site : getSites()) {
Future<FormValidation> future = site.updateDirectly();
if (future != null) {
futures.add(future);
}
}
List<FormValidation> results = new ArrayList<FormValidation>();
for (Future<FormValidation> f : futures) {
results.add(f.get());
}
return results;
}
/**
......
......@@ -27,6 +27,7 @@ package hudson.model;
import hudson.PluginManager;
import hudson.PluginWrapper;
import hudson.ProxyConfiguration;
import hudson.lifecycle.Lifecycle;
import hudson.model.UpdateCenter.UpdateCenterJob;
import hudson.util.FormValidation;
......@@ -41,14 +42,18 @@ import net.sf.json.JSONException;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.export.Exported;
import org.kohsuke.stapler.export.ExportedBean;
import org.kohsuke.stapler.interceptor.RequirePOST;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Collections;
......@@ -57,6 +62,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
......@@ -144,12 +150,53 @@ public class UpdateSite {
return dataTimestamp;
}
/**
* Update the json file from the given URL if the file
* does not exist, or is otherwise due for update.
*
* @return null if no updates are necessary, or the future result
* @since 1.501
*/
public Future<FormValidation> updateDirectly() {
if (! getDataFile().exists() || isDue()) {
return Jenkins.getInstance().getUpdateCenter().updateService.submit(new Callable<FormValidation>() {
public FormValidation call() throws Exception {
URL src = new URL(getUrl());
URLConnection conn = ProxyConfiguration.open(src);
BufferedInputStream is = new BufferedInputStream(conn.getInputStream());
try {
// remove non-json characters from update center
is.mark(1);
for (int r = is.read(); r > 0 && (char)r != '{'; r = is.read()) {
is.mark(1);
}
is.reset();
return updateData(is);
} finally {
if (is != null)
is.close();
}
}
});
}
return null;
}
/**
* This is the endpoint that receives the update center data file from the browser.
*/
public FormValidation doPostBack(StaplerRequest req) throws IOException, GeneralSecurityException {
dataTimestamp = System.currentTimeMillis();
String json = IOUtils.toString(req.getInputStream(),"UTF-8");
return updateData(req.getInputStream());
}
private FormValidation updateData(java.io.InputStream is)
throws IOException {
dataTimestamp = System.currentTimeMillis();
String json = IOUtils.toString(is,"UTF-8");
JSONObject o = JSONObject.fromObject(json);
int v = o.getInt("updateCenterVersion");
......@@ -158,7 +205,7 @@ public class UpdateSite {
if (signatureCheck) {
FormValidation e = verifySignature(o);
if (e.kind!=Kind.OK) {
if (e.kind!=Kind.OK && Stapler.getCurrentRequest() != null) {
LOGGER.severe(e.renderHtml());
return e;
}
......
......@@ -28,6 +28,7 @@ import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebRequestSettings;
import hudson.model.UpdateSite.Data;
import hudson.util.FormValidation;
import hudson.util.PersistedList;
import java.net.URL;
import java.util.Arrays;
......@@ -64,4 +65,19 @@ public class UpdateSiteTest {
assertEquals("http://nowhere.net/dummy.hpi", data.plugins.get("dummy").url);
}
@Test public void updateDirectlyWithJson() throws Exception {
UpdateSite us = new UpdateSite("default", UpdateSiteTest.class.getResource("update-center.json").toExternalForm());
assertNull(us.getPlugin("AdaptivePlugin"));
FormValidation result = us.updateDirectly().get();
assertTrue(result.equals(FormValidation.ok()));
assertNotNull(us.getPlugin("AdaptivePlugin"));
}
@Test public void updateDirectlyWithHtml() throws Exception {
UpdateSite us = new UpdateSite("default", UpdateSiteTest.class.getResource("update-center.json").toExternalForm());
assertNull(us.getPlugin("AdaptivePlugin"));
FormValidation result = us.updateDirectly().get();
assertTrue(result.equals(FormValidation.ok()));
assertNotNull(us.getPlugin("AdaptivePlugin"));
}
}
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册