File D:\maven-qcr-plugin-testsunitaires\qcr4java\jenkins-master\target\site\qc\core\src\main\java\hudson\Plugin.java.html

1 /*
2 * The MIT License
3 *
4 * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24 package hudson;
25
26 import hudson.util.TimeUnit2;
27 import jenkins.model.Jenkins;
28 import hudson.model.Descriptor;
29 import hudson.model.Saveable;
30 import hudson.model.listeners.ItemListener;
31 import hudson.model.listeners.SaveableListener;
32 import hudson.model.Descriptor.FormException;
33 import org.kohsuke.stapler.MetaClass;
34 import org.kohsuke.stapler.StaplerRequest;
35 import org.kohsuke.stapler.StaplerResponse;
36
37 import javax.servlet.ServletContext;
38 import javax.servlet.ServletException;
39 import javax.servlet.http.HttpServletResponse;
40 import java.io.IOException;
41 import java.io.File;
42 import java.net.URL;
43
44 import net.sf.json.JSONObject;
45 import com.thoughtworks.xstream.XStream;
46
47 /**
48 * Base class of Hudson plugin.
49 *
50 * <p>
51 * A plugin needs to derive from this class.
52 *
53 * <p>
54 * One instance of a plugin is created by Hudson, and used as the entry point
55 * to plugin functionality.
56 *
57 * <p>
58 * A plugin is bound to URL space of Hudson as <tt>${rootURL}/plugin/foo/</tt>,
59 * where "foo" is taken from your plugin name "foo.jpi". All your web resources
60 * in src/main/webapp are visible from this URL, and you can also define Jelly
61 * views against your Plugin class, and those are visible in this URL, too.
62 *
63 * <p>
64 * {@link Plugin} can have an optional <tt>config.jelly</tt> page. If present,
65 * it will become a part of the system configuration page (http://server/hudson/configure).
66 * This is convenient for exposing/maintaining configuration that doesn't
67 * fit any {@link Descriptor}s.
68 *
69 * <p>
70 * Up until Hudson 1.150 or something, subclasses of {@link Plugin} required
71 * <tt>@plugin</tt> javadoc annotation, but that is no longer a requirement.
72 *
73 * @author Kohsuke Kawaguchi
74 * @since 1.42
75 */
76 public abstract class Plugin implements Saveable {
77
78 /**
79 * Set by the {@link PluginManager}, before the {@link #start()} method is called.
80 * This points to the {@link PluginWrapper} that wraps
81 * this {@link Plugin} object.
82 */
83 /*package*/ transient PluginWrapper wrapper;
84
85 /**
86 * Called when a plugin is loaded to make the {@link ServletContext} object available to a plugin.
87 * This object allows plugins to talk to the surrounding environment.
88 *
89 * <p>
90 * The default implementation is no-op.
91 *
92 * @param context
93 * Always non-null.
94 *
95 * @since 1.42
96 */
97 public void setServletContext(ServletContext context) {
98 }
99
100 /**
101 * Gets the paired {@link PluginWrapper}.
102 *
103 * @since 1.426
104 */
105 public PluginWrapper getWrapper() {
106 return wrapper;
107 }
108
109 /**
110 * Called to allow plugins to initialize themselves.
111 *
112 * <p>
113 * This method is called after {@link #setServletContext(ServletContext)} is invoked.
114 * You can also use {@link jenkins.model.Jenkins#getInstance()} to access the singleton hudson instance,
115 * although the plugin start up happens relatively early in the initialization
116 * stage and not all the data are loaded in Hudson.
117 *
118 * <p>
119 * If a plugin wants to run an initialization step after all plugins and extension points
120 * are registered, a good place to do that is {@link #postInitialize()}.
121 * If a plugin wants to run an initialization step after all the jobs are loaded,
122 * {@link ItemListener#onLoaded()} is a good place.
123 *
124 * @throws Exception
125 * any exception thrown by the plugin during the initialization will disable plugin.
126 *
127 * @since 1.42
128 * @see ExtensionPoint
129 * @see #postInitialize()
130 */
131 public void start() throws Exception {
132 }
133
134 /**
135 * Called after {@link #start()} is called for all the plugins.
136 *
137 * @throws Exception
138 * any exception thrown by the plugin during the initialization will disable plugin.
139 */
140 public void postInitialize() throws Exception {}
141
142 /**
143 * Called to orderly shut down Hudson.
144 *
145 * <p>
146 * This is a good opportunity to clean up resources that plugin started.
147 * This method will not be invoked if the {@link #start()} failed abnormally.
148 *
149 * @throws Exception
150 * if any exception is thrown, it is simply recorded and shut-down of other
151 * plugins continue. This is primarily just a convenience feature, so that
152 * each plugin author doesn't have to worry about catching an exception and
153 * recording it.
154 *
155 * @since 1.42
156 */
157 public void stop() throws Exception {
158 }
159
160 /**
161 * @since 1.233
162 * @deprecated as of 1.305 override {@link #configure(StaplerRequest,JSONObject)} instead
163 */
164 public void configure(JSONObject formData) throws IOException, ServletException, FormException {
165 }
166
167 /**
168 * Handles the submission for the system configuration.
169 *
170 * <p>
171 * If this class defines <tt>config.jelly</tt> view, be sure to
172 * override this method and persists the submitted values accordingly.
173 *
174 * <p>
175 * The following is a sample <tt>config.jelly</tt> that you can start yours with:
176 * <pre><xmp>
177 * <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">
178 * <f:section title="Locale">
179 * <f:entry title="${%Default Language}" help="/plugin/locale/help/default-language.html">
180 * <f:textbox name="systemLocale" value="${it.systemLocale}" />
181 * </f:entry>
182 * </f:section>
183 * </j:jelly>
184 * </xmp></pre>
185 *
186 * <p>
187 * This allows you to access data as {@code formData.getString("systemLocale")}
188 *
189 * <p>
190 * If you are using this method, you'll likely be interested in
191 * using {@link #save()} and {@link #load()}.
192 * @since 1.305
193 */
194 public void configure(StaplerRequest req, JSONObject formData) throws IOException, ServletException, FormException {
195 configure(formData);
196 }
197
198 /**
199 * This method serves static resources in the plugin under <tt>hudson/plugin/SHORTNAME</tt>.
200 */
201 public void doDynamic(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
202 String path = req.getRestOfPath();
203
204 if(path.length()==0)
205 path = "/";
206
207 if(path.indexOf("..")!=-1 || path.length()<1) {
208 // don't serve anything other than files in the sub directory.
209 rsp.sendError(HttpServletResponse.SC_BAD_REQUEST);
210 return;
211 }
212
213 // Stapler routes requests like the "/static/.../foo/bar/zot" to be treated like "/foo/bar/zot"
214 // and this is used to serve long expiration header, by using Jenkins.VERSION_HASH as "..."
215 // to create unique URLs. Recognize that and set a long expiration header.
216 String requestPath = req.getRequestURI().substring(req.getContextPath().length());
217 boolean staticLink = requestPath.startsWith("/static/");
218
219 long expires = staticLink ? TimeUnit2.DAYS.toMillis(365) : -1;
220
221 // use serveLocalizedFile to support automatic locale selection
222 rsp.serveLocalizedFile(req, new URL(wrapper.baseResourceURL,'.'+path),expires);
223 }
224
225 //
226 // Convenience methods for those plugins that persist configuration
227 //
228 /**
229 * Loads serializable fields of this instance from the persisted storage.
230 *
231 * <p>
232 * If there was no previously persisted state, this method is no-op.
233 *
234 * @since 1.245
235 */
236 protected void load() throws IOException {
237 XmlFile xml = getConfigXml();
238 if(xml.exists())
239 xml.unmarshal(this);
240 }
241
242 /**
243 * Saves serializable fields of this instance to the persisted storage.
244 *
245 * @since 1.245
246 */
247 public void save() throws IOException {
248 if(BulkChange.contains(this)) return;
249 XmlFile config = getConfigXml();
250 config.write(this);
251 SaveableListener.fireOnChange(this, config);
252 }
253
254 /**
255 * Controls the file where {@link #load()} and {@link #save()}
256 * persists data.
257 *
258 * This method can be also overriden if the plugin wants to
259 * use a custom {@link XStream} instance to persist data.
260 *
261 * @since 1.245
262 */
263 protected XmlFile getConfigXml() {
264 return new XmlFile(Jenkins.XSTREAM,
265 new File(Jenkins.getInstance().getRootDir(),wrapper.getShortName()+".xml"));
266 }
267
268
269 /**
270 * Dummy instance of {@link Plugin} to be used when a plugin didn't
271 * supply one on its own.
272 *
273 * @since 1.321
274 */
275 public static final class DummyImpl extends Plugin {}
276 }
277