diff --git a/changelog.html b/changelog.html index 6bd59c14b94d2a3c19fecb22a722a163ff1778ef..32b55e3091d1c7860883366db3839e58979179ba 100644 --- a/changelog.html +++ b/changelog.html @@ -86,6 +86,9 @@ Upcoming changes
  • If CLI fails to connect via a JNLP Slave port, fall back to HTTP full-duplex. (issue 10611) +
  • + Added two CLI commands to manipulate job by its XML definition. + (issue 8797)
  • Fixed unclear text for Tabs with no jobs (issue 9330) diff --git a/core/src/main/java/hudson/cli/GetJobXmlCommand.java b/core/src/main/java/hudson/cli/GetJobXmlCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..8208649089e31909ad9799357dc46f60d30d31d8 --- /dev/null +++ b/core/src/main/java/hudson/cli/GetJobXmlCommand.java @@ -0,0 +1,50 @@ +/* + * The MIT License + * + * Copyright (c) 2011, CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package hudson.cli; + +import hudson.model.AbstractProject; +import hudson.model.Item; +import hudson.util.IOUtils; +import org.kohsuke.args4j.Argument; + +/** + * @author Kohsuke Kawaguchi + */ +public class GetJobXmlCommand extends CLICommand { + @Argument(metaVar="JOB",usage="Name of the job",required=true) + public AbstractProject job; + + @Override + public String getShortDescription() { + return "Dumps the job definition XML to stdout"; + } + + protected int run() throws Exception { + job.checkPermission(Item.EXTENDED_READ); + IOUtils.copy( + job.getConfigFile().getFile(), + stdout); + return 0; + } +} diff --git a/core/src/main/java/hudson/cli/UpdateJobXmlCommand.java b/core/src/main/java/hudson/cli/UpdateJobXmlCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..e22ee7ef5e55ecab289028fe0bdd7d8961a098c2 --- /dev/null +++ b/core/src/main/java/hudson/cli/UpdateJobXmlCommand.java @@ -0,0 +1,49 @@ +/* + * The MIT License + * + * Copyright (c) 2011, CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package hudson.cli; + +import hudson.model.AbstractProject; +import hudson.util.IOUtils; +import org.kohsuke.args4j.Argument; + +import javax.xml.transform.stream.StreamSource; + +/** + * @author Kohsuke Kawaguchi + */ +public class UpdateJobXmlCommand extends CLICommand { + @Argument(metaVar="JOB",usage="Name of the job",required=true) + public AbstractProject job; + + @Override + public String getShortDescription() { + return "Updates the job definition XML from stdin. The opposite of the get-job-xml command"; + } + + protected int run() throws Exception { + job.updateByXml(new StreamSource(stdin)); + return 0; + } +} + diff --git a/core/src/main/java/hudson/model/AbstractItem.java b/core/src/main/java/hudson/model/AbstractItem.java index 8f0130dfb1eb66ac239864469117f93e5968c732..ecdf5a5f5d3b7c2b5c6184e9be20c36d39318385 100644 --- a/core/src/main/java/hudson/model/AbstractItem.java +++ b/core/src/main/java/hudson/model/AbstractItem.java @@ -51,10 +51,8 @@ import org.kohsuke.stapler.export.ExportedBean; import java.io.File; import java.io.IOException; -import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.List; import java.util.Map; import org.kohsuke.stapler.StaplerRequest; @@ -509,32 +507,7 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet } if (req.getMethod().equals("POST")) { // submission - checkPermission(CONFIGURE); - XmlFile configXmlFile = getConfigFile(); - AtomicFileWriter out = new AtomicFileWriter(configXmlFile.getFile()); - try { - try { - // this allows us to use UTF-8 for storing data, - // plus it checks any well-formedness issue in the submitted - // data - Transformer t = TransformerFactory.newInstance() - .newTransformer(); - t.transform(new StreamSource(req.getReader()), - new StreamResult(out)); - out.close(); - } catch (TransformerException e) { - throw new IOException2("Failed to persist configuration.xml", e); - } - - // try to reflect the changes by reloading - new XmlFile(Items.XSTREAM, out.getTemporaryFile()).unmarshal(this); - onLoad(getParent(), getRootDir().getName()); - - // if everything went well, commit this new version - out.commit(); - } finally { - out.abort(); // don't leave anything behind - } + updateByXml(new StreamSource(req.getReader())); return; } @@ -542,6 +515,38 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet rsp.sendError(SC_BAD_REQUEST); } + /** + * Updates Job by its XML definition. + */ + public void updateByXml(StreamSource source) throws IOException { + checkPermission(CONFIGURE); + XmlFile configXmlFile = getConfigFile(); + AtomicFileWriter out = new AtomicFileWriter(configXmlFile.getFile()); + try { + try { + // this allows us to use UTF-8 for storing data, + // plus it checks any well-formedness issue in the submitted + // data + Transformer t = TransformerFactory.newInstance() + .newTransformer(); + t.transform(source, + new StreamResult(out)); + out.close(); + } catch (TransformerException e) { + throw new IOException2("Failed to persist configuration.xml", e); + } + + // try to reflect the changes by reloading + new XmlFile(Items.XSTREAM, out.getTemporaryFile()).unmarshal(this); + onLoad(getParent(), getRootDir().getName()); + + // if everything went well, commit this new version + out.commit(); + } finally { + out.abort(); // don't leave anything behind + } + } + public String toString() { return super.toString()+'['+getFullName()+']'; }