diff --git a/changelog.html b/changelog.html index c926905eb5..c121a698e2 100644 --- a/changelog.html +++ b/changelog.html @@ -60,7 +60,9 @@ Upcoming changes diff --git a/core/src/main/java/hudson/PluginManager.java b/core/src/main/java/hudson/PluginManager.java index b4b843fc07..c275fa0e5c 100644 --- a/core/src/main/java/hudson/PluginManager.java +++ b/core/src/main/java/hudson/PluginManager.java @@ -455,6 +455,20 @@ public abstract class PluginManager extends AbstractModelObject { return result; } + /** + * Return the {@link PluginWrapper} that loaded the given class 'c'. + * + * @since 1.402. + */ + public PluginWrapper whichPlugin(Class c) { + ClassLoader cl = c.getClassLoader(); + for (PluginWrapper p : activePlugins) { + if (p.classLoader==cl) + return p; + } + return null; + } + /** * Orderly terminates all the plugins. */ diff --git a/core/src/main/java/hudson/diagnosis/NullIdDescriptorMonitor.java b/core/src/main/java/hudson/diagnosis/NullIdDescriptorMonitor.java new file mode 100644 index 0000000000..b54355f620 --- /dev/null +++ b/core/src/main/java/hudson/diagnosis/NullIdDescriptorMonitor.java @@ -0,0 +1,80 @@ +/* + * The MIT License + * + * Copyright (c) 2011, CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package hudson.diagnosis; + +import hudson.Extension; +import hudson.PluginWrapper; +import hudson.init.Initializer; +import hudson.model.AdministrativeMonitor; +import hudson.model.Descriptor; +import hudson.model.Hudson; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.logging.Logger; + +import static hudson.init.InitMilestone.EXTENSIONS_AUGMENTED; + +/** + * Some old descriptors apparently has the getId() method that's used in different ways + * and that's causing errors like JENKINS-8866, so detect and report that. + * + * @author Kohsuke Kawaguchi + * @since 1.402 + */ +@Extension +public class NullIdDescriptorMonitor extends AdministrativeMonitor { + + private final List problems = new ArrayList(); + + @Override + public boolean isActivated() { + return !problems.isEmpty(); + } + + public List getProblems() { + return Collections.unmodifiableList(problems); + } + + private void verify() { + Hudson h = Hudson.getInstance(); + for (Descriptor d : h.getExtensionList(Descriptor.class)) { + if (d.getId()==null) { + PluginWrapper p = h.getPluginManager().whichPlugin(d.getClass()); + LOGGER.severe(MessageFormat.format("Descriptor {0} from plugin {1} with display name {2} has null ID", + d, p==null?"???":p.getLongName(), d.getDisplayName())); + problems.add(d); + } + } + } + + @Initializer(after=EXTENSIONS_AUGMENTED) + public static void verifyId() { + AdministrativeMonitor.all().get(NullIdDescriptorMonitor.class).verify(); + } + + private static final Logger LOGGER = Logger.getLogger(NullIdDescriptorMonitor.class.getName()); +} diff --git a/core/src/main/java/hudson/model/Descriptor.java b/core/src/main/java/hudson/model/Descriptor.java index 5ad77d0862..183ba785a0 100644 --- a/core/src/main/java/hudson/model/Descriptor.java +++ b/core/src/main/java/hudson/model/Descriptor.java @@ -30,6 +30,8 @@ import hudson.BulkChange; import hudson.Util; import static hudson.Functions.jsStringEscape; import hudson.diagnosis.OldDataMonitor; +import hudson.init.InitMilestone; +import hudson.init.Initializer; import hudson.model.listeners.SaveableListener; import hudson.util.ReflectionUtils; import hudson.util.ReflectionUtils.Parameter; @@ -41,12 +43,14 @@ import org.springframework.util.StringUtils; import org.jvnet.tiger_types.Types; import org.apache.commons.io.IOUtils; +import static hudson.init.InitMilestone.EXTENSIONS_AUGMENTED; import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND; import javax.servlet.ServletException; import javax.servlet.RequestDispatcher; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; diff --git a/core/src/main/java/hudson/model/Hudson.java b/core/src/main/java/hudson/model/Hudson.java index 3975a337bf..54eb95f5a9 100644 --- a/core/src/main/java/hudson/model/Hudson.java +++ b/core/src/main/java/hudson/model/Hudson.java @@ -1682,7 +1682,7 @@ public final class Hudson extends Node implements ItemGroup, Stapl public static final DescriptorImpl INSTANCE = new DescriptorImpl(); public String getDisplayName() { - throw new UnsupportedOperationException(); + return ""; } @Override diff --git a/core/src/main/resources/hudson/diagnosis/NullIdDescriptorMonitor/message.jelly b/core/src/main/resources/hudson/diagnosis/NullIdDescriptorMonitor/message.jelly new file mode 100644 index 0000000000..3717859576 --- /dev/null +++ b/core/src/main/resources/hudson/diagnosis/NullIdDescriptorMonitor/message.jelly @@ -0,0 +1,36 @@ + + + +
+ ${%blurb} +
    + +
  • + ${%problem(d, d.displayName, app.pluginManager.whichPlugin(d.getClass()))} +
  • +
    +
+
+
diff --git a/core/src/main/resources/hudson/diagnosis/NullIdDescriptorMonitor/message.properties b/core/src/main/resources/hudson/diagnosis/NullIdDescriptorMonitor/message.properties new file mode 100644 index 0000000000..399938b97a --- /dev/null +++ b/core/src/main/resources/hudson/diagnosis/NullIdDescriptorMonitor/message.properties @@ -0,0 +1,3 @@ +blurb=The following extensions have no ID value and therefore likely cause a problem. Please upgrade these plugins if they are not the latest, \ + and if they are the latest, please file a bug so that we can fix them. +problem=Descriptor {0} from plugin {2} with display name {1} \ No newline at end of file