Esempio n. 1
0
 /**
  * Get the plugin instances that extend a specific class, use to find similar plugins. Note:
  * beware the classloader fun.
  *
  * @param pluginSuperclass The class that your plugin is derived from.
  * @return The list of plugins implementing the specified class.
  */
 public List<PluginWrapper> getPlugins(Class<? extends Plugin> pluginSuperclass) {
   List<PluginWrapper> result = new ArrayList<PluginWrapper>();
   for (PluginWrapper p : plugins) {
     if (pluginSuperclass.isInstance(p.getPlugin())) result.add(p);
   }
   return Collections.unmodifiableList(result);
 }
Esempio n. 2
0
 /** Orderly terminates all the plugins. */
 public void stop() {
   for (PluginWrapper p : activePlugins) {
     p.stop();
     p.releaseClassLoader();
   }
   activePlugins.clear();
   // Work around a bug in commons-logging.
   // See http://www.szegedi.org/articles/memleak.html
   LogFactory.release(uberClassLoader);
 }
Esempio n. 3
0
 public boolean isActivated() {
   if (pluginsWithCycle == null) {
     pluginsWithCycle = new ArrayList<String>();
     for (PluginWrapper p : Jenkins.getInstance().getPluginManager().getPlugins()) {
       if (p.hasCycleDependency()) {
         pluginsWithCycle.add(p.getShortName());
         isActive = true;
       }
     }
   }
   return isActive;
 }
Esempio n. 4
0
  /** TODO: revisit where/how to expose this. This is an experiment. */
  public void dynamicLoad(File arc)
      throws IOException, InterruptedException, RestartRequiredException {
    LOGGER.info("Attempting to dynamic load " + arc);
    final PluginWrapper p = strategy.createPluginWrapper(arc);
    String sn = p.getShortName();
    if (getPlugin(sn) != null)
      throw new RestartRequiredException(
          Messages._PluginManager_PluginIsAlreadyInstalled_RestartRequired(sn));

    if (p.supportsDynamicLoad() == YesNoMaybe.NO)
      throw new RestartRequiredException(
          Messages._PluginManager_PluginDoesntSupportDynamicLoad_RestartRequired(sn));

    // there's no need to do cyclic dependency check, because we are deploying one at a time,
    // so existing plugins can't be depending on this newly deployed one.

    plugins.add(p);
    activePlugins.add(p);

    try {
      p.resolvePluginDependencies();
      strategy.load(p);

      Jenkins.getInstance().refreshExtensions();

      p.getPlugin().postInitialize();
    } catch (Exception e) {
      failedPlugins.add(new FailedPlugin(sn, e));
      activePlugins.remove(p);
      plugins.remove(p);
      throw new IOException("Failed to install " + sn + " plugin", e);
    }

    // run initializers in the added plugin
    Reactor r = new Reactor(InitMilestone.ordering());
    r.addAll(
        new InitializerFinder(p.classLoader) {
          @Override
          protected boolean filter(Method e) {
            return e.getDeclaringClass().getClassLoader() != p.classLoader || super.filter(e);
          }
        }.discoverTasks(r));
    try {
      new InitReactorRunner().run(r);
    } catch (ReactorException e) {
      throw new IOException("Failed to initialize " + sn + " plugin", e);
    }
    LOGGER.info("Plugin " + sn + " dynamically installed");
  }
Esempio n. 5
0
  /**
   * Like {@link #doInstallNecessaryPlugins(StaplerRequest)} but only checks if everything is
   * installed or if some plugins need updates or installation.
   *
   * <p>This method runs without side-effect. I'm still requiring the ADMINISTER permission since
   * XML file can contain various external references and we don't configure parsers properly
   * against that.
   *
   * @since 1.483
   */
  @RequirePOST
  public JSONArray doPrevalidateConfig(StaplerRequest req) throws IOException {
    Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER);

    JSONArray response = new JSONArray();

    for (Map.Entry<String, VersionNumber> p :
        parseRequestedPlugins(req.getInputStream()).entrySet()) {
      PluginWrapper pw = getPlugin(p.getKey());
      JSONObject j =
          new JSONObject()
              .accumulate("name", p.getKey())
              .accumulate("version", p.getValue().toString());
      if (pw == null) { // install new
        response.add(j.accumulate("mode", "missing"));
      } else if (pw.isOlderThan(p.getValue())) { // upgrade
        response.add(j.accumulate("mode", "old"));
      } // else already good
    }

    return response;
  }
Esempio n. 6
0
 /**
  * Prepares plugins for some expected XML configuration. If the configuration (typically a job’s
  * {@code config.xml}) needs some plugins to be installed (or updated), those jobs will be
  * triggered. Plugins are dynamically loaded whenever possible. Requires {@link
  * Jenkins#ADMINISTER}.
  *
  * @param configXml configuration that might be uploaded
  * @return an empty list if all is well, else a list of submitted jobs which must be completed
  *     before this configuration can be fully read
  * @throws IOException if loading or parsing the configuration failed
  * @see ItemGroupMixIn#createProjectFromXML
  * @see AbstractItem#updateByXml(javax.xml.transform.Source)
  * @see XStream2
  * @see hudson.model.UpdateSite.Plugin#deploy(boolean)
  * @see PluginWrapper#supportsDynamicLoad
  * @see hudson.model.UpdateCenter.DownloadJob.SuccessButRequiresRestart
  * @since 1.483
  */
 public List<Future<UpdateCenter.UpdateCenterJob>> prevalidateConfig(InputStream configXml)
     throws IOException {
   Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER);
   List<Future<UpdateCenter.UpdateCenterJob>> jobs =
       new ArrayList<Future<UpdateCenter.UpdateCenterJob>>();
   UpdateCenter uc = Jenkins.getInstance().getUpdateCenter();
   // TODO call uc.updateAllSites() when available? perhaps not, since we should not block on
   // network here
   for (Map.Entry<String, VersionNumber> requestedPlugin :
       parseRequestedPlugins(configXml).entrySet()) {
     PluginWrapper pw = getPlugin(requestedPlugin.getKey());
     if (pw == null) { // install new
       UpdateSite.Plugin toInstall = uc.getPlugin(requestedPlugin.getKey());
       if (toInstall == null) {
         LOGGER.log(WARNING, "No such plugin {0} to install", requestedPlugin.getKey());
         continue;
       }
       if (new VersionNumber(toInstall.version).compareTo(requestedPlugin.getValue()) < 0) {
         LOGGER.log(
             WARNING,
             "{0} can only be satisfied in @{1}",
             new Object[] {requestedPlugin, toInstall.version});
       }
       if (toInstall.isForNewerHudson()) {
         LOGGER.log(
             WARNING,
             "{0}@{1} was built for a newer Jenkins",
             new Object[] {toInstall.name, toInstall.version});
       }
       jobs.add(toInstall.deploy(true));
     } else if (pw.isOlderThan(requestedPlugin.getValue())) { // upgrade
       UpdateSite.Plugin toInstall = uc.getPlugin(requestedPlugin.getKey());
       if (toInstall == null) {
         LOGGER.log(WARNING, "No such plugin {0} to upgrade", requestedPlugin.getKey());
         continue;
       }
       if (!pw.isOlderThan(new VersionNumber(toInstall.version))) {
         LOGGER.log(
             WARNING,
             "{0}@{1} is no newer than what we already have",
             new Object[] {toInstall.name, toInstall.version});
         continue;
       }
       if (new VersionNumber(toInstall.version).compareTo(requestedPlugin.getValue()) < 0) {
         LOGGER.log(
             WARNING,
             "{0} can only be satisfied in @{1}",
             new Object[] {requestedPlugin, toInstall.version});
       }
       if (toInstall.isForNewerHudson()) {
         LOGGER.log(
             WARNING,
             "{0}@{1} was built for a newer Jenkins",
             new Object[] {toInstall.name, toInstall.version});
       }
       if (!toInstall.isCompatibleWithInstalledVersion()) {
         LOGGER.log(
             WARNING,
             "{0}@{1} is incompatible with the installed @{2}",
             new Object[] {toInstall.name, toInstall.version, pw.getVersion()});
       }
       jobs.add(
           toInstall.deploy(
               true)); // dynamicLoad=true => sure to throw RestartRequiredException, but at least
                       // message is nicer
     } // else already good
   }
   return jobs;
 }
Esempio n. 7
0
 /**
  * Get the plugin instance that implements a specific class, use to find your plugin singleton.
  * Note: beware the classloader fun.
  *
  * @param pluginClazz The class that your plugin implements.
  * @return The plugin singleton or <code>null</code> if for some reason the plugin is not loaded.
  */
 public PluginWrapper getPlugin(Class<? extends Plugin> pluginClazz) {
   for (PluginWrapper p : plugins) {
     if (pluginClazz.isInstance(p.getPlugin())) return p;
   }
   return null;
 }
Esempio n. 8
0
 /**
  * Get the plugin instance with the given short name.
  *
  * @param shortName the short name of the plugin
  * @return The plugin singleton or <code>null</code> if a plugin with the given short name does
  *     not exist.
  */
 public PluginWrapper getPlugin(String shortName) {
   for (PluginWrapper p : plugins) {
     if (p.getShortName().equals(shortName)) return p;
   }
   return null;
 }