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{&amp;com.dmdirc.updater.UpdateChecker$STATE__static_init.new UpdateChecker$STATE(UpdateChecker$STATE__static_init#1), old com/dmdirc/updater/UpdateChecker.status, &amp;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, &amp;com.dmdirc.updater.UpdateChecker$STATE__static_init.new UpdateChecker$STATE(UpdateChecker$STATE__static_init#1), &amp;com.dmdirc.updater.UpdateChecker$STATE__static_init.new UpdateChecker$STATE(UpdateChecker$STATE__static_init#4), &amp;com.dmdi...
                  *    timer == One-of{old timer, &amp;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{&amp;com.dmdirc.updater.UpdateStatus__static_init.new UpdateStatus(UpdateStatus__static_init#6)}, Inverse{&amp;com.dmdirc.updater.UpdateStatus__static_init.new UpdateStatus(UpdateStatus__static_init#6)}
                  *    update.status@187: Inverse{&amp;com.dmdirc.updater.UpdateStatus__static_init.new UpdateStatus(UpdateStatus__static_init#1)}, Addr_Set{&amp;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 == &amp;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{&amp;com.dmdirc.updater.UpdateChecker$STATE__static_init.new UpdateChecker$STATE(UpdateChecker$STATE__static_init#1), old status, &amp;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, &amp;com.dmdirc.updater.UpdateChecker$STATE__static_init.new UpdateChecker$STATE(UpdateChecker$STATE__static_init#3), &amp;com.dmdirc.updater.UpdateChecker$STATE__static_init.new UpdateChecker$STATE(UpdateChecker$STATE__static_init#5), &amp;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, &amp;com.dmdirc.updater.UpdateChecker$STATE__static_init.new UpdateChecker$STATE(UpdateChecker$STATE__static_init#5), &amp;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{&amp;com.dmdirc.updater.UpdateStatus__static_init.new UpdateStatus(UpdateStatus__static_init#1),&amp;com.dmdirc.updater.UpdateStatus__static_init.new UpdateStatus(UpdateStatus__static_init#6)}, Addr_Set{&amp;com.dmdirc.updater.UpdateStatus__static_init.new UpdateStatus(UpdateStatus__static_init#1)}, Addr_Set{&amp;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 == &amp;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 == &amp;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