提交 c2d0a577 编写于 作者: J Jesse Glick

Merge commit '97a0fa0d' into security-master

......@@ -55,8 +55,84 @@ Upcoming changes</a>
<!-- Record your changes in the trunk here. -->
<div id="trunk" style="display:none"><!--=TRUNK-BEGIN=-->
<ul class=image>
<li class=>
</ul>
</div><!--=TRUNK-END=-->
<h3><a name=v2.1>What's new in 2.1</a> (2016/05/01)</h3>
<ul class=image>
<li class="major bug">
Enable disabled dependencies during plugin installations.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-34494">issue 34494</a>)
<li class="major bug">
Force ordering between GPG and jarsigner to ensure correct GPG signature.
(<a href="https://github.com/jenkinsci/jenkins/pull/2285">pull 2285</a>)
<li class="major bug">
Secured Jenkins installations didn't properly save the queue on shutdown.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-34281">issue 34281</a>)
<li class="rfe">
Add dependency resolution to manually uploaded plugins.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-15057">issue 15057</a>)
<li class="rfe">
Show Jenkins version on setup wizard.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-33535">issue 33535</a>)
<li class="rfe">
Update remoting to 2.57.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-33999">issue 33999</a>)
<li class="rfe">
Allow retrying plugin downloads in setup wizard.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-33244">issue 33244</a>)
<li class="rfe">
Add links to homepage of plugins and dependencies in setup wizard.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-33936">issue 33936</a>,
<a href="https://issues.jenkins-ci.org/browse/JENKINS-33937">issue 33937</a>)
<li class="rfe">
Improved handling of the 'close' button during setup wizard.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-34137">issue 34137</a>)
<li class="rfe">
Wrong spacing in flat mode of 'Create Item' screen.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-31162">issue 31162</a>)
<li class="rfe">
Add timestamp to the <tt>jarsigner</tt> signature.
(<a href="https://github.com/jenkinsci/jenkins/pull/2284">pull 2284</a>)
<li class="rfe">
Improved French translation.
(<a href="https://github.com/jenkinsci/jenkins/pull/2267">pull 2267</a>)
<li class="rfe">
Improved Lithuanian translation.
(<a href="https://github.com/jenkinsci/jenkins/pull/2286">pull 2286</a>)
<li class="rfe">
Improved Brazilian Portuguese translation.
(<a href="https://github.com/jenkinsci/jenkins/pull/2273">pull 2273</a>)
<li class="bug">
Prevent errors when hiding management links.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-33683">issue 33683</a>)
<li class="bug">
Internal: Make logger field private.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-34093">issue 34093</a>)
<li class="bug">
Shorter timeout for plugin downloads to prevent setup wizard from hanging.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-34174">issue 34174</a>)
<li class="bug">
Check if job is buildable before showing 'Build with parameters' page.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-34146">issue 34146</a>)
<li class="bug">
Fixed race condition in slave offline cause.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-34448">issue 34448</a>)
<li class="bug">
Allow enabling disabled dependencies in the plugin manager to fix broken configurations.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-32340">issue 32340</a>)
<li class="bug">
Always display clicked scrollspy items as active in setup wizard.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-33948">issue 33948</a>)
<li class="bug">
Prevent multiple installations of the same dependency.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-33950">issue 33950</a>)
</ul>
<h3><a name=v2.0>What's new in 2.0</a> (2016/04/20)</h3>
<div style="margin: 10px; padding: 10px; background-color: #FFFFCE;">
<strong>More detailed information about the new features in Jenkins 2.0 <a href="/2.0/">on the overview page</a>.</strong>
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>2.1-SNAPSHOT</version>
<version>2.3-SNAPSHOT</version>
</parent>
<artifactId>cli</artifactId>
......
......@@ -29,7 +29,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>2.1-SNAPSHOT</version>
<version>2.3-SNAPSHOT</version>
</parent>
<artifactId>jenkins-core</artifactId>
......@@ -39,7 +39,7 @@ THE SOFTWARE.
<properties>
<staplerFork>true</staplerFork>
<stapler.version>1.239</stapler.version>
<stapler.version>1.243</stapler.version>
<spring.version>2.5.6.SEC03</spring.version>
<groovy.version>2.4.6</groovy.version>
</properties>
......@@ -558,6 +558,11 @@ THE SOFTWARE.
<artifactId>robust-http-client</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci</groupId>
<artifactId>symbol-annotation</artifactId>
<version>1.1</version>
</dependency>
<dependency><!-- Jenkins doesn't depend on it but some plugin wants the latest version. Bundling 1.6 until we figure out a mechanism to let plugins load its own -->
<groupId>commons-codec</groupId>
......
......@@ -2,6 +2,8 @@ package hudson;
import hudson.model.ManagementLink;
import java.net.URL;
import org.jenkinsci.Symbol;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
......@@ -10,7 +12,7 @@ import org.kohsuke.accmod.restrictions.NoExternalUse;
*
* @author Kohsuke Kawaguchi
*/
@Extension
@Extension @Symbol("about")
public class AboutJenkins extends ManagementLink {
@Override
public String getIconFileName() {
......
......@@ -431,7 +431,7 @@ public abstract class ExtensionFinder implements ExtensionPoint {
if (verbose) {
LOGGER.log(Level.WARNING, "Failed to instantiate " + key + "; skipping this component", x);
} else {
LOGGER.log(Level.WARNING, "Failed to instantiate optional component {0}; skipping", key.getTypeLiteral());
LOGGER.log(Level.INFO, "Failed to instantiate optional component {0}; skipping", key.getTypeLiteral());
LOGGER.log(Level.FINE, key.toString(), x);
}
}
......
......@@ -34,6 +34,7 @@ import hudson.util.io.ArchiverFactory;
import jenkins.model.Jenkins;
import hudson.model.listeners.RunListener;
import hudson.scm.SCM;
import org.jenkinsci.Symbol;
import java.io.BufferedOutputStream;
import java.io.File;
......@@ -235,7 +236,7 @@ public abstract class FileSystemProvisioner implements ExtensionPoint, Describab
}
}
@Extension
@Extension @Symbol("standard")
public static final class DescriptorImpl extends FileSystemProvisionerDescriptor {
public boolean discard(FilePath ws, TaskListener listener) throws IOException, InterruptedException {
// the default provisioner does not do anything special,
......
......@@ -66,6 +66,7 @@ import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.LogFactory;
import org.jenkinsci.Symbol;
import org.jenkinsci.bytecode.Transformer;
import org.jvnet.hudson.reactor.Executable;
import org.jvnet.hudson.reactor.Reactor;
......@@ -108,6 +109,7 @@ import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.ListIterator;
......@@ -452,6 +454,14 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas
session.addAll(g.discoverTasks(session));
}
});
// All plugins are loaded. Now we can figure out who depends on who.
requires(PLUGINS_PREPARED).attains(COMPLETED).add("Resolving Dependant Plugins Graph", new Executable() {
@Override
public void run(Reactor reactor) throws Exception {
resolveDependantPlugins();
}
});
}});
}
......@@ -660,6 +670,14 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas
* TODO: revisit where/how to expose this. This is an experiment.
*/
public void dynamicLoad(File arc) throws IOException, InterruptedException, RestartRequiredException {
dynamicLoad(arc, false);
}
/**
* Try the dynamicLoad, removeExisting to attempt to dynamic load disabled plugins
*/
@Restricted(NoExternalUse.class)
public void dynamicLoad(File arc, boolean removeExisting) throws IOException, InterruptedException, RestartRequiredException {
LOGGER.info("Attempting to dynamic load "+arc);
PluginWrapper p = null;
String sn;
......@@ -670,9 +688,21 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas
p = strategy.createPluginWrapper(arc);
sn = p.getShortName();
}
if (getPlugin(sn)!=null)
throw new RestartRequiredException(Messages._PluginManager_PluginIsAlreadyInstalled_RestartRequired(sn));
PluginWrapper pw = getPlugin(sn);
if (pw!=null) {
if (removeExisting) { // try to load disabled plugins
for (Iterator<PluginWrapper> i = plugins.iterator(); i.hasNext();) {
pw = i.next();
if(sn.equals(pw.getShortName())) {
i.remove();
pw = null;
break;
}
}
} else {
throw new RestartRequiredException(Messages._PluginManager_PluginIsAlreadyInstalled_RestartRequired(sn));
}
}
if (p == null) {
p = strategy.createPluginWrapper(arc);
}
......@@ -1698,7 +1728,7 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas
/**
* {@link AdministrativeMonitor} that checks if there are any plugins with cycle dependencies.
*/
@Extension
@Extension @Symbol("pluginCycleDependencies")
public static final class PluginCycleDependenciesMonitor extends AdministrativeMonitor {
private transient volatile boolean isActive = false;
......@@ -1727,7 +1757,7 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas
* {@link AdministrativeMonitor} that informs the administrator about a required plugin update.
* @since 1.491
*/
@Extension
@Extension @Symbol("pluginUpdate")
public static final class PluginUpdateMonitor extends AdministrativeMonitor {
private Map<String, PluginUpdateInfo> pluginsToBeUpdated = new HashMap<String, PluginManager.PluginUpdateMonitor.PluginUpdateInfo>();
......
......@@ -55,6 +55,7 @@ import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.GetMethod;
import org.jenkinsci.Symbol;
import org.jvnet.robust_http_client.RetryableHttpStream;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
......@@ -306,7 +307,7 @@ public final class ProxyConfiguration extends AbstractDescribableImpl<ProxyConfi
XSTREAM.alias("proxy", ProxyConfiguration.class);
}
@Extension
@Extension @Symbol("proxy")
public static class DescriptorImpl extends Descriptor<ProxyConfiguration> {
@Override
public String getDisplayName() {
......
......@@ -43,6 +43,9 @@ import org.apache.tools.ant.taskdefs.Chmod;
import org.apache.tools.ant.taskdefs.Copy;
import org.apache.tools.ant.types.FileSet;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import jnr.posix.FileStat;
import jnr.posix.POSIX;
......@@ -216,24 +219,54 @@ public class Util {
/**
* Deletes the contents of the given directory (but not the directory itself)
* recursively.
* It does not take no for an answer - if necessary, it will have multiple
* attempts at deleting things.
*
* @throws IOException
* if the operation fails.
*/
public static void deleteContentsRecursive(@Nonnull File file) throws IOException {
File[] files = file.listFiles();
if(files==null)
return; // the directory didn't exist in the first place
for (File child : files)
deleteRecursive(child);
for( int numberOfAttempts=1 ; ; numberOfAttempts++ ) {
try {
tryOnceDeleteContentsRecursive(file);
break; // success
} catch (IOException ex) {
boolean threadWasInterrupted = pauseBetweenDeletes(numberOfAttempts);
if( numberOfAttempts>= DELETION_MAX || threadWasInterrupted)
throw new IOException(deleteFailExceptionMessage(file, numberOfAttempts, threadWasInterrupted), ex);
}
}
}
/**
* Deletes this file (and does not take no for an answer).
* If necessary, it will have multiple attempts at deleting things.
*
* @param f a file to delete
* @throws IOException if it exists but could not be successfully deleted
*/
public static void deleteFile(@Nonnull File f) throws IOException {
for( int numberOfAttempts=1 ; ; numberOfAttempts++ ) {
try {
tryOnceDeleteFile(f);
break; // success
} catch (IOException ex) {
boolean threadWasInterrupted = pauseBetweenDeletes(numberOfAttempts);
if( numberOfAttempts>= DELETION_MAX || threadWasInterrupted)
throw new IOException(deleteFailExceptionMessage(f, numberOfAttempts, threadWasInterrupted), ex);
}
}
}
/**
* Deletes this file, working around most problems which might make
* this difficult.
*
* @param f
* What to delete. If a directory, it'll need to be empty.
* @throws IOException if it exists but could not be successfully deleted
*/
private static void tryOnceDeleteFile(File f) throws IOException {
if (!f.delete()) {
if(!f.exists())
// we are trying to delete a file that no longer exists, so this is not an error
......@@ -302,21 +335,146 @@ public class Util {
}
/**
* Deletes the given directory (including its contents) recursively.
* It does not take no for an answer - if necessary, it will have multiple
* attempts at deleting things.
*
* @throws IOException
* if the operation fails.
*/
public static void deleteRecursive(@Nonnull File dir) throws IOException {
for( int numberOfAttempts=1 ; ; numberOfAttempts++ ) {
try {
tryOnceDeleteRecursive(dir);
break; // success
} catch (IOException ex) {
boolean threadWasInterrupted = pauseBetweenDeletes(numberOfAttempts);
if( numberOfAttempts>= DELETION_MAX || threadWasInterrupted)
throw new IOException(deleteFailExceptionMessage(dir, numberOfAttempts, threadWasInterrupted), ex);
}
}
}
/**
* Deletes a file or folder, throwing the first exception encountered, but
* having a go at deleting everything. i.e. it does not <em>stop</em> on the
* first exception, but tries (to delete) everything once.
*
* @param dir
* What to delete. If a directory, the contents will be deleted
* too.
* @throws The first exception encountered.
*/
private static void tryOnceDeleteRecursive(File dir) throws IOException {
if(!isSymlink(dir))
deleteContentsRecursive(dir);
tryOnceDeleteContentsRecursive(dir);
tryOnceDeleteFile(dir);
}
/**
* Deletes a folder's contents, throwing the first exception encountered,
* but having a go at deleting everything. i.e. it does not <em>stop</em>
* on the first exception, but tries (to delete) everything once.
*
* @param directory
* The directory whose contents will be deleted.
* @throws The first exception encountered.
*/
private static void tryOnceDeleteContentsRecursive(File directory) throws IOException {
File[] directoryContents = directory.listFiles();
if(directoryContents==null)
return; // the directory didn't exist in the first place
IOException firstCaught = null;
for (File child : directoryContents) {
try {
tryOnceDeleteRecursive(child);
} catch (IOException justCaught) {
if( firstCaught==null) {
firstCaught = justCaught;
}
}
}
if( firstCaught!=null )
throw firstCaught;
}
/**
* Pauses between delete attempts, and says if it's ok to try again.
* This does not wait if the wait time is zero or if we have tried
* too many times already.
* <p>
* See {@link #WAIT_BETWEEN_DELETION_RETRIES} for details of
* the pause duration.<br/>
* See {@link #GC_AFTER_FAILED_DELETE} for when {@link System#gc()} is called.
*
* @return false if it is ok to continue trying to delete things, true if
* we were interrupted (and should stop now).
*/
private static boolean pauseBetweenDeletes(int numberOfAttemptsSoFar) {
long delayInMs;
if( numberOfAttemptsSoFar>=DELETION_MAX ) return false;
/* If the Jenkins process had the file open earlier, and it has not
* closed it then Windows won't let us delete it until the Java object
* with the open stream is Garbage Collected, which can result in builds
* failing due to "file in use" on Windows despite working perfectly
* well on other OSs. */
if (GC_AFTER_FAILED_DELETE) {
System.gc();
}
if (WAIT_BETWEEN_DELETION_RETRIES>=0) {
delayInMs = WAIT_BETWEEN_DELETION_RETRIES;
} else {
delayInMs = -numberOfAttemptsSoFar*WAIT_BETWEEN_DELETION_RETRIES;
}
if (delayInMs<=0)
return Thread.interrupted();
try {
deleteFile(dir);
} catch (IOException e) {
// if some of the child directories are big, it might take long enough to delete that
// it allows others to create new files, causing problemsl ike JENKINS-10113
// so give it one more attempt before we give up.
if(!isSymlink(dir))
deleteContentsRecursive(dir);
deleteFile(dir);
Thread.sleep(delayInMs);
return false;
} catch (InterruptedException e) {
return true;
}
}
/**
* Creates a "couldn't delete file" message that explains how hard we tried.
* See {@link #DELETION_MAX}, {@link #WAIT_BETWEEN_DELETION_RETRIES}
* and {@link #GC_AFTER_FAILED_DELETE} for more details.
*/
private static String deleteFailExceptionMessage(File whatWeWereTryingToRemove, int retryCount, boolean wasInterrupted) {
StringBuilder sb = new StringBuilder();
sb.append("Unable to delete '");
sb.append(whatWeWereTryingToRemove);
sb.append("'. Tried ");
sb.append(retryCount);
sb.append(" time");
if( retryCount!=1 ) sb.append('s');
if( DELETION_MAX>1 ) {
sb.append(" (of a maximum of ");
sb.append(DELETION_MAX);
sb.append(')');
if( GC_AFTER_FAILED_DELETE )
sb.append(" garbage-collecting");
if( WAIT_BETWEEN_DELETION_RETRIES!=0 && GC_AFTER_FAILED_DELETE )
sb.append(" and");
if( WAIT_BETWEEN_DELETION_RETRIES!=0 ) {
sb.append(" waiting ");
sb.append(getTimeSpanString(Math.abs(WAIT_BETWEEN_DELETION_RETRIES)));
if( WAIT_BETWEEN_DELETION_RETRIES<0 ) {
sb.append("-");
sb.append(getTimeSpanString(Math.abs(WAIT_BETWEEN_DELETION_RETRIES)*DELETION_MAX));
}
}
if( WAIT_BETWEEN_DELETION_RETRIES!=0 || GC_AFTER_FAILED_DELETE)
sb.append(" between attempts");
}
if( wasInterrupted )
sb.append(". The delete operation was interrupted before it completed successfully");
sb.append('.');
return sb.toString();
}
/*
* Copyright 2001-2004 The Apache Software Foundation.
*
......@@ -1479,4 +1637,57 @@ public class Util {
public static boolean NO_SYMLINK = Boolean.getBoolean(Util.class.getName()+".noSymLink");
public static boolean SYMLINK_ESCAPEHATCH = Boolean.getBoolean(Util.class.getName()+".symlinkEscapeHatch");
/**
* The number of times we will attempt to delete files/directory trees
* before giving up and throwing an exception.<br/>
* Specifying a value less than 1 is invalid and will be treated as if
* a value of 1 (i.e. one attempt, no retries) was specified.
* <p>
* e.g. if some of the child directories are big, it might take long enough
* to delete that it allows others to create new files in the directory we
* are trying to empty, causing problems like JENKINS-10113.
* Or, if we're on Windows, then deletes can fail for transient reasons
* regardless of external activity; see JENKINS-15331.
* Whatever the reason, this allows us to do multiple attempts before we
* give up, thus improving build reliability.
*/
@Restricted(value = NoExternalUse.class)
static int DELETION_MAX = Math.max(1, Integer.getInteger(Util.class.getName() + ".maxFileDeletionRetries", 3).intValue());
/**
* The time (in milliseconds) that we will wait between attempts to
* delete files when retrying.<br>
* This has no effect unless {@link #DELETION_MAX} is non-zero.
* <p>
* If zero, we will not delay between attempts.<br>
* If negative, we will wait an (linearly) increasing multiple of this value
* between attempts.
*/
@Restricted(value = NoExternalUse.class)
static int WAIT_BETWEEN_DELETION_RETRIES = Integer.getInteger(Util.class.getName() + ".deletionRetryWait", 100).intValue();
/**
* If this flag is set to true then we will request a garbage collection
* after a deletion failure before we next retry the delete.<br>
* It defaults to <code>false</code> and is ignored unless
* {@link #DELETION_MAX} is greater than 1.
* <p>
* Setting this flag to true <i>may</i> resolve some problems on Windows,
* and also for directory trees residing on an NFS share, <b>but</b> it can
* have a negative impact on performance and may have no effect at all (GC
* behavior is JVM-specific).
* <p>
* Warning: This should only ever be used if you find that your builds are
* failing because Jenkins is unable to delete files, that this failure is
* because Jenkins itself has those files locked "open", and even then it
* should only be used on slaves with relatively few executors (because the
* garbage collection can impact the performance of all job executors on
* that slave).<br/>
* i.e. Setting this flag is a act of last resort - it is <em>not</em>
* recommended, and should not be used on the main Jenkins server
* unless you can tolerate the performance impact.
*/
@Restricted(value = NoExternalUse.class)
static boolean GC_AFTER_FAILED_DELETE = Boolean.getBoolean(Util.class.getName() + ".performGCOnFailedDelete");
}
......@@ -224,6 +224,11 @@ public class WebAppMain implements ServletContextListener {
boolean success = false;
try {
Jenkins instance = new Hudson(_home, context);
// one last check to make sure everything is in order before we go live
if (Thread.interrupted())
throw new InterruptedException();
context.setAttribute(APP, instance);
BootFailure.getBootFailureFile(_home).delete();
......
......@@ -34,6 +34,7 @@ import javax.servlet.http.HttpServletResponse;
import hudson.model.UnprotectedRootAction;
import jenkins.model.Jenkins;
import org.jenkinsci.Symbol;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.HttpResponses.HttpResponseException;
......@@ -51,7 +52,7 @@ import hudson.remoting.Channel;
*
* @author ogondza
*/
@Extension
@Extension @Symbol("cli")
@Restricted(NoExternalUse.class)
public class CLIAction implements UnprotectedRootAction, StaplerProxy {
......
......@@ -8,6 +8,7 @@ import hudson.remoting.ChannelBuilder;
import jenkins.AgentProtocol;
import jenkins.model.Jenkins;
import jenkins.slaves.NioChannelSelector;
import org.jenkinsci.Symbol;
import org.jenkinsci.remoting.nio.NioChannelHub;
import javax.inject.Inject;
......@@ -25,7 +26,7 @@ import java.net.Socket;
* @author Kohsuke Kawaguchi
* @since 1.467
*/
@Extension
@Extension @Symbol("cli")
public class CliProtocol extends AgentProtocol {
@Inject
NioChannelSelector nio;
......
......@@ -2,6 +2,7 @@ package hudson.cli;
import hudson.Extension;
import jenkins.model.Jenkins;
import org.jenkinsci.Symbol;
import org.jenkinsci.remoting.nio.NioChannelHub;
import javax.crypto.SecretKey;
......@@ -20,7 +21,7 @@ import java.security.Signature;
* @author Kohsuke Kawaguchi
* @since 1.467
*/
@Extension
@Extension @Symbol("cli2")
public class CliProtocol2 extends CliProtocol {
@Override
public String getName() {
......
......@@ -25,6 +25,7 @@ package hudson.console;
import hudson.Extension;
import hudson.MarkupText;
import org.jenkinsci.Symbol;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
......@@ -95,7 +96,7 @@ public class HudsonExceptionNote extends ConsoleNote<Object> {
return "http://stacktrace.jenkins-ci.org/search?query="+className;
}
@Extension
@Extension @Symbol("stackTrace")
public static final class DescriptorImpl extends ConsoleAnnotationDescriptor {
@Override
public String getDisplayName() {
......
......@@ -26,6 +26,7 @@ package hudson.console;
import hudson.Extension;
import hudson.MarkupText;
import jenkins.model.Jenkins;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest;
......@@ -83,7 +84,7 @@ public class HyperlinkNote extends ConsoleNote {
}
}
@Extension
@Extension @Symbol("hyperlink")
public static class DescriptorImpl extends ConsoleAnnotationDescriptor {
public String getDisplayName() {
return "Hyperlinks";
......
......@@ -3,6 +3,7 @@ package hudson.console;
import hudson.Extension;
import hudson.model.*;
import jenkins.model.Jenkins;
import org.jenkinsci.Symbol;
import java.io.IOException;
import java.util.logging.Level;
......@@ -64,7 +65,7 @@ public class ModelHyperlinkNote extends HyperlinkNote {
}
}
@Extension
@Extension @Symbol("hyperlinkToModels")
public static class DescriptorImpl extends HyperlinkNote.DescriptorImpl {
public String getDisplayName() {
return "Hyperlinks to models";
......
......@@ -3,6 +3,7 @@ package hudson.console;
import hudson.Extension;
import hudson.MarkupText;
import hudson.MarkupText.SubText;
import org.jenkinsci.Symbol;
import java.util.regex.Pattern;
......@@ -11,7 +12,7 @@ import java.util.regex.Pattern;
*
* @author Kohsuke Kawaguchi
*/
@Extension
@Extension @Symbol("url")
public class UrlAnnotator extends ConsoleAnnotatorFactory<Object> {
@Override
public ConsoleAnnotator newInstance(Object context) {
......
......@@ -26,6 +26,7 @@ package hudson.diagnosis;
import hudson.Extension;
import jenkins.model.Jenkins;
import hudson.model.PeriodicWork;
import org.jenkinsci.Symbol;
import java.util.logging.Logger;
......@@ -35,7 +36,7 @@ import java.util.logging.Logger;
*
* @author Kohsuke Kawaguchi
*/
@Extension
@Extension @Symbol("diskUsageCheck")
public class HudsonHomeDiskUsageChecker extends PeriodicWork {
public long getRecurrencePeriod() {
return HOUR;
......
......@@ -28,6 +28,7 @@ import hudson.model.AbstractModelObject;
import hudson.Extension;
import hudson.ExtensionPoint;
import hudson.ExtensionList;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.HttpResponses;
import org.kohsuke.stapler.QueryParameter;
......@@ -40,7 +41,7 @@ import java.util.List;
*
* @author Kohsuke Kawaguchi
*/
@Extension
@Extension @Symbol("diskUsageCheck")
public final class HudsonHomeDiskUsageMonitor extends AdministrativeMonitor {
/**
* Value updated by {@link HudsonHomeDiskUsageChecker}.
......
......@@ -39,6 +39,7 @@ import java.util.List;
import java.util.ArrayList;
import java.io.IOException;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.QueryParameter;
/**
......@@ -46,7 +47,7 @@ import org.kohsuke.stapler.QueryParameter;
*
* @author Kohsuke Kawaguchi
*/
@Extension
@Extension @Symbol("memoryUsage")
public final class MemoryUsageMonitor extends PeriodicWork {
/**
* A memory group is conceptually a set of memory pools.
......
......@@ -29,6 +29,7 @@ import hudson.init.Initializer;
import hudson.model.AdministrativeMonitor;
import hudson.model.Descriptor;
import jenkins.model.Jenkins;
import org.jenkinsci.Symbol;
import java.text.MessageFormat;
import java.util.ArrayList;
......@@ -46,7 +47,7 @@ import static hudson.init.InitMilestone.EXTENSIONS_AUGMENTED;
* @author Kohsuke Kawaguchi
* @since 1.402
*/
@Extension
@Extension @Symbol("nullId")
public class NullIdDescriptorMonitor extends AdministrativeMonitor {
private final List<Descriptor> problems = new ArrayList<Descriptor>();
......
......@@ -55,6 +55,7 @@ import javax.annotation.CheckForNull;
import jenkins.model.Jenkins;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder;
import org.jenkinsci.Symbol;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.HttpRedirect;
......@@ -70,7 +71,7 @@ import org.kohsuke.stapler.interceptor.RequirePOST;
*
* @author Alan.Harder@Sun.Com
*/
@Extension
@Extension @Symbol("oldData")
public class OldDataMonitor extends AdministrativeMonitor {
private static final Logger LOGGER = Logger.getLogger(OldDataMonitor.class.getName());
......@@ -430,7 +431,7 @@ public class OldDataMonitor extends AdministrativeMonitor {
}
}
@Extension
@Extension @Symbol("oldData")
public static class ManagementLinkImpl extends ManagementLink {
@Override
public String getIconFileName() {
......
......@@ -26,6 +26,7 @@ package hudson.diagnosis;
import hudson.Extension;
import hudson.Util;
import hudson.model.AdministrativeMonitor;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.HttpRedirect;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.HttpResponses;
......@@ -48,7 +49,7 @@ import org.kohsuke.stapler.Stapler;
*
* @author Kohsuke Kawaguchi
*/
@Extension
@Extension @Symbol("reverseProxy")
public class ReverseProxySetupMonitor extends AdministrativeMonitor {
private static final Logger LOGGER = Logger.getLogger(ReverseProxySetupMonitor.class.getName());
......
......@@ -26,6 +26,7 @@ package hudson.diagnosis;
import hudson.model.AdministrativeMonitor;
import jenkins.model.Jenkins;
import hudson.Extension;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
......@@ -39,7 +40,7 @@ import java.io.IOException;
*
* @author Kohsuke Kawaguchi
*/
@Extension
@Extension @Symbol("tooManyJobsButNoView")
public class TooManyJobsButNoView extends AdministrativeMonitor {
public boolean isActivated() {
Jenkins h = Jenkins.getInstance();
......
......@@ -29,10 +29,12 @@ import hudson.markup.MarkupFormatter;
import hudson.markup.MarkupFormatterDescriptor;
import java.io.IOException;
import java.io.Writer;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
/**
* @link MarkupFormatter} that treats the input as the escaped html.
* {@link MarkupFormatter} that treats the input as the escaped html.
*
* @author Seiji Sogabe
* @since 1.553
......@@ -48,7 +50,7 @@ public class EscapedMarkupFormatter extends MarkupFormatter {
output.write(Util.escape(markup));
}
@Extension
@Extension @Symbol("plainText")
public static class DescriptorImpl extends MarkupFormatterDescriptor {
@Override
......
......@@ -23,6 +23,7 @@
*/
package hudson.model;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest;
......@@ -88,7 +89,7 @@ public class AllView extends View {
// noop
}
@Extension
@Extension @Symbol("all")
public static final class DescriptorImpl extends ViewDescriptor {
@Override
public boolean isInstantiable() {
......
......@@ -23,6 +23,7 @@
*/
package hudson.model;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.DataBoundConstructor;
import net.sf.json.JSONObject;
......@@ -72,7 +73,9 @@ public class BooleanParameterDefinition extends SimpleParameterDefinition {
return new BooleanParameterValue(getName(), defaultValue, getDescription());
}
@Extension
// unlike all the other ParameterDescriptors, using 'booleanParam' as the primary
// to avoid picking the Java reserved word "boolean" as the primary identifier
@Extension @Symbol({"booleanParam"})
public static class DescriptorImpl extends ParameterDescriptor {
@Override
public String getDisplayName() {
......
package hudson.model;
import hudson.util.FormValidation;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.DataBoundConstructor;
......@@ -91,7 +92,7 @@ public class ChoiceParameterDefinition extends SimpleParameterDefinition {
return checkValue(new StringParameterValue(getName(), value, getDescription()));
}
@Extension
@Extension @Symbol({"choice","choiceParam"})
public static class DescriptorImpl extends ParameterDescriptor {
@Override
public String getDisplayName() {
......
......@@ -523,6 +523,10 @@ public /*transient*/ abstract class Computer extends Actionable implements Acces
setTemporarilyOffline(true, new ByCLI(cause));
}
/**
* @deprecated Implementation of CLI command "online-node" moved to {@link hudson.cli.OnlineNodeCommand}.
*/
@Deprecated
public void cliOnline() throws ExecutionException, InterruptedException {
checkPermission(CONNECT);
setTemporarilyOffline(false, null);
......
......@@ -24,6 +24,7 @@
package hudson.model;
import net.sf.json.JSONObject;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
import hudson.Extension;
......@@ -56,7 +57,7 @@ public class FileParameterDefinition extends ParameterDefinition {
return p;
}
@Extension
@Extension @Symbol({"file","fileParam"})
public static class DescriptorImpl extends ParameterDescriptor {
@Override
public String getDisplayName() {
......
......@@ -26,6 +26,7 @@ package hudson.model;
import hudson.Extension;
import hudson.ExtensionList;
import jenkins.model.Jenkins;
import org.jenkinsci.Symbol;
import java.io.File;
import java.io.FileFilter;
......@@ -42,7 +43,7 @@ import java.util.regex.Pattern;
*
* @author Kohsuke Kawaguchi
*/
@Extension
@Extension @Symbol("fingerprintCleanup")
public final class FingerprintCleanupThread extends AsyncPeriodicWork {
public FingerprintCleanupThread() {
......
......@@ -25,6 +25,7 @@ package hudson.model;
import hudson.Extension;
import jenkins.model.Jenkins;
import org.jenkinsci.Symbol;
import jenkins.model.item_category.StandaloneProjectsCategory;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
......@@ -60,12 +61,18 @@ public class FreeStyleProject extends Project<FreeStyleProject,FreeStyleBuild> i
/**
* Descriptor is instantiated as a field purely for backward compatibility.
* Do not do this in your code. Put @Extension on your DescriptorImpl class instead.
*
* @deprecated as of 2.0
* Use injection
*/
@Restricted(NoExternalUse.class)
@Extension(ordinal=1000)
public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();
public static /*almost final*/ DescriptorImpl DESCRIPTOR;
public static final class DescriptorImpl extends AbstractProjectDescriptor {
@Extension(ordinal=1000) @Symbol({"freeStyle","freeStyleJob"})
public static class DescriptorImpl extends AbstractProjectDescriptor {
public DescriptorImpl() {
DESCRIPTOR = this;
}
public String getDisplayName() {
return Messages.FreeStyleProject_DisplayName();
......
......@@ -182,15 +182,21 @@ public class Items {
* Does the opposite of {@link #toNameList(Collection)}.
*/
public static <T extends Item> List<T> fromNameList(ItemGroup context, @Nonnull String list, @Nonnull Class<T> type) {
Jenkins hudson = Jenkins.getInstance();
final Jenkins jenkins = Jenkins.getInstance();
List<T> r = new ArrayList<T>();
if (jenkins == null) {
return r;
}
StringTokenizer tokens = new StringTokenizer(list,",");
while(tokens.hasMoreTokens()) {
String fullName = tokens.nextToken().trim();
T item = hudson.getItem(fullName, context, type);
if(item!=null)
r.add(item);
if (StringUtils.isNotEmpty(fullName)) {
T item = jenkins.getItem(fullName, context, type);
if(item!=null)
r.add(item);
}
}
return r;
}
......
......@@ -44,6 +44,7 @@ import java.util.Arrays;
import java.util.Collections;
import jenkins.model.Jenkins;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
......@@ -166,7 +167,7 @@ public final class JDK extends ToolInstallation implements NodeSpecific<JDK>, En
}
}
@Extension
@Extension @Symbol("jdk")
public static class DescriptorImpl extends ToolDescriptor<JDK> {
public String getDisplayName() {
......
......@@ -49,10 +49,12 @@ import javax.servlet.ServletException;
import jenkins.model.Jenkins;
import net.sf.json.JSONObject;
import org.jenkinsci.Symbol;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
......@@ -109,6 +111,14 @@ public class ListView extends View implements DirectlyModifiableView {
this.owner = owner;
}
/**
* Sets the columns of this view.
*/
@DataBoundSetter
public void setColumns(List<ListViewColumn> columns) throws IOException {
this.columns.replaceBy(columns);
}
private Object readResolve() {
if(includeRegex!=null) {
try {
......@@ -398,7 +408,7 @@ public class ListView extends View implements DirectlyModifiableView {
this.includePattern = Pattern.compile(includeRegex);
}
@Extension
@Extension @Symbol("list")
public static class DescriptorImpl extends ViewDescriptor {
@Override
public String getDisplayName() {
......
......@@ -31,6 +31,7 @@ import hudson.model.queue.Tasks;
import hudson.util.ColorPalette;
import hudson.util.NoOverlapCategoryAxis;
import jenkins.model.Jenkins;
import org.jenkinsci.Symbol;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
......@@ -380,7 +381,7 @@ public abstract class LoadStatistics {
/**
* Periodically update the load statistics average.
*/
@Extension
@Extension @Symbol("loadStatistics")
public static class LoadStatisticsUpdater extends PeriodicWork {
public long getRecurrencePeriod() {
return CLOCK;
......
......@@ -25,13 +25,14 @@ package hudson.model;
import hudson.Extension;
import jenkins.model.Jenkins;
import org.jenkinsci.Symbol;
/**
* Adds the "Manage Jenkins" link to the top page.
*
* @author Kohsuke Kawaguchi
*/
@Extension(ordinal=100)
@Extension(ordinal=100) @Symbol("manageJenkins")
public class ManageJenkinsAction implements RootAction {
public String getIconFileName() {
if (Jenkins.getInstance().hasPermission(Jenkins.ADMINISTER))
......
......@@ -32,6 +32,7 @@ import java.util.List;
import javax.servlet.ServletException;
import jenkins.model.Jenkins;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.DataBoundConstructor;
......@@ -93,7 +94,7 @@ public class MyView extends View {
// noop
}
@Extension
@Extension @Symbol("myView")
public static final class DescriptorImpl extends ViewDescriptor {
/**
* If the security is not enabled, there's no point in having
......
......@@ -45,6 +45,7 @@ import jenkins.model.Jenkins;
import net.sf.json.JSONObject;
import org.acegisecurity.AccessDeniedException;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.HttpRedirect;
import org.kohsuke.stapler.HttpResponse;
......@@ -201,7 +202,7 @@ public class MyViewsProperty extends UserProperty implements ModifiableViewGroup
return "my-views";
}
@Extension
@Extension @Symbol("myView")
public static class DescriptorImpl extends UserPropertyDescriptor {
@Override
......@@ -242,7 +243,7 @@ public class MyViewsProperty extends UserProperty implements ModifiableViewGroup
return Jenkins.getInstance().getMyViewsTabBar();
}
@Extension
@Extension @Symbol("myView")
public static class GlobalAction implements RootAction {
public String getDisplayName() {
......
......@@ -8,6 +8,7 @@ import java.io.IOException;
import javax.servlet.http.HttpSession;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.Stapler;
public class PaneStatusProperties extends UserProperty implements Saveable {
......@@ -43,7 +44,7 @@ public class PaneStatusProperties extends UserProperty implements Saveable {
return this;
}
@Extension
@Extension @Symbol("paneStatus")
public static class DescriptorImpl extends UserPropertyDescriptor {
@Override
......
......@@ -24,6 +24,7 @@
package hudson.model;
import net.sf.json.JSONObject;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.DataBoundConstructor;
import hudson.Extension;
......@@ -88,7 +89,7 @@ public class PasswordParameterDefinition extends SimpleParameterDefinition {
this.defaultValue = Secret.fromString(defaultValue);
}
@Extension
@Extension @Symbol({"password","nonStoredPasswordParam"})
public final static class ParameterDescriptorImpl extends ParameterDescriptor {
@Override
public String getDisplayName() {
......
......@@ -32,6 +32,7 @@ import java.util.Collection;
import javax.servlet.ServletException;
import jenkins.model.Jenkins;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.Stapler;
......@@ -120,7 +121,7 @@ public class ProxyView extends View implements StaplerFallback {
return FormValidation.error(Messages.ProxyView_NoSuchViewExists(value));
}
@Extension
@Extension @Symbol("proxy")
public static class DescriptorImpl extends ViewDescriptor {
@Override
......
......@@ -26,6 +26,7 @@ package hudson.model;
import jenkins.model.Jenkins;
import net.sf.json.JSONObject;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.export.Exported;
......@@ -133,7 +134,7 @@ public class RunParameterDefinition extends SimpleParameterDefinition {
}
}
@Extension
@Extension @Symbol({"run","runParam"})
public static class DescriptorImpl extends ParameterDescriptor {
@Override
public String getDisplayName() {
......
......@@ -67,6 +67,7 @@ import jenkins.slaves.WorkspaceLocator;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.kohsuke.stapler.DataBoundSetter;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
......@@ -98,7 +99,7 @@ public abstract class Slave extends Node implements Serializable {
/**
* Description of this node.
*/
private final String description;
private String description;
/**
* Path to the root of the workspace from the view point of this node, such as "/hudson", this need not
......@@ -118,7 +119,7 @@ public abstract class Slave extends Node implements Serializable {
/**
* Job allocation strategy.
*/
private Mode mode;
private Mode mode = Mode.NORMAL;
/**
* Agent availablility strategy.
......@@ -162,6 +163,16 @@ public abstract class Slave extends Node implements Serializable {
this(name, nodeDescription, remoteFS, numExecutors, mode, labelString, launcher, retentionStrategy, new ArrayList());
}
public Slave(@Nonnull String name, String remoteFS, ComputerLauncher launcher) throws FormException, IOException {
this.name = name;
this.remoteFS = remoteFS;
this.launcher = launcher;
}
/**
* @deprecated as of 1.XXX
* Use {@link #Slave(String, String, ComputerLauncher)} and set the rest through setters.
*/
public Slave(@Nonnull String name, String nodeDescription, String remoteFS, int numExecutors,
Mode mode, String labelString, ComputerLauncher launcher, RetentionStrategy retentionStrategy, List<? extends NodeProperty<?>> nodeProperties) throws FormException, IOException {
this.name = name;
......@@ -231,6 +242,11 @@ public abstract class Slave extends Node implements Serializable {
this.name = name;
}
@DataBoundSetter
public void setNodeDescription(String value) {
this.description = value;
}
public String getNodeDescription() {
return description;
}
......@@ -239,10 +255,16 @@ public abstract class Slave extends Node implements Serializable {
return numExecutors;
}
@DataBoundSetter
public void setNumExecutors(int n) {
this.numExecutors = n;
}
public Mode getMode() {
return mode;
}
@DataBoundSetter
public void setMode(Mode mode) {
this.mode = mode;
}
......@@ -252,10 +274,16 @@ public abstract class Slave extends Node implements Serializable {
return nodeProperties;
}
@DataBoundSetter
public void setNodeProperties(List<? extends NodeProperty<?>> properties) throws IOException {
nodeProperties.replaceBy(properties);
}
public RetentionStrategy getRetentionStrategy() {
return retentionStrategy == null ? RetentionStrategy.Always.INSTANCE : retentionStrategy;
}
@DataBoundSetter
public void setRetentionStrategy(RetentionStrategy availabilityStrategy) {
this.retentionStrategy = availabilityStrategy;
}
......@@ -265,6 +293,7 @@ public abstract class Slave extends Node implements Serializable {
}
@Override
@DataBoundSetter
public void setLabelString(String labelString) throws IOException {
this.label = Util.fixNull(labelString).trim();
// Compute labels now.
......
......@@ -25,6 +25,7 @@ package hudson.model;
import hudson.Extension;
import net.sf.json.JSONObject;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
......@@ -69,7 +70,7 @@ public class StringParameterDefinition extends SimpleParameterDefinition {
return v;
}
@Extension
@Extension @Symbol({"string","stringParam"})
public static class DescriptorImpl extends ParameterDescriptor {
@Override
public String getDisplayName() {
......
......@@ -25,6 +25,7 @@ package hudson.model;
import hudson.Extension;
import net.sf.json.JSONObject;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
......@@ -37,7 +38,7 @@ public class TextParameterDefinition extends StringParameterDefinition {
super(name, defaultValue, description);
}
@Extension
@Extension @Symbol({"text","textParam"})
public static class DescriptorImpl extends ParameterDescriptor {
@Override
public String getDisplayName() {
......
......@@ -63,6 +63,7 @@ import org.acegisecurity.context.SecurityContext;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.input.CountingInputStream;
import org.apache.commons.io.output.NullOutputStream;
import org.jenkinsci.Symbol;
import org.jvnet.localizer.Localizable;
import org.kohsuke.accmod.restrictions.DoNotUse;
import org.kohsuke.stapler.HttpResponse;
......@@ -898,7 +899,7 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas
/**
* {@link AdministrativeMonitor} that checks if there's Jenkins update.
*/
@Extension
@Extension @Symbol("coreUpdate")
public static final class CoreUpdateMonitor extends AdministrativeMonitor {
public boolean isActivated() {
Data data = getData();
......@@ -1405,7 +1406,52 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas
}
/**
* Enables a required plugin, provides feedback in the update center
*/
public class EnableJob extends InstallationJob {
public EnableJob(UpdateSite site, Authentication auth, @Nonnull Plugin plugin, boolean dynamicLoad) {
super(plugin, site, auth, dynamicLoad);
}
public Plugin getPlugin() {
return plugin;
}
@Override
public void run() {
try {
plugin.getInstalled().enable();
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Failed to enable " + plugin.getDisplayName(), e);
error = e;
}
if (dynamicLoad) {
try {
// remove the existing, disabled inactive plugin to force a new one to load
pm.dynamicLoad(getDestination(), true);
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Failed to dynamically load " + plugin.getDisplayName(), e);
error = e;
requiresRestart = true;
}
} else {
requiresRestart = true;
}
}
}
/**
* A no-op, e.g. this plugin is already installed
*/
public class NoOpJob extends EnableJob {
public NoOpJob(UpdateSite site, Authentication auth, @Nonnull Plugin plugin) {
super(site, auth, plugin, false);
}
}
/**
* Base class for a job that downloads a file from the Jenkins project.
*/
......@@ -1575,6 +1621,15 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas
}
}
/**
* Indicates that the plugin was successfully installed.
*/
public class Skipped extends InstallationStatus {
@Override public boolean isSuccess() {
return true;
}
}
/**
* Indicates that the plugin is waiting for its turn for installation.
*/
......@@ -1619,19 +1674,19 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas
/**
* Represents the state of the installation activity of one plugin.
*/
public final class InstallationJob extends DownloadJob {
public class InstallationJob extends DownloadJob {
/**
* What plugin are we trying to install?
*/
@Exported
public final Plugin plugin;
private final PluginManager pm = Jenkins.getInstance().getPluginManager();
protected final PluginManager pm = Jenkins.getInstance().getPluginManager();
/**
* True to load the plugin into this Jenkins, false to wait until restart.
*/
private final boolean dynamicLoad;
protected final boolean dynamicLoad;
/**
* @deprecated as of 1.442
......@@ -1667,29 +1722,81 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas
@Override
public void _run() throws IOException, InstallationStatus {
super._run();
if (wasInstalled()) {
// Do this first so we can avoid duplicate downloads, too
// check to see if the plugin is already installed at the same version and skip it
LOGGER.info("Skipping duplicate install of: " + plugin.getDisplayName() + "@" + plugin.version);
//throw new Skipped(); // TODO set skipped once we have a status indicator for it
return;
}
try {
super._run();
// if this is a bundled plugin, make sure it won't get overwritten
PluginWrapper pw = plugin.getInstalled();
if (pw!=null && pw.isBundled()) {
SecurityContext oldContext = ACL.impersonate(ACL.SYSTEM);
try {
pw.doPin();
} finally {
SecurityContextHolder.setContext(oldContext);
}
}
// if this is a bundled plugin, make sure it won't get overwritten
PluginWrapper pw = plugin.getInstalled();
if (pw!=null && pw.isBundled()) {
SecurityContext oldContext = ACL.impersonate(ACL.SYSTEM);
try {
pw.doPin();
} finally {
SecurityContextHolder.setContext(oldContext);
if (dynamicLoad) {
try {
pm.dynamicLoad(getDestination());
} catch (RestartRequiredException e) {
throw new SuccessButRequiresRestart(e.message);
} catch (Exception e) {
throw new IOException("Failed to dynamically deploy this plugin",e);
}
} else {
throw new SuccessButRequiresRestart(Messages._UpdateCenter_DownloadButNotActivated());
}
} finally {
synchronized(this) {
// There may be other threads waiting on completion
LOGGER.fine("Install complete for: " + plugin.getDisplayName() + "@" + plugin.version);
// some status other than Installing or Downloading needs to be set here
// {@link #isAlreadyInstalling()}, it will be overwritten by {@link DownloadJob#run()}
status = new Skipped();
notifyAll();
}
}
}
if (dynamicLoad) {
try {
pm.dynamicLoad(getDestination());
} catch (RestartRequiredException e) {
throw new SuccessButRequiresRestart(e.message);
} catch (Exception e) {
throw new IOException("Failed to dynamically deploy this plugin",e);
/**
* Indicates there is another installation job for this plugin
* @since TODO
*/
protected boolean wasInstalled() {
synchronized(UpdateCenter.this) {
for (UpdateCenterJob job : getJobs()) {
if (job == this) {
// oldest entries first, if we reach this instance,
// we need it to continue installing
return false;
}
if (job instanceof InstallationJob) {
InstallationJob ij = (InstallationJob)job;
if (ij.plugin.equals(plugin) && ij.plugin.version.equals(plugin.version)) {
// wait until other install is completed
synchronized(ij) {
if(ij.status instanceof Installing || ij.status instanceof Pending) {
try {
LOGGER.fine("Waiting for other plugin install of: " + plugin.getDisplayName() + "@" + plugin.version);
ij.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
return true;
}
}
}
} else {
throw new SuccessButRequiresRestart(Messages._UpdateCenter_DownloadButNotActivated());
return false;
}
}
......
......@@ -731,6 +731,10 @@ public class UpdateSite {
else if (current.isOlderThan(requiredVersion)) {
deps.add(depPlugin);
}
// JENKINS-34494 - or if the plugin is disabled, this will allow us to enable it
else if (!current.isEnabled()) {
deps.add(depPlugin);
}
}
for(Map.Entry<String,String> e : optionalDependencies.entrySet()) {
......@@ -847,10 +851,22 @@ public class UpdateSite {
for (Plugin dep : getNeededDependencies()) {
UpdateCenter.InstallationJob job = uc.getJob(dep);
if (job == null || job.status instanceof UpdateCenter.DownloadJob.Failure) {
LOGGER.log(Level.WARNING, "Adding dependent install of " + dep.name + " for plugin " + name);
LOGGER.log(Level.INFO, "Adding dependent install of " + dep.name + " for plugin " + name);
dep.deploy(dynamicLoad);
} else {
LOGGER.log(Level.WARNING, "Dependent install of " + dep.name + " for plugin " + name + " already added, skipping");
LOGGER.log(Level.INFO, "Dependent install of " + dep.name + " for plugin " + name + " already added, skipping");
}
}
PluginWrapper pw = getInstalled();
if(pw != null) { // JENKINS-34494 - check for this plugin being disabled
Future<UpdateCenterJob> enableJob = null;
if(!pw.isEnabled()) {
UpdateCenter.EnableJob job = uc.new EnableJob(UpdateSite.this, null, this, dynamicLoad);
job.setCorrelationId(correlationId);
enableJob = uc.addJob(job);
}
if(pw.getVersionNumber().equals(new VersionNumber(version))) {
return enableJob != null ? enableJob : uc.addJob(uc.new NoOpJob(UpdateSite.this, null, this));
}
}
UpdateCenter.InstallationJob job = uc.new InstallationJob(this, UpdateSite.this, Jenkins.getAuthentication(), dynamicLoad);
......
......@@ -51,6 +51,7 @@ import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.acegisecurity.providers.anonymous.AnonymousAuthenticationToken;
import org.acegisecurity.userdetails.UserDetails;
import org.acegisecurity.userdetails.UsernameNotFoundException;
import org.jenkinsci.Symbol;
import org.springframework.dao.DataAccessException;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
......@@ -997,7 +998,7 @@ public class User extends AbstractModelObject implements AccessControlled, Descr
/**
* Resolve user ID from full name
*/
@Extension
@Extension @Symbol("fullName")
public static class FullNameIdResolver extends CanonicalIdResolver {
@Override
......
......@@ -37,13 +37,14 @@ import java.util.logging.Logger;
import javax.annotation.Nonnull;
import jenkins.model.Jenkins;
import jenkins.model.ModifiableTopLevelItemGroup;
import org.jenkinsci.Symbol;
/**
* Clean up old left-over workspaces from agents.
*
* @author Kohsuke Kawaguchi
*/
@Extension
@Extension @Symbol("workspaceCleanup")
public class WorkspaceCleanupThread extends AsyncPeriodicWork {
public WorkspaceCleanupThread() {
super("Workspace clean-up");
......
......@@ -28,6 +28,7 @@ import hudson.remoting.Callable;
import hudson.Extension;
import jenkins.security.MasterToSlaveCallable;
import net.sf.json.JSONObject;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.StaplerRequest;
import java.io.IOException;
......@@ -38,7 +39,7 @@ import java.io.IOException;
* @author Kohsuke Kawaguchi
*/
public class ArchitectureMonitor extends NodeMonitor {
@Extension
@Extension @Symbol("architecture")
public static final class DescriptorImpl extends AbstractAsyncNodeMonitorDescriptor<String> {
@Override
protected Callable<String, IOException> createCallable(Computer c) {
......
......@@ -28,6 +28,9 @@ import hudson.model.Node;
import hudson.remoting.Callable;
import hudson.util.ClockDifference;
import hudson.Extension;
import org.jenkinsci.Symbol;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.StaplerRequest;
import java.io.IOException;
......@@ -46,8 +49,19 @@ public class ClockMonitor extends NodeMonitor {
return DESCRIPTOR.get(c);
}
@Extension
public static final AbstractNodeMonitorDescriptor<ClockDifference> DESCRIPTOR = new AbstractAsyncNodeMonitorDescriptor<ClockDifference>() {
/**
* @deprecated as of 2.0
* Don't use this field, use injection.
*/
@Restricted(NoExternalUse.class)
public static /*almost final*/ AbstractNodeMonitorDescriptor<ClockDifference> DESCRIPTOR;
@Extension @Symbol("clock")
public static class DescriptorImpl extends AbstractAsyncNodeMonitorDescriptor<ClockDifference> {
public DescriptorImpl() {
DESCRIPTOR = this;
}
@Override
protected Callable<ClockDifference,IOException> createCallable(Computer c) {
Node n = c.getNode();
......
......@@ -30,6 +30,7 @@ import hudson.model.Computer;
import jenkins.model.Jenkins;
import jenkins.security.MasterToSlaveCallable;
import net.sf.json.JSONObject;
import org.jenkinsci.Symbol;
import org.jvnet.hudson.MemoryMonitor;
import org.jvnet.hudson.MemoryUsage;
import org.kohsuke.stapler.StaplerRequest;
......@@ -80,8 +81,18 @@ public class SwapSpaceMonitor extends NodeMonitor {
return Jenkins.getInstance().hasPermission(Jenkins.ADMINISTER) ? super.getColumnCaption() : null;
}
@Extension
public static final AbstractNodeMonitorDescriptor<MemoryUsage> DESCRIPTOR = new AbstractAsyncNodeMonitorDescriptor<MemoryUsage>() {
/**
* @deprecated as of 2.0
* use injection
*/
public static /*almost final*/ AbstractNodeMonitorDescriptor<MemoryUsage> DESCRIPTOR;
@Extension @Symbol("swapSpace")
public static class DescriptorImpl extends AbstractAsyncNodeMonitorDescriptor<MemoryUsage> {
public DescriptorImpl() {
DESCRIPTOR = this;
}
@Override
protected MonitorTask createCallable(Computer c) {
return new MonitorTask();
......
......@@ -32,6 +32,7 @@ import hudson.remoting.Callable;
import jenkins.model.Jenkins;
import hudson.node_monitors.DiskSpaceMonitorDescriptor.DiskSpace;
import hudson.remoting.VirtualChannel;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import java.io.File;
......@@ -61,7 +62,18 @@ public class TemporarySpaceMonitor extends AbstractDiskSpaceMonitor {
return Jenkins.getInstance().hasPermission(Jenkins.ADMINISTER) ? super.getColumnCaption() : null;
}
public static final DiskSpaceMonitorDescriptor DESCRIPTOR = new DiskSpaceMonitorDescriptor() {
/**
* @deprecated as of 2.0
* Use injection
*/
public static /*almost final*/ DiskSpaceMonitorDescriptor DESCRIPTOR;
@Extension @Symbol("tmpSpace")
public static class DescriptorImpl extends DiskSpaceMonitorDescriptor {
public DescriptorImpl() {
DESCRIPTOR = this;
}
public String getDisplayName() {
return Messages.TemporarySpaceMonitor_DisplayName();
}
......@@ -76,9 +88,11 @@ public class TemporarySpaceMonitor extends AbstractDiskSpaceMonitor {
return p.asCallableWith(new GetTempSpace());
}
};
}
@Extension
/**
* @deprecated as of 2.0
*/
public static DiskSpaceMonitorDescriptor install() {
return DESCRIPTOR;
}
......
......@@ -39,6 +39,7 @@ import java.io.IOException;
import java.io.File;
import java.io.Serializable;
import org.jenkinsci.Symbol;
import org.jvnet.solaris.libzfs.LibZFS;
import org.jvnet.solaris.libzfs.ZFSFileSystem;
......@@ -111,7 +112,7 @@ public class ZFSProvisioner extends FileSystemProvisioner implements Serializabl
throw new UnsupportedOperationException();
}
@Extension
@Extension @Symbol("zfs")
public static final class DescriptorImpl extends FileSystemProvisionerDescriptor {
public boolean discard(FilePath ws, TaskListener listener) throws IOException, InterruptedException {
// TODO
......
......@@ -32,6 +32,7 @@ import hudson.model.TaskListener;
import java.io.File;
import java.io.IOException;
import net.sf.json.JSONObject;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.StaplerRequest;
/**
......@@ -58,7 +59,7 @@ public class NullSCM extends SCM {
return NullChangeLogParser.INSTANCE;
}
@Extension(ordinal = Integer.MAX_VALUE)
@Extension(ordinal = Integer.MAX_VALUE) @Symbol("none")
public static class DescriptorImpl extends SCMDescriptor<NullSCM> {
public DescriptorImpl() {
super(null);
......
......@@ -6,6 +6,7 @@ import hudson.model.UserProperty;
import hudson.model.UserPropertyDescriptor;
import net.sf.json.JSONObject;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.export.Exported;
......@@ -32,7 +33,7 @@ public class UserSearchProperty extends hudson.model.UserProperty {
}
@Extension
@Extension @Symbol("search")
public static final class DescriptorImpl extends UserPropertyDescriptor {
public String getDisplayName() {
return Messages.UserSearchProperty_DisplayName();
......
......@@ -39,6 +39,7 @@ import jenkins.model.Jenkins;
import net.sf.json.JSONObject;
import org.acegisecurity.Authentication;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.StaplerRequest;
/**
......@@ -231,7 +232,7 @@ public abstract class AuthorizationStrategy extends AbstractDescribableImpl<Auth
}
};
@Extension
@Extension @Symbol("unsecured")
public static final class DescriptorImpl extends Descriptor<AuthorizationStrategy> {
@Override
public String getDisplayName() {
......
......@@ -26,6 +26,7 @@ package hudson.security;
import hudson.Extension;
import hudson.model.Descriptor;
import jenkins.model.Jenkins;
import org.jenkinsci.Symbol;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.DataBoundConstructor;
......@@ -92,7 +93,7 @@ public class FullControlOnceLoggedInAuthorizationStrategy extends AuthorizationS
@Restricted(NoExternalUse.class)
public static Descriptor<AuthorizationStrategy> DESCRIPTOR;
@Extension
@Extension @Symbol("loggedInUsersCanDoAnything")
public static class DescriptorImpl extends Descriptor<AuthorizationStrategy> {
public DescriptorImpl() {
DESCRIPTOR = this;
......
......@@ -45,6 +45,7 @@ import jenkins.model.Jenkins;
import jenkins.util.ServerTcpPort;
import net.sf.json.JSONObject;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
......@@ -55,7 +56,7 @@ import org.kohsuke.stapler.StaplerResponse;
*
* @author Kohsuke Kawaguchi
*/
@Extension(ordinal = Integer.MAX_VALUE - 210)
@Extension(ordinal = Integer.MAX_VALUE - 210) @Symbol("securityConfig")
public class GlobalSecurityConfiguration extends ManagementLink implements Describable<GlobalSecurityConfiguration> {
private static final Logger LOGGER = Logger.getLogger(GlobalSecurityConfiguration.class.getName());
......@@ -167,7 +168,7 @@ public class GlobalSecurityConfiguration extends ManagementLink implements Descr
return Jenkins.getInstance().getDescriptorOrDie(getClass());
}
@Extension
@Extension @Symbol("security")
public static final class DescriptorImpl extends Descriptor<GlobalSecurityConfiguration> {
@Override
public String getDisplayName() {
......
......@@ -52,6 +52,7 @@ import org.acegisecurity.providers.encoding.PasswordEncoder;
import org.acegisecurity.providers.encoding.ShaPasswordEncoder;
import org.acegisecurity.userdetails.UserDetails;
import org.acegisecurity.userdetails.UsernameNotFoundException;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.ForwardToView;
import org.kohsuke.stapler.HttpResponse;
......@@ -560,7 +561,7 @@ public class HudsonPrivateSecurityRealm extends AbstractPasswordBasedSecurityRea
}
}
@Extension
@Extension @Symbol("password")
public static final class DescriptorImpl extends UserPropertyDescriptor {
@Override
public String getDisplayName() {
......@@ -600,7 +601,7 @@ public class HudsonPrivateSecurityRealm extends AbstractPasswordBasedSecurityRea
* Displays "manage users" link in the system config if {@link HudsonPrivateSecurityRealm}
* is in effect.
*/
@Extension
@Extension @Symbol("localUsers")
public static final class ManageUserLinks extends ManagementLink {
public String getIconFileName() {
if(Jenkins.getInstance().getSecurityRealm() instanceof HudsonPrivateSecurityRealm)
......@@ -711,7 +712,7 @@ public class HudsonPrivateSecurityRealm extends AbstractPasswordBasedSecurityRea
private static final String JBCRYPT_HEADER = "#jbcrypt:";
};
@Extension
@Extension @Symbol("local")
public static final class DescriptorImpl extends Descriptor<SecurityRealm> {
public String getDisplayName() {
return Messages.HudsonPrivateSecurityRealm_DisplayName();
......
......@@ -27,6 +27,7 @@ import hudson.Extension;
import hudson.model.Descriptor;
import jenkins.model.Jenkins;
import org.acegisecurity.acls.sid.GrantedAuthoritySid;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import java.util.Collection;
......@@ -54,7 +55,7 @@ public final class LegacyAuthorizationStrategy extends AuthorizationStrategy {
return Collections.singleton("admin");
}
@Extension
@Extension @Symbol("legacy")
public static final class DescriptorImpl extends Descriptor<AuthorizationStrategy> {
public String getDisplayName() {
return Messages.LegacyAuthorizationStrategy_DisplayName();
......
......@@ -26,6 +26,9 @@ package hudson.security;
import org.acegisecurity.AuthenticationManager;
import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationException;
import org.jenkinsci.Symbol;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.springframework.web.context.WebApplicationContext;
import org.kohsuke.stapler.StaplerRequest;
import groovy.lang.Binding;
......@@ -88,8 +91,19 @@ public final class LegacySecurityRealm extends SecurityRealm implements Authenti
return (Filter) context.getBean("legacy");
}
@Extension
public static final Descriptor<SecurityRealm> DESCRIPTOR = new Descriptor<SecurityRealm>() {
/**
* @deprecated as of 2.0
* Don't use this field, use injection.
*/
@Restricted(NoExternalUse.class)
public static /*almost final*/ Descriptor<SecurityRealm> DESCRIPTOR;
@Extension @Symbol("legacy")
public static class DescriptorImpl extends Descriptor<SecurityRealm> {
public DescriptorImpl() {
DESCRIPTOR = this;
}
public SecurityRealm newInstance(StaplerRequest req, JSONObject formData) throws FormException {
return new LegacySecurityRealm();
}
......
......@@ -12,6 +12,7 @@ import jenkins.model.Jenkins;
import org.acegisecurity.Authentication;
import org.acegisecurity.GrantedAuthority;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.export.Exported;
import org.kohsuke.stapler.export.ExportedBean;
......@@ -21,7 +22,7 @@ import org.kohsuke.stapler.export.ExportedBean;
* @author Ryan Campbell
*
*/
@Extension
@Extension @Symbol("whoAmI")
@ExportedBean
public class WhoAmI implements UnprotectedRootAction {
......
......@@ -23,6 +23,7 @@ import jenkins.security.HexStringConfidentialKey;
import net.sf.json.JSONObject;
import org.acegisecurity.Authentication;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
......@@ -118,7 +119,7 @@ public class DefaultCrumbIssuer extends CrumbIssuer {
return defaultAddress;
}
@Extension
@Extension @Symbol("standard")
public static final class DescriptorImpl extends CrumbIssuerDescriptor<DefaultCrumbIssuer> implements ModelObject {
private final static HexStringConfidentialKey CRUMB_SALT = new HexStringConfidentialKey(Jenkins.class,"crumbSalt",16);
......
......@@ -28,6 +28,7 @@ import jenkins.model.GlobalConfiguration;
import jenkins.model.GlobalConfigurationCategory;
import jenkins.model.Jenkins;
import net.sf.json.JSONObject;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.StaplerRequest;
/**
......@@ -35,7 +36,7 @@ import org.kohsuke.stapler.StaplerRequest;
*
* @author Kohsuke Kawaguchi
*/
@Extension(ordinal=195) // immediately after the security setting
@Extension(ordinal=195) @Symbol("crumb") // immediately after the security setting
public class GlobalCrumbIssuerConfiguration extends GlobalConfiguration {
@Override
public GlobalConfigurationCategory getCategory() {
......
......@@ -26,6 +26,7 @@ package hudson.slaves;
import hudson.EnvVars;
import hudson.Extension;
import hudson.model.TaskListener;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import java.io.IOException;
......@@ -48,7 +49,7 @@ public class CommandConnector extends ComputerConnector {
return new CommandLauncher(command,new EnvVars("SLAVE",host));
}
@Extension
@Extension @Symbol("command")
public static class DescriptorImpl extends ComputerConnectorDescriptor {
@Override
public String getDisplayName() {
......
......@@ -42,6 +42,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
......@@ -182,7 +183,7 @@ public class CommandLauncher extends ComputerLauncher {
private static final Logger LOGGER = Logger.getLogger(CommandLauncher.class.getName());
@Extension
@Extension @Symbol("command")
public static class DescriptorImpl extends Descriptor<ComputerLauncher> {
public String getDisplayName() {
return Messages.CommandLauncher_displayName();
......
......@@ -32,6 +32,7 @@ import jenkins.model.Jenkins;
import hudson.model.Node;
import hudson.model.PeriodicWork;
import hudson.Extension;
import org.jenkinsci.Symbol;
/**
* Periodically checks the agents and try to reconnect dead agents.
......@@ -39,7 +40,7 @@ import hudson.Extension;
* @author Kohsuke Kawaguchi
* @author Stephen Connolly
*/
@Extension
@Extension @Symbol("computerRetention")
public class ComputerRetentionWork extends PeriodicWork {
/**
......
......@@ -32,6 +32,7 @@ import hudson.remoting.VirtualChannel;
import hudson.remoting.Channel;
import hudson.Extension;
import jenkins.security.SlaveToMasterCallable;
import org.jenkinsci.Symbol;
import java.io.IOException;
import java.util.logging.Logger;
......@@ -46,7 +47,7 @@ import java.util.logging.Logger;
* @author Kohsuke Kawaguchi
* @since 1.325
*/
@Extension
@Extension @Symbol("connectionActivityMonitor")
public class ConnectionActivityMonitor extends AsyncPeriodicWork {
public ConnectionActivityMonitor() {
super("Connection Activity monitoring to agents");
......
......@@ -31,8 +31,11 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import javax.annotation.Nonnull;
/**
* Default {@link Slave} implementation for computers that do not belong to a higher level structure,
* like grid or cloud.
......@@ -49,12 +52,21 @@ public final class DumbSlave extends Slave {
this(name, nodeDescription, remoteFS, numExecutors, mode, labelString, launcher, retentionStrategy, new ArrayList());
}
@DataBoundConstructor
/**
* @deprecated as of 1.XXX.
* Use {@link #DumbSlave(String, String, ComputerLauncher)} and configure the rest through setters.
*/
public DumbSlave(String name, String nodeDescription, String remoteFS, String numExecutors, Mode mode, String labelString, ComputerLauncher launcher, RetentionStrategy retentionStrategy, List<? extends NodeProperty<?>> nodeProperties) throws IOException, FormException {
super(name, nodeDescription, remoteFS, numExecutors, mode, labelString, launcher, retentionStrategy, nodeProperties);
}
@Extension
@DataBoundConstructor
public DumbSlave(@Nonnull String name, String remoteFS, ComputerLauncher launcher) throws FormException, IOException {
super(name, remoteFS, launcher);
}
@Extension @Symbol({"dumb",
"slave"/*because this is in effect the canonical slave type*/})
public static final class DescriptorImpl extends SlaveDescriptor {
public String getDisplayName() {
return Messages.DumbSlave_displayName();
......
......@@ -32,6 +32,7 @@ import hudson.model.ComputerSet;
import hudson.model.Environment;
import hudson.model.Node;
import hudson.model.TaskListener;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.Stapler;
......@@ -75,7 +76,7 @@ public class EnvironmentVariablesNodeProperty extends NodeProperty<Node> {
env.putAll(envVars);
}
@Extension
@Extension @Symbol("envVars")
public static class DescriptorImpl extends NodePropertyDescriptor {
@Override
......
......@@ -27,6 +27,8 @@ import hudson.model.Descriptor;
import hudson.model.TaskListener;
import hudson.Util;
import hudson.Extension;
import jenkins.model.Jenkins;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
/**
......@@ -75,8 +77,18 @@ public class JNLPLauncher extends ComputerLauncher {
// do nothing as we cannot self start
}
@Extension
public static final Descriptor<ComputerLauncher> DESCRIPTOR = new Descriptor<ComputerLauncher>() {
/**
* @deprecated as of 1.XXX
* Use {@link Jenkins#getDescriptor(Class)}
*/
public static /*almost final*/ Descriptor<ComputerLauncher> DESCRIPTOR;
@Extension @Symbol("jnlp")
public static class DescriptorImpl extends Descriptor<ComputerLauncher> {
public DescriptorImpl() {
DESCRIPTOR = this;
}
public String getDisplayName() {
return Messages.JNLPLauncher_displayName();
}
......
......@@ -30,6 +30,7 @@ import jenkins.model.Jenkins;
import static hudson.model.LoadStatistics.DECAY;
import hudson.model.MultiStageTimeSeries.TimeScale;
import hudson.Extension;
import org.jenkinsci.Symbol;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.GuardedBy;
......@@ -598,7 +599,7 @@ public class NodeProvisioner {
*
* @since 1.588
*/
@Extension
@Extension @Symbol("standard")
public static class StandardStrategyImpl extends Strategy {
/** {@inheritDoc} */
......
......@@ -32,6 +32,7 @@ import hudson.util.DescriptorList;
import java.util.Collections;
import java.util.HashMap;
import jenkins.model.Jenkins;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import javax.annotation.concurrent.GuardedBy;
......@@ -164,7 +165,7 @@ public abstract class RetentionStrategy<T extends Computer> extends AbstractDesc
return 1;
}
@Extension(ordinal=100)
@Extension(ordinal=100) @Symbol("always")
public static class DescriptorImpl extends Descriptor<RetentionStrategy<?>> {
public String getDisplayName() {
return Messages.RetentionStrategy_Always_displayName();
......@@ -276,7 +277,7 @@ public abstract class RetentionStrategy<T extends Computer> extends AbstractDesc
return 1;
}
@Extension
@Extension @Symbol("demand")
public static class DescriptorImpl extends Descriptor<RetentionStrategy<?>> {
@Override
public String getDisplayName() {
......
......@@ -31,6 +31,7 @@ import hudson.model.Descriptor;
import hudson.model.Queue;
import hudson.scheduler.CronTabList;
import hudson.util.FormValidation;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
......@@ -242,7 +243,7 @@ public class SimpleScheduledRetentionStrategy extends RetentionStrategy<SlaveCom
return (lastStart < now && lastStop > now) || (nextStart < now && nextStop > now);
}
@Extension
@Extension @Symbol("schedule")
public static class DescriptorImpl extends Descriptor<RetentionStrategy<?>> {
public String getDisplayName() {
return Messages.SimpleScheduledRetentionStrategy_displayName();
......
......@@ -38,6 +38,7 @@ import hudson.util.FormValidation;
import java.io.File;
import org.apache.tools.ant.types.FileSet;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.AncestorInPath;
......@@ -306,7 +307,7 @@ public class ArtifactArchiver extends Recorder implements SimpleBuildStep {
@Deprecated
public static volatile DescriptorImpl DESCRIPTOR;
@Extension
@Extension @Symbol("archiveArtifacts")
public static class DescriptorImpl extends BuildStepDescriptor<Publisher> {
public DescriptorImpl() {
DESCRIPTOR = this; // backward compatibility
......
......@@ -28,6 +28,7 @@ import hudson.Extension;
import hudson.model.AbstractProject;
import hudson.util.LineEndingConversion;
import net.sf.json.JSONObject;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
import java.io.ObjectStreamException;
......@@ -59,7 +60,7 @@ public class BatchFile extends CommandInterpreter {
return new BatchFile(command);
}
@Extension
@Extension @Symbol("batchFile")
public static final class DescriptorImpl extends BuildStepDescriptor<Builder> {
@Override
public String getHelpFile() {
......
......@@ -68,6 +68,7 @@ import org.acegisecurity.Authentication;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.AncestorInPath;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
......@@ -331,7 +332,7 @@ public class BuildTrigger extends Recorder implements DependencyDeclarer {
return this;
}
@Extension
@Extension @Symbol("downstream")
public static class DescriptorImpl extends BuildStepDescriptor<Publisher> {
public String getDisplayName() {
return Messages.BuildTrigger_DisplayName();
......
......@@ -52,6 +52,7 @@ import net.sf.json.JSONObject;
import org.acegisecurity.AccessDeniedException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.types.FileSet;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.AncestorInPath;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
......@@ -248,7 +249,7 @@ public class Fingerprinter extends Recorder implements Serializable, DependencyD
}
}
@Extension
@Extension @Symbol("fingerprint")
public static class DescriptorImpl extends BuildStepDescriptor<Publisher> {
public String getDisplayName() {
return Messages.Fingerprinter_DisplayName();
......
......@@ -29,6 +29,7 @@ import hudson.model.Job;
import hudson.model.Run;
import jenkins.model.BuildDiscarder;
import jenkins.model.BuildDiscarderDescriptor;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import java.io.IOException;
......@@ -252,7 +253,7 @@ public class LogRotator extends BuildDiscarder {
return String.valueOf(i);
}
@Extension
@Extension @Symbol("logRotator")
public static final class LRDescriptor extends BuildDiscarderDescriptor {
public String getDisplayName() {
return "Log Rotation";
......
......@@ -62,6 +62,7 @@ import jenkins.security.MasterToSlaveCallable;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
......@@ -386,7 +387,7 @@ public class Maven extends Builder {
@Deprecated
public static DescriptorImpl DESCRIPTOR;
@Extension
@Extension @Symbol("maven")
public static final class DescriptorImpl extends BuildStepDescriptor<Builder> {
@CopyOnWrite
private volatile MavenInstallation[] installations = new MavenInstallation[0];
......@@ -620,7 +621,7 @@ public class Maven extends Builder {
return new MavenInstallation(getName(), translateFor(node, log), getProperties().toList());
}
@Extension
@Extension @Symbol("maven")
public static class DescriptorImpl extends ToolDescriptor<MavenInstallation> {
@Override
public String getDisplayName() {
......@@ -678,7 +679,7 @@ public class Maven extends Builder {
super(id);
}
@Extension
@Extension @Symbol("maven")
public static final class DescriptorImpl extends DownloadFromUrlInstaller.DescriptorImpl<MavenInstaller> {
public String getDisplayName() {
return Messages.InstallFromApache();
......
......@@ -35,6 +35,7 @@ import java.io.ObjectStreamException;
import hudson.util.LineEndingConversion;
import jenkins.security.MasterToSlaveCallable;
import net.sf.json.JSONObject;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.QueryParameter;
......@@ -102,7 +103,7 @@ public class Shell extends CommandInterpreter {
return new Shell(command);
}
@Extension
@Extension @Symbol("shell")
public static class DescriptorImpl extends BuildStepDescriptor<Builder> {
/**
* Shell executable, or null to default.
......
......@@ -28,6 +28,7 @@ import hudson.MarkupText;
import hudson.console.ConsoleAnnotationDescriptor;
import hudson.console.ConsoleAnnotator;
import hudson.console.ConsoleNote;
import org.jenkinsci.Symbol;
import java.util.regex.Pattern;
......@@ -57,7 +58,7 @@ public class Maven3MojoNote extends ConsoleNote {
return null;
}
@Extension
@Extension @Symbol("maven3Mojos")
public static final class DescriptorImpl extends ConsoleAnnotationDescriptor {
public String getDisplayName() {
return "Maven 3 Mojos";
......
......@@ -28,6 +28,7 @@ import hudson.MarkupText;
import hudson.console.ConsoleAnnotationDescriptor;
import hudson.console.ConsoleAnnotator;
import hudson.console.ConsoleNote;
import org.jenkinsci.Symbol;
import java.util.regex.Pattern;
......@@ -44,7 +45,7 @@ public class MavenErrorNote extends ConsoleNote {
return null;
}
@Extension
@Extension @Symbol("mavenErrors")
public static final class DescriptorImpl extends ConsoleAnnotationDescriptor {
public String getDisplayName() {
return "Maven Errors";
......
......@@ -28,6 +28,7 @@ import hudson.MarkupText;
import hudson.console.ConsoleAnnotationDescriptor;
import hudson.console.ConsoleAnnotator;
import hudson.console.ConsoleNote;
import org.jenkinsci.Symbol;
import java.util.regex.Pattern;
......@@ -49,7 +50,7 @@ public class MavenMojoNote extends ConsoleNote {
return null;
}
@Extension
@Extension @Symbol("mavenMojos")
public static final class DescriptorImpl extends ConsoleAnnotationDescriptor {
public String getDisplayName() {
return "Maven Mojos";
......
......@@ -28,6 +28,7 @@ import hudson.MarkupText;
import hudson.console.ConsoleAnnotationDescriptor;
import hudson.console.ConsoleAnnotator;
import hudson.console.ConsoleNote;
import org.jenkinsci.Symbol;
import java.util.regex.Pattern;
......@@ -46,7 +47,7 @@ public class MavenWarningNote extends ConsoleNote {
return null;
}
@Extension
@Extension @Symbol("mavenWarnings")
public static final class DescriptorImpl extends ConsoleAnnotationDescriptor {
public String getDisplayName() {
return "Maven Warnings";
......
......@@ -27,6 +27,7 @@ package hudson.tools;
import hudson.Extension;
import hudson.FilePath;
import hudson.util.LineEndingConversion;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import java.io.ObjectStreamException;
......@@ -57,7 +58,7 @@ public class BatchCommandInstaller extends AbstractCommandInstaller {
return new BatchCommandInstaller(getLabel(), getCommand(), getToolHome());
}
@Extension
@Extension @Symbol("batchFile")
public static class DescriptorImpl extends Descriptor<BatchCommandInstaller> {
@Override
......
......@@ -27,6 +27,7 @@ package hudson.tools;
import hudson.Extension;
import hudson.FilePath;
import hudson.util.LineEndingConversion;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import java.io.ObjectStreamException;
......@@ -56,7 +57,7 @@ public class CommandInstaller extends AbstractCommandInstaller {
return new CommandInstaller(getLabel(), getCommand(), getToolHome());
}
@Extension
@Extension @Symbol("command")
public static class DescriptorImpl extends Descriptor<CommandInstaller> {
@Override
......
......@@ -27,6 +27,7 @@ import hudson.Extension;
import hudson.util.DescribableList;
import hudson.model.Descriptor;
import hudson.model.Saveable;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import java.util.List;
......@@ -61,7 +62,7 @@ public class InstallSourceProperty extends ToolProperty<ToolInstallation> {
return ToolInstallation.class;
}
@Extension
@Extension @Symbol("installSource")
public static class DescriptorImpl extends ToolPropertyDescriptor {
public String getDisplayName() {
return Messages.InstallSourceProperty_DescriptorImpl_displayName();
......
......@@ -52,6 +52,7 @@ import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.io.IOUtils;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.QueryParameter;
......@@ -740,7 +741,7 @@ public class JDKInstaller extends ToolInstaller {
return (DescriptorImpl)super.getDescriptor();
}
@Extension
@Extension @Symbol("jdkInstaller")
public static final class DescriptorImpl extends ToolInstallerDescriptor<JDKInstaller> {
private String username;
private Secret password;
......@@ -804,7 +805,7 @@ public class JDKInstaller extends ToolInstaller {
/**
* JDK list.
*/
@Extension
@Extension @Symbol("jdk")
public static final class JDKList extends Downloadable {
public JDKList() {
super(JDKInstaller.class);
......
......@@ -35,6 +35,7 @@ import hudson.slaves.NodeSpecific;
import java.io.IOException;
import java.util.ArrayList;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import java.util.Arrays;
......@@ -115,7 +116,7 @@ public class ToolLocationNodeProperty extends NodeProperty<Node> {
return installation.getHome();
}
@Extension
@Extension @Symbol("toolLocation")
public static class DescriptorImpl extends NodePropertyDescriptor {
public String getDisplayName() {
......
......@@ -41,6 +41,8 @@ import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
......@@ -86,7 +88,7 @@ public class ZipExtractionInstaller extends ToolInstaller {
}
}
@Extension
@Extension @Symbol("zip")
public static class DescriptorImpl extends ToolInstallerDescriptor<ZipExtractionInstaller> {
public String getDisplayName() {
......
......@@ -48,6 +48,7 @@ import hudson.util.StreamTaskListener;
import hudson.util.TimeUnit2;
import org.apache.commons.io.FileUtils;
import org.apache.commons.jelly.XMLOutput;
import org.jenkinsci.Symbol;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.DoNotUse;
import org.kohsuke.stapler.StaplerRequest;
......@@ -176,7 +177,7 @@ public class SCMTrigger extends Trigger<Item> {
return new File(job.getRootDir(),"scm-polling.log");
}
@Extension
@Extension @Symbol("scm")
public static class DescriptorImpl extends TriggerDescriptor {
private static ThreadFactory threadFactory() {
......
......@@ -38,6 +38,7 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.AncestorInPath;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
......@@ -65,7 +66,7 @@ public class TimerTrigger extends Trigger<BuildableItem> {
job.scheduleBuild(0, new TimerTriggerCause());
}
@Extension
@Extension @Symbol("cron")
public static class DescriptorImpl extends TriggerDescriptor {
public boolean isApplicable(Item item) {
return item instanceof BuildableItem;
......
......@@ -63,6 +63,7 @@ import javax.annotation.Nonnull;
import edu.umd.cs.findbugs.annotations.SuppressWarnings;
import hudson.model.Items;
import jenkins.model.ParameterizedJobMixIn;
import org.jenkinsci.Symbol;
/**
* Triggers a {@link Build}.
......@@ -197,7 +198,7 @@ public abstract class Trigger<J extends Item> implements Describable<Trigger<?>>
/**
* Runs every minute to check {@link TimerTrigger} and schedules build.
*/
@Extension
@Extension @Symbol("cron")
public static class Cron extends PeriodicWork {
private final Calendar cal = new GregorianCalendar();
......
......@@ -24,6 +24,7 @@
package hudson.views;
import hudson.Extension;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
public class BuildButtonColumn extends ListViewColumn {
......@@ -31,7 +32,7 @@ public class BuildButtonColumn extends ListViewColumn {
public BuildButtonColumn() {
}
@Extension(ordinal=DEFAULT_COLUMNS_ORDINAL_ACTIONS_START-1)
@Extension(ordinal=DEFAULT_COLUMNS_ORDINAL_ACTIONS_START-1) @Symbol("buildButton")
public static class DescriptorImpl extends ListViewColumnDescriptor {
@Override
public String getDisplayName() {
......
......@@ -24,6 +24,7 @@
package hudson.views;
import hudson.Extension;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
/**
......@@ -38,7 +39,7 @@ public class DefaultMyViewsTabBar extends MyViewsTabBar {
public DefaultMyViewsTabBar() {
}
@Extension
@Extension @Symbol("standard")
public static class DescriptorImpl extends MyViewsTabBarDescriptor {
@Override
public String getDisplayName() {
......
......@@ -24,6 +24,7 @@
package hudson.views;
import hudson.Extension;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
/**
......@@ -38,7 +39,7 @@ public class DefaultViewsTabBar extends ViewsTabBar {
public DefaultViewsTabBar() {
}
@Extension
@Extension @Symbol("standard")
public static class DescriptorImpl extends ViewsTabBarDescriptor {
@Override
public String getDisplayName() {
......
......@@ -27,6 +27,7 @@ import hudson.Extension;
import jenkins.model.GlobalConfiguration;
import jenkins.model.Jenkins;
import net.sf.json.JSONObject;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.StaplerRequest;
/**
......@@ -34,7 +35,7 @@ import org.kohsuke.stapler.StaplerRequest;
*
* @author Kohsuke Kawaguchi
*/
@Extension(ordinal=300)
@Extension(ordinal=300) @Symbol("defaultView")
public class GlobalDefaultViewConfiguration extends GlobalConfiguration {
@Override
public boolean configure(StaplerRequest req, JSONObject json) throws FormException {
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册