diff --git a/core/src/main/java/jenkins/util/io/FileBoolean.java b/core/src/main/java/jenkins/util/io/FileBoolean.java new file mode 100644 index 000000000000..3800ae287f7b --- /dev/null +++ b/core/src/main/java/jenkins/util/io/FileBoolean.java @@ -0,0 +1,61 @@ +package jenkins.util.io; + +import jenkins.model.Jenkins; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Uses a presence/absence of a file as a persisted boolean storage. + * + *
+ * This is convenient when you need to store just a few bits of infrequently accessed information + * as you can forget the explicit persistence of it. This class masks I/O problem, so if the persistence + * fails, you'll get no error report. + * + * @author Kohsuke Kawaguchi + * @since 1.498 + */ +public class FileBoolean { + private final File file; + + public FileBoolean(File file) { + this.file = file; + } + + public FileBoolean(Class owner, String name) { + this(new File(Jenkins.getInstance().getRootDir(),owner.getName().replace('$','.')+'/'+name)); + } + + /** + * Gets the current state. True if the file exists, false if it doesn't. + */ + public boolean get() { + return file.exists(); + } + + public boolean isOn() { return get(); } + public boolean isOff() { return !get(); } + + public void set(boolean b) { + if (b) on(); else off(); + } + + public void on() { + try { + file.getParentFile().mkdirs(); + new FileOutputStream(file).close(); + } catch (IOException e) { + LOGGER.log(Level.WARNING, "Failed to touch "+file); + } + } + + public void off() { + file.delete(); + } + + private static final Logger LOGGER = Logger.getLogger(FileBoolean.class.getName()); +} diff --git a/core/src/main/java/jenkins/util/xstream/XStreamDOM.java b/core/src/main/java/jenkins/util/xstream/XStreamDOM.java index eef29647f495..e5011d5662cc 100644 --- a/core/src/main/java/jenkins/util/xstream/XStreamDOM.java +++ b/core/src/main/java/jenkins/util/xstream/XStreamDOM.java @@ -35,10 +35,21 @@ import com.thoughtworks.xstream.io.xml.AbstractXmlWriter; import com.thoughtworks.xstream.io.xml.DocumentReader; import com.thoughtworks.xstream.io.xml.XmlFriendlyReplacer; +import com.thoughtworks.xstream.io.xml.XppDriver; import hudson.Util; import hudson.util.VariableResolver; +import hudson.util.XStream2; +import org.apache.commons.io.IOUtils; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; import java.util.ArrayList; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -61,6 +72,16 @@ * The reverse operation is {@link #from(XStream, Object)} method, which marshals an object * into {@link XStreamDOM}. * + *
+ * You can also use this class to parse an entire XML document into a DOM like tree with + * {@link #from(HierarchicalStreamReader)} and {@link #writeTo(HierarchicalStreamWriter)}. + * These two methods support variants that accept other forms. + *
+ * Whereas the above methods read from and write to {@link HierarchicalStreamReader} and,
+ * {@link HierarchicalStreamWriter}, we can also create {@link HierarchicalStreamReader}
+ * that read from DOM and {@link HierarchicalStreamWriter} that writes to DOM. See
+ * {@link #newReader()} and {@link #newWriter()} for those operations.
+ *
* @author Kohsuke Kawaguchi
* @since 1.473
*/
@@ -184,6 +205,21 @@ public static WriterImpl newWriter() {
return new WriterImpl();
}
+ /**
+ * Writes this {@link XStreamDOM} into {@link OutputStream}.
+ */
+ public void writeTo(OutputStream os) {
+ writeTo(new XppDriver().createWriter(os));
+ }
+
+ public void writeTo(Writer w) {
+ writeTo(new XppDriver().createWriter(w));
+ }
+
+ public void writeTo(HierarchicalStreamWriter w) {
+ new ConverterImpl().marshal(this,w,null);
+ }
+
/**
* Marshals the given object with the given XStream into {@link XStreamDOM} and return it.
*/
@@ -193,6 +229,25 @@ public static XStreamDOM from(XStream xs, Object obj) {
return w.getOutput();
}
+ public static XStreamDOM from(InputStream in) {
+ return from(new XppDriver().createReader(in));
+ }
+
+ public static XStreamDOM from(Reader in) {
+ return from(new XppDriver().createReader(in));
+ }
+
+ public static XStreamDOM from(HierarchicalStreamReader in) {
+ return new ConverterImpl().unmarshalElement(in, null);
+ }
+
+ public Map