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

1 /*
2 * The MIT License
3 *
4 * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Tom Huybrechts
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 jenkins.model.lazy.AbstractLazyLoadRunMap;
27 import jenkins.model.lazy.BuildReference;
28 import org.apache.commons.collections.comparators.ReverseComparator;
29
30 import java.io.File;
31 import java.io.FilenameFilter;
32 import java.io.IOException;
33 import java.text.ParseException;
34 import java.text.SimpleDateFormat;
35 import java.util.Collections;
36 import java.util.Comparator;
37 import java.util.Iterator;
38 import java.util.Map;
39 import java.util.NoSuchElementException;
40 import java.util.SortedMap;
41 import java.util.logging.Level;
42 import java.util.logging.Logger;
43
44 import static java.util.logging.Level.*;
45 import static jenkins.model.lazy.AbstractLazyLoadRunMap.Direction.*;
46
47 /**
48 * {@link Map} from build number to {@link Run}.
49 *
50 * <p>
51 * This class is multi-thread safe by using copy-on-write technique,
52 * and it also updates the bi-directional links within {@link Run}
53 * accordingly.
54 *
55 * @author Kohsuke Kawaguchi
56 */
57 // in practice R is always bound by AbstractBuild, but making that change causes all kinds of
58 // signature breakage.
59 public final class RunMap<R extends Run<?,R>> extends AbstractLazyLoadRunMap<R> implements Iterable<R> {
60 /**
61 * Read-only view of this map.
62 */
63 private final SortedMap<Integer,R> view = Collections.unmodifiableSortedMap(this);
64
65 private Constructor<R> cons;
66
67 // TODO: before first complete build
68 // patch up next/previous build link
69
70
71 /**
72 * @deprecated as of 1.485
73 * Use {@link #RunMap(File, Constructor)}.
74 */
75 public RunMap() {
76 super(null); // will be set later
77 }
78
79 /**
80 * @param cons
81 * Used to create new instance of {@link Run}.
82 */
83 public RunMap(File baseDir, Constructor cons) {
84 super(baseDir);
85 this.cons = cons;
86 }
87
88 public boolean remove(R run) {
89 return removeValue(run);
90 }
91
92 /**
93 * Walks through builds, newer ones first.
94 */
95 public Iterator<R> iterator() {
96 return new Iterator<R>() {
97 R last = null;
98 R next = newestBuild();
99
100 public boolean hasNext() {
101 return next!=null;
102 }
103
104 public R next() {
105 last = next;
106 if (last!=null)
107 next = last.getPreviousBuild();
108 else
109 throw new NoSuchElementException();
110 return last;
111 }
112
113 public void remove() {
114 if (last==null)
115 throw new UnsupportedOperationException();
116 removeValue(last);
117 }
118 };
119 }
120
121 @Override
122 public boolean removeValue(R run) {
123 run.dropLinks();
124 return super.removeValue(run);
125 }
126
127 /**
128 * Gets the read-only view of this map.
129 */
130 public SortedMap<Integer,R> getView() {
131 return view;
132 }
133
134 /**
135 * This is the newest build (with the biggest build number)
136 */
137 public R newestValue() {
138 return search(Integer.MAX_VALUE, DESC);
139 }
140
141 /**
142 * This is the oldest build (with the smallest build number)
143 */
144 public R oldestValue() {
145 return search(Integer.MIN_VALUE, ASC);
146 }
147
148 /**
149 * @deprecated as of 1.485
150 * Use {@link ReverseComparator}
151 */
152 public static final Comparator<Comparable> COMPARATOR = new Comparator<Comparable>() {
153 public int compare(Comparable o1, Comparable o2) {
154 return -o1.compareTo(o2);
155 }
156 };
157
158 /**
159 * {@link Run} factory.
160 */
161 public interface Constructor<R extends Run<?,R>> {
162 R create(File dir) throws IOException;
163 }
164
165 @Override
166 protected final int getNumberOf(R r) {
167 return r.getNumber();
168 }
169
170 @Override
171 protected final String getIdOf(R r) {
172 return r.getId();
173 }
174
175 @Override
176 public R put(R r) {
177 return super._put(r);
178 }
179
180 /**
181 * Reuses the same reference as much as we can.
182 * <p>
183 * If concurrency ends up creating a few extra, that's OK, because
184 * we are really just trying to reduce the # of references we create.
185 */
186 @Override
187 protected BuildReference<R> createReference(R r) {
188 if (r instanceof AbstractBuild) return ((AbstractBuild)r).selfReference;
189 else return super.createReference(r);
190 }
191
192 @Override
193 protected FilenameFilter createDirectoryFilter() {
194 final SimpleDateFormat formatter = Run.ID_FORMATTER.get();
195
196 return new FilenameFilter() {
197 public boolean accept(File dir, String name) {
198 // JENKINS-1461 sometimes create bogus data directories with impossible dates, such as year 0, April 31st,
199 // or August 0th. Date object doesn't roundtrip those, so we eventually fail to load this data.
200 // Don't even bother trying.
201 if (!isCorrectDate(name)) {
202 LOGGER.log(FINE, "Skipping {0}", new File(dir,name));
203 return false;
204 }
205 return !name.startsWith("0000") && new File(dir,name).isDirectory();
206 }
207
208 private boolean isCorrectDate(String name) {
209 try {
210 if(formatter.format(formatter.parse(name)).equals(name))
211 return true;
212 } catch (ParseException e) {
213 // fall through
214 }
215 return false;
216 }
217 };
218 }
219
220 @Override
221 protected R retrieve(File d) throws IOException {
222 if(new File(d,"build.xml").exists()) {
223 // if the build result file isn't in the directory, ignore it.
224 try {
225 R b = cons.create(d);
226 b.onLoad();
227 if (LOGGER.isLoggable(FINE))
228 LOGGER.log(FINE,"Loaded " + b.getFullDisplayName(),new ThisIsHowItsLoaded());
229 return b;
230 } catch (IOException e) {
231 LOGGER.log(Level.WARNING, "could not load " + d, e);
232 } catch (InstantiationError e) {
233 LOGGER.log(Level.WARNING, "could not load " + d, e);
234 }
235 }
236 return null;
237 }
238
239 /**
240 * Backward compatibility method that notifies {@link RunMap} of who the owner is.
241 *
242 * Traditionally, this method blocked and loaded all the build records on the disk,
243 * but now all the actual loading happens lazily.
244 *
245 * @param job
246 * Job that owns this map.
247 * @param cons
248 * Used to create new instance of {@link Run}.
249 * @deprecated as of 1.485
250 * Use {@link #RunMap(File, Constructor)}
251 */
252 public void load(Job job, Constructor<R> cons) {
253 this.cons = cons;
254 initBaseDir(job.getBuildDir());
255 }
256
257 private static final Logger LOGGER = Logger.getLogger(RunMap.class.getName());
258
259 private static class ThisIsHowItsLoaded extends Exception {}
260 }
261