All Downloads are FREE. Search and download functionalities are using the official Maven repository.

hudson.Plugin Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 *
 * Copyright (c) 2004-2009 Oracle Corporation.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *
 *    Kohsuke Kawaguchi
 *
 *
 *******************************************************************************/ 

package hudson;

import com.thoughtworks.xstream.XStream;
import hudson.model.Descriptor;
import hudson.model.Descriptor.FormException;
import hudson.model.Hudson;
import hudson.model.Saveable;
import hudson.model.listeners.ItemListener;
import hudson.model.listeners.SaveableListener;
import hudson.util.TimeUnit2;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;

/**
 * Base class of Hudson plugin.
 *
 * 

A plugin needs to derive from this class. * *

One instance of a plugin is created by Hudson, and used as the entry * point to plugin functionality. * *

A plugin is bound to URL space of Hudson as * ${rootURL}/plugin/foo/, where "foo" is taken from your plugin name * "foo.hpi". All your web resources in src/main/webapp are visible from this * URL, and you can also define Jelly views against your Plugin class, and those * are visible in this URL, too. * *

{@link Plugin} can have an optional config.jelly page. If * present, it will become a part of the system configuration page * (http://server/hudson/configure). This is convenient for exposing/maintaining * configuration that doesn't fit any {@link Descriptor}s. * *

Up until Hudson 1.150 or something, subclasses of {@link Plugin} required * @plugin javadoc annotation, but that is no longer a requirement. * * @author Kohsuke Kawaguchi * @since 1.42 */ public abstract class Plugin implements Saveable { /** * Set by the {@link PluginManager}. This points to the * {@link PluginWrapper} that wraps this {@link Plugin} object. */ /*package*/ transient PluginWrapper wrapper; /** * Called when a plugin is loaded to make the {@link ServletContext} object * available to a plugin. This object allows plugins to talk to the * surrounding environment. * *

The default implementation is no-op. * * @param context Always non-null. * * @since 1.42 */ public void setServletContext(ServletContext context) { } /** * Called to allow plugins to initialize themselves. * *

This method is called after * {@link #setServletContext(ServletContext)} is invoked. You can also use * {@link Hudson#getInstance()} to access the singleton hudson instance, * although the plugin start up happens relatively early in the * initialization stage and not all the data are loaded in Hudson. * *

If a plugin wants to run an initialization step after all plugins and * extension points are registered, a good place to do that is * {@link #postInitialize()}. If a plugin wants to run an initialization * step after all the jobs are loaded, {@link ItemListener#onLoaded()} is a * good place. * * @throws Exception any exception thrown by the plugin during the * initialization will disable plugin. * * @since 1.42 * @see ExtensionPoint * @see #postInitialize() */ public void start() throws Exception { } /** * Called after {@link #start()} is called for all the plugins. * * @throws Exception any exception thrown by the plugin during the * initialization will disable plugin. */ public void postInitialize() throws Exception { } /** * Called to orderly shut down Hudson. * *

This is a good opportunity to clean up resources that plugin started. * This method will not be invoked if the {@link #start()} failed * abnormally. * * @throws Exception if any exception is thrown, it is simply recorded and * shut-down of other plugins continue. This is primarily just a convenience * feature, so that each plugin author doesn't have to worry about catching * an exception and recording it. * * @since 1.42 */ public void stop() throws Exception { } /** * @since 1.233 * @deprecated as of 1.305 override * {@link #configure(StaplerRequest,JSONObject)} instead */ public void configure(JSONObject formData) throws IOException, ServletException, FormException { } /** * Handles the submission for the system configuration. * *

If this class defines config.jelly view, be sure to override * this method and persists the submitted values accordingly. * *

The following is a sample config.jelly that you can start * yours with: *


     * <j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
     *   <f:section title="Locale">
     *     <f:entry title="${%Default Language}" help="/plugin/locale/help/default-language.html">
     *       <f:textbox name="systemLocale" value="${it.systemLocale}" />
     *     </f:entry>
     *   </f:section>
     * </j:jelly>
     * 
* *

This allows you to access data as * {@code formData.getString("systemLocale")} * *

If you are using this method, you'll likely be interested in using * {@link #save()} and {@link #load()}. * * @since 1.305 */ public void configure(StaplerRequest req, JSONObject formData) throws IOException, ServletException, FormException { configure(formData); } /** * This method serves static resources in the plugin under * hudson/plugin/SHORTNAME. */ public void doDynamic(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, URISyntaxException { String path = req.getRestOfPath(); if (path.length() == 0) { path = "/"; } String requestPath = req.getRequestURI().substring(req.getContextPath().length()); boolean staticLink = requestPath.startsWith("/static/"); long expires = staticLink ? TimeUnit2.DAYS.toMillis(365) : -1; try { rsp.serveLocalizedFile(req, wrapper.baseResourceURL.toURI().resolve(new URI(null, '.' + path, null)).toURL(), expires); } catch (URISyntaxException x) { throw new IOException(x); } } // // Convenience methods for those plugins that persist configuration // /** * Loads serializable fields of this instance from the persisted storage. * *

If there was no previously persisted state, this method is no-op. * * @since 1.245 */ protected void load() throws IOException { XmlFile xml = getConfigXml(); if (xml.exists()) { xml.unmarshal(this); } } /** * Saves serializable fields of this instance to the persisted storage. * * @since 1.245 */ public void save() throws IOException { if (BulkChange.contains(this)) { return; } getConfigXml().write(this); SaveableListener.fireOnChange(this, getConfigXml()); } /** * Controls the file where {@link #load()} and {@link #save()} persists * data. * * This method can be also overriden if the plugin wants to use a custom * {@link XStream} instance to persist data. * * @since 1.245 */ protected XmlFile getConfigXml() { return new XmlFile(Hudson.XSTREAM, new File(Hudson.getInstance().getRootDir(), wrapper.getShortName() + ".xml")); } /** * Dummy instance of {@link Plugin} to be used when a plugin didn't supply * one on its own. * * @since 1.321 */ public static final class DummyImpl extends Plugin { } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy