File Source: UpdateChecker.java
/*
P/P * Method: com.dmdirc.updater.UpdateChecker$1__static_init
*/
1 /*
2 * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 package com.dmdirc.updater;
24
25 import com.dmdirc.Precondition;
26 import com.dmdirc.config.ConfigManager;
27 import com.dmdirc.config.IdentityManager;
28 import com.dmdirc.logger.ErrorLevel;
29 import com.dmdirc.logger.Logger;
30 import com.dmdirc.updater.components.ClientComponent;
31 import com.dmdirc.updater.components.DefaultsComponent;
32 import com.dmdirc.updater.components.ModeAliasesComponent;
33 import com.dmdirc.util.Downloader;
34 import com.dmdirc.util.ListenerList;
35
36 import java.io.IOException;
37 import java.net.MalformedURLException;
38 import java.util.ArrayList;
39 import java.util.Date;
40 import java.util.List;
41 import java.util.Timer;
42 import java.util.TimerTask;
43 import java.util.concurrent.Semaphore;
44
45 /**
46 * The update checker contacts the DMDirc website to check to see if there
47 * are any updates available.
48 *
49 * @author chris
50 */
/*
P/P * Method: com.dmdirc.updater.UpdateChecker__static_init
*
* Postconditions:
* components == &new ArrayList(UpdateChecker__static_init#2)
* listener == &new UpdateChecker$1(UpdateChecker__static_init#6)
* listeners == &new ListenerList(UpdateChecker__static_init#5)
* mutex == &new Semaphore(UpdateChecker__static_init#1)
* status == &com.dmdirc.updater.UpdateChecker$STATE__static_init.new UpdateChecker$STATE(UpdateChecker$STATE__static_init#1)
* timer == &new Timer(UpdateChecker__static_init#3)
* updates == &new ArrayList(UpdateChecker__static_init#4)
* new ArrayList(UpdateChecker__static_init#2) num objects == 1
* new ArrayList(UpdateChecker__static_init#4) num objects == 1
* new HashMap(MapList#1) num objects == 1
* ...
*/
51 public final class UpdateChecker implements Runnable {
52
53 /** The possible states for the checker. */
/*
P/P * Method: void com.dmdirc.updater.UpdateChecker$STATE(String, int)
*/
54 public static enum STATE {
55 /** Nothing's happening. */
/*
P/P * Method: com.dmdirc.updater.UpdateChecker$STATE__static_init
*
* Postconditions:
* $VALUES == &new UpdateChecker$STATE[](UpdateChecker$STATE__static_init#6)
* CHECKING == &new UpdateChecker$STATE(UpdateChecker$STATE__static_init#2)
* $VALUES[1] == &new UpdateChecker$STATE(UpdateChecker$STATE__static_init#2)
* IDLE == &new UpdateChecker$STATE(UpdateChecker$STATE__static_init#1)
* $VALUES[0] == &new UpdateChecker$STATE(UpdateChecker$STATE__static_init#1)
* RESTART_REQUIRED == &new UpdateChecker$STATE(UpdateChecker$STATE__static_init#5)
* $VALUES[4] == &new UpdateChecker$STATE(UpdateChecker$STATE__static_init#5)
* UPDATES_AVAILABLE == &new UpdateChecker$STATE(UpdateChecker$STATE__static_init#4)
* $VALUES[3] == &new UpdateChecker$STATE(UpdateChecker$STATE__static_init#4)
* UPDATING == &new UpdateChecker$STATE(UpdateChecker$STATE__static_init#3)
* ...
*/
56 IDLE,
57 /** Currently checking for updates. */
58 CHECKING,
59 /** Currently updating. */
60 UPDATING,
61 /** New updates are available. */
62 UPDATES_AVAILABLE,
63 /** Updates installed but restart needed. */
64 RESTART_REQUIRED,
65 }
66
67 /** Semaphore used to prevent multiple invocations. */
68 private static final Semaphore mutex = new Semaphore(1);
69
70 /** A list of components that we're to check. */
71 private static final List<UpdateComponent> components
72 = new ArrayList<UpdateComponent>();
73
74 /** Our timer. */
75 private static Timer timer = new Timer("Update Checker Timer");
76
77 /** The list of updates that are available. */
78 private static final List<Update> updates = new ArrayList<Update>();
79
80 /** A list of our listeners. */
81 private static final ListenerList listeners = new ListenerList();
82
83 /** Our current state. */
84 private static STATE status = STATE.IDLE;
85
86 /** A reference to the listener we use for update status changes. */
/*
P/P * Method: void com.dmdirc.updater.UpdateChecker$1()
*/
87 private static final UpdateListener listener = new UpdateListener() {
88 @Override
89 public void updateStatusChange(final Update update, final UpdateStatus status) {
/*
P/P * Method: void updateStatusChange(Update, UpdateStatus)
*
* Preconditions:
* (soft) com.dmdirc.util.ListenerList.new MapList(ListenerList#1).map != null
* (soft) init'ed(com/dmdirc/updater/UpdateChecker.status)
* (soft) update != null
* (soft) update.listeners != null
*
* Postconditions:
* com/dmdirc/updater/UpdateChecker.status == One-of{&com.dmdirc.updater.UpdateChecker$STATE__static_init.new UpdateChecker$STATE(UpdateChecker$STATE__static_init#1), old com/dmdirc/updater/UpdateChecker.status, &com.dmdirc.updater.UpdateChecker$STATE__static_init.new UpdateChecker$STATE(UpdateChecker...
* init'ed(com/dmdirc/updater/UpdateChecker.status)
*/
90 if (status == UpdateStatus.INSTALLED
91 || status == UpdateStatus.ERROR) {
92 removeUpdate(update);
93 } else if (status == UpdateStatus.RESTART_NEEDED && UpdateChecker.status
94 == STATE.UPDATING) {
95 doNextUpdate();
96 }
97 }
98
99 @Override
100 public void updateProgressChange(final Update update, final float progress) {
101 // Don't care
/*
P/P * Method: void updateProgressChange(Update, float)
*/
102 }
103 };
104
105 static {
106 components.add(new ClientComponent());
107 components.add(new ModeAliasesComponent());
108 components.add(new DefaultsComponent());
109 }
110
111 /**
112 * Instantiates an Updatechecker.
113 */
/*
P/P * Method: void com.dmdirc.updater.UpdateChecker()
*/
114 public UpdateChecker() {
115 //Ignore
116 }
117
118 /** {@inheritDoc} */
119 @Override
120 public void run() {
/*
P/P * Method: void run()
*
* Preconditions:
* (soft) new MapList(ListenerList#1).map != null
* (soft) init'ed(status)
* (soft) timer != null
*
* Presumptions:
* com.dmdirc.config.IdentityManager:getConfigIdentity(...)@131 != null
* com.dmdirc.config.IdentityManager:getConfigIdentity(...)@198 != null
* com.dmdirc.config.IdentityManager:getGlobalConfig(...)@127 != null
* init'ed(com.dmdirc.logger.ErrorLevel.LOW)
* java.util.ArrayList:iterator(...)@142 != null
* ...
*
* Postconditions:
* status == One-of{old status, &com.dmdirc.updater.UpdateChecker$STATE__static_init.new UpdateChecker$STATE(UpdateChecker$STATE__static_init#1), &com.dmdirc.updater.UpdateChecker$STATE__static_init.new UpdateChecker$STATE(UpdateChecker$STATE__static_init#4), &com.dmdi...
* timer == One-of{old timer, &new Timer(init#3)}
* timer != null
* new Timer(init#3) num objects <= 1
*
* Test Vectors:
* com.dmdirc.config.ConfigManager:getOptionBool(...)@129: {0}, {1}
* com.dmdirc.config.ConfigManager:getOptionBool(...)@203: {0}, {1}
* java.lang.StringBuilder:length(...)@164: {-231..0}, {1..232-1}
* java.util.Iterator:hasNext(...)@142: {0}, {1}
* java.util.Iterator:hasNext(...)@152: {0}, {1}
* java.util.Iterator:hasNext(...)@187: {0}, {1}
* java.util.List:isEmpty(...)@180: {0}, {1}
* java.util.concurrent.Semaphore:tryAcquire(...)@121: {1}, {0}
* update.status@142: Addr_Set{&com.dmdirc.updater.UpdateStatus__static_init.new UpdateStatus(UpdateStatus__static_init#6)}, Inverse{&com.dmdirc.updater.UpdateStatus__static_init.new UpdateStatus(UpdateStatus__static_init#6)}
* update.status@187: Inverse{&com.dmdirc.updater.UpdateStatus__static_init.new UpdateStatus(UpdateStatus__static_init#1)}, Addr_Set{&com.dmdirc.updater.UpdateStatus__static_init.new UpdateStatus(UpdateStatus__static_init#1)}
*/
121 if (!mutex.tryAcquire()) {
122 // Duplicate invocation
123
124 return;
125 }
126
127 final ConfigManager config = IdentityManager.getGlobalConfig();
128
129 if (!config.getOptionBool("updater", "enable")
130 || status == STATE.UPDATING) {
131 IdentityManager.getConfigIdentity().setOption("updater",
132 "lastcheck", String.valueOf((int) (new Date().getTime() / 1000)));
133
134 mutex.release();
135 init();
136 return;
137 }
138
139 setStatus(STATE.CHECKING);
140
141 // Remove any existing update that isn't waiting for a restart.
142 for (Update update : new ArrayList<Update>(updates)) {
143 if (update.getStatus() != UpdateStatus.RESTART_NEEDED) {
144 updates.remove(update);
145 }
146 }
147
148 final StringBuilder data = new StringBuilder();
149 final String updateChannel = config.getOption("updater", "channel");
150
151 // Build the data string to send to the server
152 for (UpdateComponent component : components) {
153 if (isEnabled(component)) {
154 data.append(component.getName());
155 data.append(',');
156 data.append(updateChannel);
157 data.append(',');
158 data.append(component.getVersion());
159 data.append(';');
160 }
161 }
162
163 // If we actually have components to check
164 if (data.length() > 0) {
165 try {
166 final List<String> response
167 = Downloader.getPage("http://updates.dmdirc.com/", "data=" + data);
168
169 for (String line : response) {
170 checkLine(line);
171 }
172 } catch (MalformedURLException ex) {
173 Logger.appError(ErrorLevel.LOW, "Error when checking for updates", ex);
174 } catch (IOException ex) {
175 Logger.userError(ErrorLevel.LOW,
176 "I/O error when checking for updates: " + ex.getMessage());
177 }
178 }
179
180 if (updates.isEmpty()) {
181 setStatus(STATE.IDLE);
182 } else {
183 boolean available = false;
184
185 // Check to see if the updates are outstanding or just waiting for
186 // a restart
187 for (Update update : updates) {
188 if (update.getStatus() == UpdateStatus.PENDING) {
189 available = true;
190 }
191 }
192
193 setStatus(available ? STATE.UPDATES_AVAILABLE : STATE.RESTART_REQUIRED);
194 }
195
196 mutex.release();
197
198 IdentityManager.getConfigIdentity().setOption("updater",
199 "lastcheck", String.valueOf((int) (new Date().getTime() / 1000)));
200
201 UpdateChecker.init();
202
203 if (config.getOptionBool("updater", "autoupdate")) {
204 applyUpdates();
205 }
206 }
207
208 /**
209 * Checks the specified line to determine the message from the update server.
210 *
211 * @param line The line to be checked
212 */
213 private void checkLine(final String line) {
/*
P/P * Method: void checkLine(String)
*
* Preconditions:
* line != null
*
* Presumptions:
* init'ed(com.dmdirc.logger.ErrorLevel.LOW)
*
* Test Vectors:
* java.lang.String:startsWith(...)@214: {0}, {1}
* java.lang.String:startsWith(...)@216: {0}, {1}
* java.lang.String:startsWith(...)@219: {1}, {0}
*/
214 if (line.startsWith("outofdate")) {
215 doUpdateAvailable(line);
216 } else if (line.startsWith("error")) {
217 Logger.userError(ErrorLevel.LOW, "Error when checking for updates: "
218 + line.substring(6));
219 } else if (!line.startsWith("uptodate")) {
220 Logger.userError(ErrorLevel.LOW, "Unknown update line received from server: "
221 + line);
222 }
223 }
224
225 /**
226 * Informs the user that there's an update available.
227 *
228 * @param line The line that was received from the update server
229 */
230 private void doUpdateAvailable(final String line) {
/*
P/P * Method: void doUpdateAvailable(String)
*
* Preconditions:
* line != null
*/
231 final Update update = new Update(line);
232
233 if (update.getUrl() != null) {
234 updates.add(update);
235 update.addUpdateListener(listener);
236 }
237 }
238
239 /**
240 * Initialises the update checker. Sets a timer to check based on the
241 * frequency specified in the config.
242 */
243 public static void init() {
/*
P/P * Method: void init()
*
* Preconditions:
* timer != null
*
* Presumptions:
* com.dmdirc.config.IdentityManager:getGlobalConfig(...)@244 != null
* com.dmdirc.config.IdentityManager:getGlobalConfig(...)@246 != null
* init'ed(com.dmdirc.logger.ErrorLevel.LOW)
* java.util.Date:getTime(...)@248 in {-2_147_483_648_999..4_294_967_295_999}
* java.util.Date:getTime(...)@248/1_000 - (com.dmdirc.config.ConfigManager:getOptionInt(...)@244 + com.dmdirc.config.ConfigManager:getOptionInt(...)@246) in {-232+1..8_589_934_591}
*
* Postconditions:
* timer == &new Timer(init#3)
* new Timer(init#3) num objects == 1
*
* Test Vectors:
* java.util.Date:getTime(...)@248/1_000 - (com.dmdirc.config.ConfigManager:getOptionInt(...)@244 + com.dmdirc.config.ConfigManager:getOptionInt(...)@246): {0..8_589_934_591}, {-232+1..-1}
*/
244 final int last = IdentityManager.getGlobalConfig()
245 .getOptionInt("updater", "lastcheck");
246 final int freq = IdentityManager.getGlobalConfig()
247 .getOptionInt("updater", "frequency");
248 final int timestamp = (int) (new Date().getTime() / 1000);
249 int time = 0;
250
251 if (last + freq > timestamp) {
252 time = last + freq - timestamp;
253 }
254
255 if (time > freq || time < 0) {
256 Logger.userError(ErrorLevel.LOW, "Attempted to schedule update check "
257 + (time < 0 ? "in the past" : "too far in the future")
258 + ", rescheduling.");
259 time = 1;
260 }
261
262 timer.cancel();
263 timer = new Timer("Update Checker Timer");
/*
P/P * Method: void com.dmdirc.updater.UpdateChecker$2()
*/
264 timer.schedule(new TimerTask() {
265 /** {@inheritDoc} */
266 @Override
267 public void run() {
/*
P/P * Method: void run()
*/
268 checkNow();
269 }
270 }, time * 1000);
271 }
272
273 /**
274 * Checks for updates now.
275 */
276 public static void checkNow() {
/*
P/P * Method: void checkNow()
*/
277 new Thread(new UpdateChecker(), "Update Checker thread").start();
278 }
279
280 /**
281 * Registers an update component.
282 *
283 * @param component The component to be registered
284 */
285 public static void registerComponent(final UpdateComponent component) {
/*
P/P * Method: void registerComponent(UpdateComponent)
*/
286 components.add(component);
287 }
288
289 /**
290 * Unregisters an update component with the specified name.
291 *
292 * @param name The name of the component to be removed
293 */
294 public static void removeComponent(final String name) {
/*
P/P * Method: void removeComponent(String)
*
* Preconditions:
* (soft) name != null
*
* Presumptions:
* java.util.Iterator:next(...)@297 != null
*
* Test Vectors:
* java.lang.String:equals(...)@298: {0}, {1}
* java.util.Iterator:hasNext(...)@297: {0}, {1}
*/
295 UpdateComponent target = null;
296
297 for (UpdateComponent component : components) {
298 if (name.equals(component.getName())) {
299 target = component;
300 }
301 }
302
303 if (target != null) {
304 components.remove(target);
305 }
306 }
307
308 /**
309 * Finds and returns the component with the specified name.
310 *
311 * @param name The name of the component that we're looking for
312 * @return The corresponding UpdateComponent, or null if it's not found
313 */
314 @Precondition("The specified name is not null")
315 public static UpdateComponent findComponent(final String name) {
/*
P/P * Method: UpdateComponent findComponent(String)
*
* Preconditions:
* name != null
*
* Presumptions:
* java.util.Iterator:next(...)@318 != null
*
* Postconditions:
* init'ed(return_value)
*
* Test Vectors:
* java.lang.String:equals(...)@319: {0}, {1}
* java.util.Iterator:hasNext(...)@318: {0}, {1}
*/
316 assert(name != null);
317
318 for (UpdateComponent component : components) {
319 if (name.equals(component.getName())) {
320 return component;
321 }
322 }
323
324 return null;
325 }
326
327 /**
328 * Removes the specified update from the list. This should be called when
329 * the update has finished, has encountered an error, or the user does not
330 * want the update to be performed.
331 *
332 * @param update The update to be removed
333 */
334 public static void removeUpdate(final Update update) {
/*
P/P * Method: void removeUpdate(Update)
*
* Preconditions:
* update != null
* update.listeners != null
* (soft) new MapList(ListenerList#1).map != null
* (soft) init'ed(status)
*
* Postconditions:
* status == One-of{&com.dmdirc.updater.UpdateChecker$STATE__static_init.new UpdateChecker$STATE(UpdateChecker$STATE__static_init#1), old status, &com.dmdirc.updater.UpdateChecker$STATE__static_init.new UpdateChecker$STATE(UpdateChecker$STATE__static_init#5)}
* init'ed(status)
*
* Test Vectors:
* java.util.List:isEmpty(...)@338: {0}, {1}
*/
335 update.removeUpdateListener(listener);
336 updates.remove(update);
337
338 if (updates.isEmpty()) {
339 setStatus(STATE.IDLE);
340 } else if (status == STATE.UPDATING) {
341 doNextUpdate();
342 }
343 }
344
345 /**
346 * Downloads and installs all known updates.
347 */
348 public static void applyUpdates() {
/*
P/P * Method: void applyUpdates()
*
* Preconditions:
* (soft) new MapList(ListenerList#1).map != null
*
* Postconditions:
* status == One-of{old status, &com.dmdirc.updater.UpdateChecker$STATE__static_init.new UpdateChecker$STATE(UpdateChecker$STATE__static_init#3), &com.dmdirc.updater.UpdateChecker$STATE__static_init.new UpdateChecker$STATE(UpdateChecker$STATE__static_init#5), &com.dmdi...
*
* Test Vectors:
* java.util.List:isEmpty(...)@349: {1}, {0}
*/
349 if (!updates.isEmpty()) {
350 setStatus(STATE.UPDATING);
351 doNextUpdate();
352 }
353 }
354
355 /**
356 * Finds and applies the next pending update, or sets the state to idle
357 * / restart needed if appropriate.
358 */
359 private static void doNextUpdate() {
/*
P/P * Method: void doNextUpdate()
*
* Preconditions:
* (soft) new MapList(ListenerList#1).map != null
*
* Presumptions:
* java.util.Iterator:next(...)@362 != null
*
* Postconditions:
* status == One-of{old status, &com.dmdirc.updater.UpdateChecker$STATE__static_init.new UpdateChecker$STATE(UpdateChecker$STATE__static_init#5), &com.dmdirc.updater.UpdateChecker$STATE__static_init.new UpdateChecker$STATE(UpdateChecker$STATE__static_init#1)}
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@362: {0}, {1}
* update.status@362: Inverse{&com.dmdirc.updater.UpdateStatus__static_init.new UpdateStatus(UpdateStatus__static_init#1),&com.dmdirc.updater.UpdateStatus__static_init.new UpdateStatus(UpdateStatus__static_init#6)}, Addr_Set{&com.dmdirc.updater.UpdateStatus__static_init.new UpdateStatus(UpdateStatus__static_init#1)}, Addr_Set{&com.dmdirc.updater.UpdateStatus__static_init.new UpdateStatus(UpdateStatus__static_init#6)}
*/
360 boolean restart = false;
361
362 for (Update update : updates) {
363 if (update.getStatus() == UpdateStatus.PENDING) {
364 update.doUpdate();
365 return;
366 } else if (update.getStatus() == UpdateStatus.RESTART_NEEDED) {
367 restart = true;
368 }
369 }
370
371 setStatus(restart ? STATE.RESTART_REQUIRED : STATE.IDLE);
372 }
373
374 /**
375 * Retrieves a list of components registered with the checker.
376 *
377 * @return A list of registered components
378 */
379 public static List<UpdateComponent> getComponents() {
/*
P/P * Method: List getComponents()
*
* Postconditions:
* return_value == &new ArrayList(UpdateChecker__static_init#2)
*/
380 return components;
381 }
382
383 /**
384 * Retrives a list of available updates from the checker.
385 *
386 * @return A list of available updates
387 */
388 public static List<Update> getAvailableUpdates() {
/*
P/P * Method: List getAvailableUpdates()
*
* Postconditions:
* return_value == &new ArrayList(UpdateChecker__static_init#4)
*/
389 return updates;
390 }
391
392
393 /**
394 * Adds a new status listener to the update checker.
395 *
396 * @param listener The listener to be added
397 */
398 public static void addListener(final UpdateCheckerListener listener) {
/*
P/P * Method: void addListener(UpdateCheckerListener)
*
* Preconditions:
* new MapList(ListenerList#1).map != null
*/
399 listeners.add(UpdateCheckerListener.class, listener);
400 }
401
402 /**
403 * Removes a status listener from the update checker.
404 *
405 * @param listener The listener to be removed
406 */
407 public static void removeListener(final UpdateCheckerListener listener) {
/*
P/P * Method: void removeListener(UpdateCheckerListener)
*
* Preconditions:
* new MapList(ListenerList#1).map != null
*/
408 listeners.remove(UpdateCheckerListener.class, listener);
409 }
410
411 /**
412 * Retrieves the current status of the update checker.
413 *
414 * @return The update checker's current status
415 */
416 public static STATE getStatus() {
/*
P/P * Method: UpdateChecker$STATE getStatus()
*
* Preconditions:
* init'ed(status)
*
* Postconditions:
* return_value == status
* init'ed(return_value)
*/
417 return status;
418 }
419
420 /**
421 * Sets the status of the update checker to the specified new status.
422 *
423 * @param newStatus The new status of this checker
424 */
425 private static void setStatus(final STATE newStatus) {
/*
P/P * Method: void setStatus(UpdateChecker$STATE)
*
* Preconditions:
* new MapList(ListenerList#1).map != null
*
* Presumptions:
* java.util.Iterator:next(...)@428 != null
*
* Postconditions:
* status == newStatus
* init'ed(status)
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@428: {0}, {1}
*/
426 status = newStatus;
427
428 for (UpdateCheckerListener myListener : listeners.get(UpdateCheckerListener.class)) {
429 myListener.statusChanged(newStatus);
430 }
431 }
432
433 /**
434 * Checks is a specified component is enabled.
435 *
436 * @param component Update component to check state
437 *
438 * @return true iif the update component is enabled
439 */
440 public static boolean isEnabled(final UpdateComponent component) {
/*
P/P * Method: bool isEnabled(UpdateComponent)
*
* Preconditions:
* component != null
*
* Presumptions:
* com.dmdirc.config.IdentityManager:getGlobalConfig(...)@441 != null
*
* Postconditions:
* init'ed(return_value)
*/
441 return !IdentityManager.getGlobalConfig().hasOptionString("updater",
442 component.getName()) || IdentityManager.getGlobalConfig()
443 .getOptionBool("updater", component.getName());
444 }
445
446 }
SofCheck Inspector Build Version : 2.17854
| UpdateChecker.java |
2009-Jun-25 01:54:24 |
| UpdateChecker.class |
2009-Sep-02 17:04:14 |
| UpdateChecker$1.class |
2009-Sep-02 17:04:14 |
| UpdateChecker$2.class |
2009-Sep-02 17:04:14 |
| UpdateChecker$STATE.class |
2009-Sep-02 17:04:14 |