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

1 /*
2 * The MIT License
3 *
4 * Copyright (c) 2004-2010, Sun Microsystems, Inc., Michael B. Donohue, Seiji Sogabe
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.model;
25
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.List;
29
30 import hudson.console.ModelHyperlinkNote;
31 import hudson.diagnosis.OldDataMonitor;
32 import hudson.util.XStream2;
33 import jenkins.model.Jenkins;
34 import org.kohsuke.stapler.export.Exported;
35 import org.kohsuke.stapler.export.ExportedBean;
36 import com.thoughtworks.xstream.converters.UnmarshallingContext;
37 import java.util.HashSet;
38 import java.util.Set;
39 import javax.annotation.Nonnull;
40
41 /**
42 * Cause object base class. This class hierarchy is used to keep track of why
43 * a given build was started. This object encapsulates the UI rendering of the cause,
44 * as well as providing more useful information in respective subypes.
45 *
46 * The Cause object is connected to a build via the {@link CauseAction} object.
47 *
48 * <h2>Views</h2>
49 * <dl>
50 * <dt>description.jelly
51 * <dd>Renders the cause to HTML. By default, it puts the short description.
52 * </dl>
53 *
54 * @author Michael Donohue
55 * @see Run#getCauses()
56 * @see Queue.Item#getCauses()
57 */
58 @ExportedBean
59 public abstract class Cause {
60 /**
61 * One-line human-readable text of the cause.
62 *
63 * <p>
64 * By default, this method is used to render HTML as well.
65 */
66 @Exported(visibility=3)
67 public abstract String getShortDescription();
68
69 /**
70 * Called when the cause is registered to {@link AbstractBuild}.
71 *
72 * @param build
73 * never null
74 * @since 1.376
75 */
76 public void onAddedTo(AbstractBuild build) {}
77
78 /**
79 * Report a line to the listener about this cause.
80 * @since 1.362
81 */
82 public void print(TaskListener listener) {
83 listener.getLogger().println(getShortDescription());
84 }
85
86 /**
87 * Fall back implementation when no other type is available.
88 * @deprecated since 2009-02-08
89 */
90 public static class LegacyCodeCause extends Cause {
91 private StackTraceElement [] stackTrace;
92 public LegacyCodeCause() {
93 stackTrace = new Exception().getStackTrace();
94 }
95
96 @Override
97 public String getShortDescription() {
98 return Messages.Cause_LegacyCodeCause_ShortDescription();
99 }
100 }
101
102 /**
103 * A build is triggered by the completion of another build (AKA upstream build.)
104 */
105 public static class UpstreamCause extends Cause {
106
107 /**
108 * Maximum depth of transitive upstream causes we want to record.
109 */
110 private static final int MAX_DEPTH = 10;
111 /**
112 * Maximum number of transitive upstream causes we want to record.
113 */
114 private static final int MAX_LEAF = 25;
115 private String upstreamProject, upstreamUrl;
116 private int upstreamBuild;
117 /**
118 * @deprecated since 2009-02-28
119 */
120 @Deprecated
121 private transient Cause upstreamCause;
122 private @Nonnull List<Cause> upstreamCauses;
123
124 /**
125 * @deprecated since 2009-02-28
126 */
127 // for backward bytecode compatibility
128 public UpstreamCause(AbstractBuild<?,?> up) {
129 this((Run<?,?>)up);
130 }
131
132 public UpstreamCause(Run<?, ?> up) {
133 upstreamBuild = up.getNumber();
134 upstreamProject = up.getParent().getFullName();
135 upstreamUrl = up.getParent().getUrl();
136 upstreamCauses = new ArrayList<Cause>();
137 Set<String> traversed = new HashSet<String>();
138 for (Cause c : up.getCauses()) {
139 upstreamCauses.add(trim(c, MAX_DEPTH, traversed));
140 }
141 }
142
143 private UpstreamCause(String upstreamProject, int upstreamBuild, String upstreamUrl, @Nonnull List<Cause> upstreamCauses) {
144 this.upstreamProject = upstreamProject;
145 this.upstreamBuild = upstreamBuild;
146 this.upstreamUrl = upstreamUrl;
147 this.upstreamCauses = upstreamCauses;
148 }
149
150 private @Nonnull Cause trim(@Nonnull Cause c, int depth, Set<String> traversed) {
151 if (!(c instanceof UpstreamCause)) {
152 return c;
153 }
154 UpstreamCause uc = (UpstreamCause) c;
155 List<Cause> cs = new ArrayList<Cause>();
156 if (depth > 0) {
157 if (traversed.add(uc.upstreamUrl + uc.upstreamBuild)) {
158 for (Cause c2 : uc.upstreamCauses) {
159 cs.add(trim(c2, depth - 1, traversed));
160 }
161 }
162 } else if (traversed.size() < MAX_LEAF) {
163 cs.add(new DeeplyNestedUpstreamCause());
164 }
165 return new UpstreamCause(uc.upstreamProject, uc.upstreamBuild, uc.upstreamUrl, cs);
166 }
167
168 /**
169 * Returns true if this cause points to a build in the specified job.
170 */
171 public boolean pointsTo(Job<?,?> j) {
172 return j.getFullName().equals(upstreamProject);
173 }
174
175 /**
176 * Returns true if this cause points to the specified build.
177 */
178 public boolean pointsTo(Run<?,?> r) {
179 return r.getNumber()==upstreamBuild && pointsTo(r.getParent());
180 }
181
182 @Exported(visibility=3)
183 public String getUpstreamProject() {
184 return upstreamProject;
185 }
186
187 @Exported(visibility=3)
188 public int getUpstreamBuild() {
189 return upstreamBuild;
190 }
191
192 @Exported(visibility=3)
193 public String getUpstreamUrl() {
194 return upstreamUrl;
195 }
196
197 public List<Cause> getUpstreamCauses() {
198 return upstreamCauses;
199 }
200
201 @Override
202 public String getShortDescription() {
203 return Messages.Cause_UpstreamCause_ShortDescription(upstreamProject, upstreamBuild);
204 }
205
206 @Override
207 public void print(TaskListener listener) {
208 print(listener, 0);
209 }
210
211 private void indent(TaskListener listener, int depth) {
212 for (int i = 0; i < depth; i++) {
213 listener.getLogger().print(' ');
214 }
215 }
216
217 private void print(TaskListener listener, int depth) {
218 indent(listener, depth);
219 listener.getLogger().println(
220 Messages.Cause_UpstreamCause_ShortDescription(
221 ModelHyperlinkNote.encodeTo('/' + upstreamUrl, upstreamProject),
222 ModelHyperlinkNote.encodeTo('/'+upstreamUrl+upstreamBuild, Integer.toString(upstreamBuild)))
223 );
224 if (upstreamCauses != null && !upstreamCauses.isEmpty()) {
225 indent(listener, depth);
226 listener.getLogger().println(Messages.Cause_UpstreamCause_CausedBy());
227 for (Cause cause : upstreamCauses) {
228 if (cause instanceof UpstreamCause) {
229 ((UpstreamCause) cause).print(listener, depth + 1);
230 } else {
231 indent(listener, depth + 1);
232 cause.print(listener);
233 }
234 }
235 }
236 }
237
238 @Override public String toString() {
239 return upstreamUrl + upstreamBuild + upstreamCauses;
240 }
241
242 public static class ConverterImpl extends XStream2.PassthruConverter<UpstreamCause> {
243 public ConverterImpl(XStream2 xstream) { super(xstream); }
244 @Override protected void callback(UpstreamCause uc, UnmarshallingContext context) {
245 if (uc.upstreamCause != null) {
246 if (uc.upstreamCauses == null) uc.upstreamCauses = new ArrayList<Cause>();
247 uc.upstreamCauses.add(uc.upstreamCause);
248 uc.upstreamCause = null;
249 OldDataMonitor.report(context, "1.288");
250 }
251 }
252 }
253
254 public static class DeeplyNestedUpstreamCause extends Cause {
255 @Override public String getShortDescription() {
256 return "(deeply nested causes)";
257 }
258 @Override public String toString() {
259 return "JENKINS-14814";
260 }
261 }
262
263 }
264
265 /**
266 * A build is started by an user action.
267 *
268 * @deprecated 1.428
269 * use {@link UserIdCause}
270 */
271 public static class UserCause extends Cause {
272 private String authenticationName;
273 public UserCause() {
274 this.authenticationName = Jenkins.getAuthentication().getName();
275 }
276
277 @Exported(visibility=3)
278 public String getUserName() {
279 User u = User.get(authenticationName, false);
280 return u != null ? u.getDisplayName() : authenticationName;
281 }
282
283 @Override
284 public String getShortDescription() {
285 return Messages.Cause_UserCause_ShortDescription(authenticationName);
286 }
287
288 @Override
289 public boolean equals(Object o) {
290 return o instanceof UserCause && Arrays.equals(new Object[] {authenticationName},
291 new Object[] {((UserCause)o).authenticationName});
292 }
293
294 @Override
295 public int hashCode() {
296 return 295 + (this.authenticationName != null ? this.authenticationName.hashCode() : 0);
297 }
298 }
299
300 /**
301 * A build is started by an user action.
302 *
303 * @since 1.427
304 */
305 public static class UserIdCause extends Cause {
306
307 private String userId;
308
309 public UserIdCause() {
310 User user = User.current();
311 this.userId = (user == null) ? null : user.getId();
312 }
313
314 @Exported(visibility = 3)
315 public String getUserId() {
316 return userId;
317 }
318
319 @Exported(visibility = 3)
320 public String getUserName() {
321 String userName = "anonymous";
322 if (userId != null) {
323 User user = User.get(userId, false);
324 if (user != null)
325 userName = user.getDisplayName();
326 }
327 return userName;
328 }
329
330 @Override
331 public String getShortDescription() {
332 return Messages.Cause_UserIdCause_ShortDescription(getUserName());
333 }
334
335 @Override
336 public void print(TaskListener listener) {
337 listener.getLogger().println(Messages.Cause_UserIdCause_ShortDescription(
338 ModelHyperlinkNote.encodeTo("/user/"+getUserId(), getUserName())));
339 }
340
341 @Override
342 public boolean equals(Object o) {
343 return o instanceof UserIdCause && Arrays.equals(new Object[]{userId},
344 new Object[]{((UserIdCause) o).userId});
345 }
346
347 @Override
348 public int hashCode() {
349 return 295 + (this.userId != null ? this.userId.hashCode() : 0);
350 }
351 }
352
353 public static class RemoteCause extends Cause {
354 private String addr;
355 private String note;
356
357 public RemoteCause(String host, String note) {
358 this.addr = host;
359 this.note = note;
360 }
361
362 @Override
363 public String getShortDescription() {
364 if(note != null) {
365 return Messages.Cause_RemoteCause_ShortDescriptionWithNote(addr, note);
366 } else {
367 return Messages.Cause_RemoteCause_ShortDescription(addr);
368 }
369 }
370
371 @Override
372 public boolean equals(Object o) {
373 return o instanceof RemoteCause && Arrays.equals(new Object[] {addr, note},
374 new Object[] {((RemoteCause)o).addr, ((RemoteCause)o).note});
375 }
376
377 @Override
378 public int hashCode() {
379 int hash = 5;
380 hash = 83 * hash + (this.addr != null ? this.addr.hashCode() : 0);
381 hash = 83 * hash + (this.note != null ? this.note.hashCode() : 0);
382 return hash;
383 }
384 }
385 }
386