mirror of
https://github.com/jenkinsci/jenkins.git
synced 2026-11-10 02:26:18 +00:00
* spelling: abstract * spelling: about * spelling: absolute * spelling: across * spelling: activity * spelling: actually * spelling: addition * spelling: allocating * spelling: ambiguous * spelling: analyzes * spelling: analysis * spelling: another * spelling: appear * spelling: arbitrary * spelling: artifact * spelling: assignment * spelling: associated * spelling: augment * spelling: authentication * spelling: automatically * spelling: available * spelling: availability * spelling: because * spelling: background * spelling: beginning * spelling: boolean * spelling: browsers * spelling: building * spelling: calculation * spelling: channel * spelling: column * spelling: concatenation * spelling: connect * spelling: contribute * spelling: convert * spelling: copied * spelling: couldn't * spelling: scrambled * spelling: creates-a * spelling: curr-entry * spelling: customize * spelling: diagnostic * spelling: contain * spelling: default * spelling: delimiter * spelling: descriptor * spelling: disambiguates * spelling: different * spelling: diligently * spelling: disabled * spelling: discovered * spelling: display * spelling: doesn't * spelling: dollar * spelling: downstream * spelling: dynamically * spelling: preemptively * spelling: encrypt * spelling: erroneous * spelling: examine * spelling: existence * spelling: value * spelling: february * spelling: handling * spelling: hostname * spelling: convenient * spelling: identify * spelling: implementation * spelling: incorrect * spelling: individual * spelling: initialization * spelling: initialized * spelling: inputstream * spelling: instantiated * spelling: instantiation * spelling: intended * spelling: interpreted * spelling: interrupted * spelling: invocations * spelling: kern * spelling: localization * spelling: logger * spelling: malfunctioning * spelling: methods * spelling: monitor * spelling: mutator * spelling: multiple * spelling: object * spelling: configured * spelling: optionally * spelling: option * spelling: overridden * spelling: parameterized * spelling: parent * spelling: permissions * spelling: plugin * spelling: potentially * spelling: preferable * spelling: problems like * spelling: programmatically * spelling: property * spelling: reallocate * spelling: recommended * spelling: redirected * spelling: registered * spelling: reliable * spelling: remember * spelling: recurrence * spelling: repeatable * spelling: repeated * spelling: resource * spelling: retrieve * spelling: returned * spelling: revision * spelling: sandwich * spelling: separator * spelling: serialization * spelling: settings * spelling: shadow * spelling: should * spelling: someone * spelling: source * spelling: specified * spelling: style * spelling: subversion * spelling: sufficient * spelling: supplementary * spelling: suppressing * spelling: synchronization * spelling: synchronized * spelling: this * spelling: transitioning * spelling: termination * spelling: trying * spelling: truncatable * spelling: unknown * spelling: undeployed * spelling: unnecessary * spelling: unparseable * spelling: update * spelling: upper * spelling: verify * spelling: visible * spelling: warning * spelling: we're * spelling: whitespace * spelling: wide * spelling: with * spelling: workspace * spelling: yielding * spelling: to * spelling: by * spelling: the * spelling: hours
168 lines
5.3 KiB
Java
168 lines
5.3 KiB
Java
/*
|
|
* The MIT License
|
|
*
|
|
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
|
|
*
|
|
* 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;
|
|
|
|
import hudson.model.Saveable;
|
|
|
|
import java.io.Closeable;
|
|
import java.io.IOException;
|
|
|
|
/**
|
|
* Transaction-like object that can be used to make a bunch of changes to an object, and defer the
|
|
* {@link Saveable#save()} until the end.
|
|
*
|
|
* <p>
|
|
* The usage of {@link BulkChange} needs to follow a specific closure-like pattern, namely:
|
|
*
|
|
* <pre>
|
|
* try (BulkChange bc = new BulkChange(someObject)) {
|
|
* ... make changes to 'someObject'
|
|
* bc.commit();
|
|
* }
|
|
* </pre>
|
|
*
|
|
* <p>
|
|
* Use of this method is optional. If {@link BulkChange} is not used, individual mutator
|
|
* will perform the save operation, and things will just run somewhat slower.
|
|
*
|
|
*
|
|
* <h2>Cooperation from {@link Saveable}</h2>
|
|
* <p>
|
|
* For this class to work as intended, {@link Saveable} implementations need to co-operate.
|
|
* Namely,
|
|
*
|
|
* <ol>
|
|
* <li>
|
|
* Mutator methods should invoke {@code this.save()} so that if the method is called outside
|
|
* a {@link BulkChange}, the result will be saved immediately.
|
|
*
|
|
* <li>
|
|
* In the {@code save()} method implementation, use {@link #contains(Saveable)} and
|
|
* only perform the actual I/O operation when this method returns false.
|
|
* </ol>
|
|
*
|
|
* <p>
|
|
* See {@link jenkins.model.Jenkins#save()} as an example if you are not sure how to implement {@link Saveable}.
|
|
*
|
|
* @author Kohsuke Kawaguchi
|
|
* @since 1.249
|
|
*/
|
|
public class BulkChange implements Closeable {
|
|
private final Saveable saveable;
|
|
public final Exception allocator;
|
|
private final BulkChange parent;
|
|
|
|
private boolean completed;
|
|
|
|
public BulkChange(Saveable saveable) {
|
|
this.parent = current();
|
|
this.saveable = saveable;
|
|
// remember who allocated this object in case
|
|
// someone forgot to call save() at the end.
|
|
allocator = new Exception();
|
|
|
|
// in effect at construction
|
|
INSCOPE.set(this);
|
|
}
|
|
|
|
/**
|
|
* Saves the accumulated changes.
|
|
*/
|
|
public void commit() throws IOException {
|
|
if(completed) return;
|
|
completed = true;
|
|
|
|
// move this object out of the scope first before save, or otherwise the save() method will do nothing.
|
|
pop();
|
|
saveable.save();
|
|
}
|
|
|
|
/**
|
|
* Alias for {@link #abort()} to make {@link BulkChange} auto-closeable.
|
|
*/
|
|
@Override
|
|
public void close() {
|
|
abort();
|
|
}
|
|
|
|
/**
|
|
* Exits the scope of {@link BulkChange} without saving the changes.
|
|
*
|
|
* <p>
|
|
* This can be used when a bulk change fails in the middle.
|
|
* Note that unlike a real transaction, this will not roll back the state of the object.
|
|
*
|
|
* <p>
|
|
* The abort method can be called after the commit method, in which case this method does nothing.
|
|
* This is so that {@link BulkChange} can be used naturally in the try/finally block.
|
|
*/
|
|
public void abort() {
|
|
if(completed) return;
|
|
completed = true;
|
|
pop();
|
|
}
|
|
|
|
private void pop() {
|
|
if(current()!=this)
|
|
throw new AssertionError("Trying to save BulkChange that's not in scope");
|
|
INSCOPE.set(parent);
|
|
}
|
|
|
|
/**
|
|
* {@link BulkChange}s that are effective currently.
|
|
*/
|
|
private static final ThreadLocal<BulkChange> INSCOPE = new ThreadLocal<BulkChange>();
|
|
|
|
/**
|
|
* Gets the {@link BulkChange} instance currently in scope for the current thread.
|
|
*/
|
|
public static BulkChange current() {
|
|
return INSCOPE.get();
|
|
}
|
|
|
|
/**
|
|
* Checks if the given {@link Saveable} is currently in the bulk change.
|
|
*
|
|
* <p>
|
|
* The expected usage is from the {@link Saveable#save()} implementation to check
|
|
* if the actual persistence should happen now or not.
|
|
*/
|
|
public static boolean contains(Saveable s) {
|
|
for(BulkChange b=current(); b!=null; b=b.parent)
|
|
if(b.saveable==s || b.saveable==ALL)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Magic {@link Saveable} instance that can make {@link BulkChange} veto
|
|
* all the save operations by making the {@link #contains(Saveable)} method return
|
|
* true for everything.
|
|
*/
|
|
public static final Saveable ALL = new Saveable() {
|
|
public void save() {
|
|
}
|
|
};
|
|
}
|